> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/pjt-prepare/framework/data-validation.md).

# Data Validation

X2BEE Framework에서 데이터 유효성 체크 방법을 설명합니다.

Bean Validation과 Custom Validator를 사용하여 유효성 체크를 구현하는 방법으로 데이터 통신에 사용되는 VO 개체나 특정 필드에 유효성 검증을 수행하는데 활용할 수 있습니다.

***

## 유효성 체크 방법

### Bean Validation

Alias 어노테이션으로 별칭 지정합니다. 데이터 통신을 VO로 함으로, jakarta.validation.constraints 패키지에서 제공하는 어노테이션을 VO 객체에 이용합니다.

{% code title="Group.java" %}

```java
package com.x2bee.api.bo.app.entity;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.apache.ibatis.type.Alias;
import com.x2bee.common.base.entity.AbstractEntity;
import lombok.Getter;
import lombok.Setter;

@Alias("group")
@Getter
@Setter
public class Group extends AbstractEntity {
    @NotNull
    String groupNo;

    @NotEmpty
    String groupName;
}
```

{% endcode %}

### @Valid 를 이용한 @RequestBody 에 대한 유효성 검증

{% code title="SampleController.java (excerpt)" %}

```java
public class SampleController {
    ...

    @PostMapping("")
    public Response<String> registerSample(@RequestBody @Valid Sample sample) throws InterruptedException {
        ...
    }

    ...
}
```

{% endcode %}

### @Validated 를 이용한 @PathVariable과 @RequestParam 에 대한 유효성 검증

{% code title="SampleController.java (excerpt)" %}

```java
@RestController
@Validated
public class SampleController {
    @GetMapping("/users/{email}")
    public String getUserInfoByEmail(@PathVariable("email") @Email String email) {
        ....
    }
}
```

{% endcode %}

## Custom Validator

jakarta.validation.constraints 패키지에서 제공되지 않는 validator를 구현하고자 하는 경우, 아래 방법으로 진행합니다.

### Custom annotation 생성

{% code title="LocaleConstraint.java" %}

```java
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;

@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = LocaleValidator.class)
@Documented
public @interface LocaleConstraint {
    String message() default "Invalid Locale";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
```

{% endcode %}

### Custom annotation을 처리할 Custom Validator 생성

{% code title="LocaleValidator.java" %}

```java
public class LocaleValidator implements ConstraintValidator<LocaleConstraint, String> {
    public static final List<String> locales = Arrays.asList("ko_KR", "en_US");

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && locales.contains(value.toLowerCase());
    }
}
```

{% endcode %}

### Custom annotation @LocaleConstraint을 적용하여 유효성 검증

{% code title="Category.java" %}

```java
package com.plateer.x2co.api.prototype.entity;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;

@Data
public class Category {
    @NotEmpty
    private String catTpCd;

    @NotBlank
    private String siteNo;

    @NotEmpty
    private String dpmlNo;

    @NotEmpty
    @LocaleConstraint // 다음과 같이 어노테이션으로 적용
    private String dbLocaleLanguage;

    @NotEmpty
    private int maxLvl = 0;

    @NotEmpty
    private int minLvl = 0;
}
```

{% endcode %}
