결과 코드
Q-Framework의 결과 코드는 선언 기반 계약입니다. 응답 코드가 어노테이션으로 선언되며, 컴파일 시점에 타입 안전한 상수가 자동 생성됩니다.
결과 코드 계약 설명
전통적인 방식에서는 결과 코드가 여러 곳에 분산됩니다:
java
// 문제: 문자열 하드코딩 — 중복 정의, 오타 위험
if (result.getCode().equals("PRODUCT_NOT_FOUND")) { ... }
// 문제: 상수 파일 관리 — 중앙화되지 않음
public static final String PRODUCT_NOT_FOUND = "PRODUCT_NOT_FOUND";Q-Framework에서는 결과 코드가 SSOT로 선언됩니다:
java
// SSOT: 어노테이션으로 선언
@QfResultCode(code = "PRODUCT_NOT_FOUND", httpStatus = 404, ...)
// → 컴파일 시점에 타입 안전한 상수 자동 생성
// → API 문서에 자동 포함
// → 프론트엔드 i18n과 자동 연동@QfResultCode 어노테이션 속성
java
@QfResultCode(
code = "PRODUCT_NOT_FOUND", // 결과 코드 문자열
httpStatus = 404, // HTTP 상태 코드
message = "상품을 찾을 수 없습니다.", // 기본 메시지
i18n = @QfI18n( // 다국어 메시지
ko = "상품을 찾을 수 없습니다.",
en = "Product not found"
)
)| 속성 | 타입 | 필수 | 설명 | 기본값 |
|---|---|---|---|---|
code | String | ✅ | 결과 코드 식별자 | — |
httpStatus | int | ✅ | HTTP 상태 코드 | — |
message | String | 기본 메시지 | "" | |
i18n | @QfI18n | 다국어 메시지 | — |
코드 형식 규칙
결과 코드는 다음 형식을 따릅니다:
{DOMAIN}_{ACTION}_{STATUS}
↓ ↓ ↓
PRODUCT _ NOT_FOUND (없음)
MEMBER _ CREATE _ FAILED
ORDER _ PAYMENT _ TIMEOUT규칙:
- 대문자만 사용
- 단어 구분은 언더스코어(
_) - 도메인 접두사 필수
예시:
PRODUCT_NOT_FOUNDMEMBER_DUPLICATE_LOGIN_IDORDER_PAYMENT_TIMEOUTVALIDATION_FAILED(시스템 공통)UNAUTHORIZED(시스템 공통)
결과 코드 정의 방법
도메인별 인터페이스 선언
java
// ProductResultCode.java
@QfResultCodeGroup(domain = "PRODUCT")
public interface ProductResultCode {
@QfResultCode(
code = "PRODUCT_NOT_FOUND",
httpStatus = 404,
i18n = @QfI18n(
ko = "상품을 찾을 수 없습니다.",
en = "Product not found"
)
)
String NOT_FOUND = "PRODUCT_NOT_FOUND";
@QfResultCode(
code = "PRODUCT_OUT_OF_STOCK",
httpStatus = 409,
i18n = @QfI18n(
ko = "품절된 상품입니다.",
en = "Product is out of stock"
)
)
String OUT_OF_STOCK = "PRODUCT_OUT_OF_STOCK";
@QfResultCode(
code = "PRODUCT_CREATE_FAILED",
httpStatus = 500,
i18n = @QfI18n(
ko = "상품 등록에 실패했습니다.",
en = "Failed to create product"
)
)
String CREATE_FAILED = "PRODUCT_CREATE_FAILED";
}자동 생성 코드 예시
컴파일 시점에 타입 안전한 상수 클래스가 생성됩니다.
생성 전 (선언):
java
@QfResultCode(code = "PRODUCT_NOT_FOUND", httpStatus = 404, ...)
String NOT_FOUND = "PRODUCT_NOT_FOUND";생성 후 (자동 생성 코드):
java
// 자동 생성 - 수동 수정 금지
public final class QfProductResultCodes {
public static final QfResultCodeDef NOT_FOUND =
new QfResultCodeDef("PRODUCT_NOT_FOUND", 404, "상품을 찾을 수 없습니다.");
public static final QfResultCodeDef OUT_OF_STOCK =
new QfResultCodeDef("PRODUCT_OUT_OF_STOCK", 409, "품절된 상품입니다.");
private QfProductResultCodes() {}
}사용 방법
java
@QfOn(entity = ProductEntity.class, event = QfEvent.BEFORE_READ)
public class ProductReadHook implements QfHook<ProductEntity> {
@Override
public void execute(QfHookContext<ProductEntity> context) {
String id = context.getId();
if (!productRepository.existsById(id)) {
// 타입 안전한 결과 코드 사용
throw new QfManagedException(QfProductResultCodes.NOT_FOUND);
}
}
}표준 응답 구조
json
{
"success": false,
"code": "PRODUCT_NOT_FOUND",
"message": "상품을 찾을 수 없습니다.",
"data": null
}성공 응답:
json
{
"success": true,
"code": "SUCCESS",
"data": {
"id": "prod-001",
"name": "노트북",
"price": 1500000
}
}시스템 기본 결과 코드
Q-Framework가 기본으로 제공하는 결과 코드입니다.
| 코드 | HTTP 상태 | 설명 |
|---|---|---|
SUCCESS | 200 | 정상 처리 |
VALIDATION_FAILED | 400 | 입력값 검증 실패 |
UNAUTHORIZED | 401 | 인증 필요 |
FORBIDDEN | 403 | 권한 없음 |
NOT_FOUND | 404 | 리소스 없음 |
CONFLICT | 409 | 중복 등록 등 충돌 |
INTERNAL_SERVER_ERROR | 500 | 서버 내부 오류 |
RUNTIME_NOT_INITIALIZED | 503 | 런타임 초기화 실패 |
다음 단계
- 어노테이션 레퍼런스 — 전체 어노테이션 목록
- SPI 확장 — 결과 코드 처리 커스터마이징