검증 (Validation)
Q-Framework의 검증은 선언 기반으로 동작합니다. 검증 로직을 직접 작성하지 않고, 어노테이션으로 규칙을 선언하면 프레임워크가 자동으로 처리합니다.
필수 필드
필수 규칙은 requiredOn을 통해 @QfCreateAttribute 또는 @QfUpdateAttribute 안에 선언합니다:
// 항상 필수
@QfCreateAttribute(requiredOn = @QfRequiredOn(always = true))
@QfUpdateAttribute(requiredOn = @QfRequiredOn(always = true))
@QfDisplayLabel(text = "Name")
private String name;
// 조건부 필수
@QfCreateAttribute(
requiredOn = @QfRequiredOn(
conditions = @QfConditionExpr(expr = "memberType == 'BUSINESS'")
)
)
@QfDisplayLabel(text = "Business Registration Number")
private String businessNumber;@QfRequiredOn은 @QfCreateAttribute / @QfUpdateAttribute 안에서 사용하는 요소 어노테이션(독립 사용 불가)입니다:
| 형태 | 설명 |
|---|---|
@QfRequiredOn(always = true) | 항상 필수 |
@QfRequiredOn(conditions = ...) | 조건이 일치할 때 필수 |
@QfRequiredOn (기본값) | 필수 아님 |
@QfValidationRule
@QfValidationRule은 단일 검증 어노테이션입니다. 반복 선언 가능 — 하나의 필드에 여러 규칙을 중첩할 수 있습니다.
@QfEntity(name = @QfI18n(defaultMessage = "Member", texts = {}))
public class MemberEntity {
// 로그인 ID — 커스텀 정규식 패턴
@QfListAttribute(sortable = true)
@QfCreateAttribute(requiredOn = @QfRequiredOn(always = true))
@QfValidationRule(
rule = QfValidationRule.Rule.login_id // 설정된 로그인 ID 정규식 사용
)
@QfDisplayLabel(text = "Login ID")
private String loginId;
// 이메일 — 컨트롤 타입으로 형식 선언; 암호화 적용
@QfDetailAttribute
@QfCreateAttribute
@QfCrypto
@QfControlType(QfControlType.Type.email)
@QfDisplayLabel(text = "Email")
private String email;
// 전화번호 — 커스텀 정규식
@QfDetailAttribute
@QfCreateAttribute
@QfUpdateAttribute
@QfCrypto
@QfValidationRule(
rule = QfValidationRule.Rule.regex,
params = "^(?:\\+82[-\\s]?)?(?:0?1[0-9])[-\\s]?\\d{3,4}[-\\s]?\\d{4}$",
invalidValueMessageKey = "validation.message.phone.invalid"
)
@QfDisplayLabel(text = "Phone")
private String phone;
// 비밀번호 — 설정된 비밀번호 정책 사용
@QfCreateAttribute(requiredOn = @QfRequiredOn(always = true))
@QfCrypto
@QfValidationRule(rule = QfValidationRule.Rule.user_pwd)
@QfDisplayLabel(text = "Password")
private String password;
}검증 규칙 타입
| 규칙 | 설명 | params |
|---|---|---|
Rule.regex | 커스텀 정규식 | params[0] = 패턴 문자열 |
Rule.unique | 서버 측 중복 검사 | params[0] = 검사 URL (선택) |
Rule.login_id | 로그인 ID 형식 (설정에서 가져옴) | 없음 |
Rule.user_pwd | 비밀번호 정책 (설정에서 가져옴) | 없음 |
검증 오류 메시지
메시지 키 또는 인라인 i18n 메시지를 제공할 수 있습니다:
// 메시지 키 사용 (메시지 리소스에서 조회)
@QfValidationRule(
rule = QfValidationRule.Rule.regex,
params = "^[A-Za-z0-9_]+$",
invalidValueMessageKey = "validation.message.loginId.invalid"
)
// 인라인 메시지 사용
@QfValidationRule(
rule = QfValidationRule.Rule.regex,
params = "^[A-Za-z0-9_]+$",
invalidValueMessages = @QfI18n(
defaultMessage = "Only alphanumeric and underscore allowed",
texts = { @QfI18nText(locale = "ko", message = "영문, 숫자, 밑줄(_)만 허용됩니다") }
)
)컨트롤 타입과 검증
@QfControlType은 필드의 렌더링 방식을 선언하며, 프레임워크는 이 타입을 기반으로 클라이언트 측 검증 동작을 추론합니다:
@QfControlType(QfControlType.Type.email) // 클라이언트에서 이메일 형식 검증
@QfDisplayLabel(text = "Email")
private String email;검증과 관련된 주요 컨트롤 타입:
| 타입 | 효과 |
|---|---|
email | 이메일 형식 검사 |
text | 일반 텍스트 (형식 제약 없음) |
number | 숫자 입력 |
date | 날짜 선택기 |
textarea | 여러 줄 텍스트 |
컴파일 시점 Fail-Fast
Q-Framework는 잘못된 어노테이션 조합을 컴파일 시점에 즉시 감지합니다.
암호화 + 검색 — 컴파일 오류
@QfCrypto
@QfSearch // 컴파일 오류 — 암호화 필드는 서버 측 검색 불가
private String email;ERROR: @QfCrypto와 @QfSearch는 함께 사용할 수 없습니다.
암호화된 필드는 서버 사이드 검색을 지원하지 않습니다.
→ MemberEntity.emailAI가 생성한 코드
Q-Framework의 컴파일 시점 검증은 AI가 생성한 코드에서도 동일하게 적용됩니다. AI가 잘못된 어노테이션 조합을 생성하더라도 빌드가 거부됩니다.
런타임 검증 오류 처리
검증 실패 시 Q-Framework는 표준화된 오류 응답을 반환합니다.
{
"success": false,
"code": "Q_RUNTIME_000002",
"message": "입력값 검증에 실패했습니다.",
"errors": [
{
"field": "loginId",
"message": "영문, 숫자, 밑줄(_)만 허용됩니다",
"rejectedValue": "invalid user!"
}
]
}@QfOn 훅을 이용한 커스텀 검증
어노테이션으로 표현할 수 없는 복잡한 비즈니스 규칙은 @QfOn 훅으로 처리합니다.
@QfOn(
phase = QfOnPhase.BEFORE,
layer = QfOnLayer.DOMAIN,
op = QfOnOp.CREATE
)
public void validateUniqueLoginId(/* hook parameters */) {
// 중복 아이디 검사
if (memberRepository.existsByLoginId(loginId)) {
throw new QfManagedException(MemberResultCode.DUPLICATE_LOGIN_ID);
}
}INFO
어노테이션으로 표현할 수 없는 복잡한 검증은 @QfOn 훅에서 처리합니다. 훅 안의 로직은 SSOT가 아닙니다 — 어노테이션 선언이 구조 규칙의 SSOT입니다.
다음 단계
- Capability / 권한 — 접근 제어 선언
- 엔티티 정의 — 전체 엔티티 구성