From f3534ca371df1badce1aad37d6afdd2f8978f459 Mon Sep 17 00:00:00 2001 From: lsh9672 Date: Thu, 12 Jun 2025 15:17:45 +0900 Subject: [PATCH] =?UTF-8?q?Fix=20:=20common=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ktds/hi/common/dto/ErrorResponse.java | 229 ++++++++++++++++++ .../ktds/hi/common/response/ResponseCode.java | 25 +- 2 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 common/src/main/java/com/ktds/hi/common/dto/ErrorResponse.java diff --git a/common/src/main/java/com/ktds/hi/common/dto/ErrorResponse.java b/common/src/main/java/com/ktds/hi/common/dto/ErrorResponse.java new file mode 100644 index 0000000..7dd8bcb --- /dev/null +++ b/common/src/main/java/com/ktds/hi/common/dto/ErrorResponse.java @@ -0,0 +1,229 @@ +package com.ktds.hi.common.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ktds.hi.common.response.ResponseCode; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 에러 응답 DTO 클래스 (제네릭 지원) + * 에러 메시지와 상세 데이터를 반환할 때 사용 + * 기존 코드와의 호환성을 유지하면서 제네릭 타입 지원 + */ +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ErrorResponse { + + private boolean success; + private String code; + private String message; + private String path; + private T data; + private List validationErrors; + private LocalDateTime timestamp; + + /** + * Validation 에러 정보 + */ + @Getter + @Builder + @NoArgsConstructor + @AllArgsConstructor + @JsonInclude(JsonInclude.Include.NON_NULL) + public static class ValidationError { + private String field; + private Object rejectedValue; + private String message; + } + + /** + * 에러 응답 생성 (에러 코드, 메시지, 경로, 상세 데이터 포함) + */ + public static ErrorResponse of(String code, String message, String path, T data) { + return ErrorResponse.builder() + .success(false) + .code(code) + .message(message) + .path(path) + .data(data) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 에러 응답 생성 (에러 코드, 메시지, 경로 포함) + */ + public static ErrorResponse of(String code, String message, String path) { + return ErrorResponse.builder() + .success(false) + .code(code) + .message(message) + .path(path) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 에러 응답 생성 (에러 코드, 메시지만 포함) - 기존 호환성 유지 + */ + public static ErrorResponse of(String code, String message) { + return ErrorResponse.builder() + .success(false) + .code(code) + .message(message) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * Validation 에러 응답 생성 + */ + public static ErrorResponse ofValidation(String message, List validationErrors) { + return ErrorResponse.builder() + .success(false) + .code("VALIDATION_ERROR") + .message(message) + .validationErrors(validationErrors) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * Validation 에러 응답 생성 (경로 포함) + */ + public static ErrorResponse ofValidation(String message, String path, List validationErrors) { + return ErrorResponse.builder() + .success(false) + .code("VALIDATION_ERROR") + .message(message) + .path(path) + .validationErrors(validationErrors) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * ResponseCode를 사용한 에러 응답 생성 + */ + public static ErrorResponse ofResponseCode(ResponseCode responseCode, String path) { + return ErrorResponse.builder() + .success(false) + .code(responseCode.getCode()) + .message(responseCode.getMessage()) + .path(path) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 비즈니스 예외를 위한 에러 응답 생성 + */ + public static ErrorResponse ofBusinessException(String code, String message) { + return ErrorResponse.builder() + .success(false) + .code(code != null ? code : "BUSINESS_ERROR") + .message(message) + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 내부 서버 에러 응답 생성 + */ + public static ErrorResponse ofInternalError(String message) { + return ErrorResponse.builder() + .success(false) + .code("INTERNAL_SERVER_ERROR") + .message(message != null ? message : "내부 서버 오류가 발생했습니다.") + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 인증 에러 응답 생성 + */ + public static ErrorResponse ofUnauthorized(String message) { + return ErrorResponse.builder() + .success(false) + .code("UNAUTHORIZED") + .message(message != null ? message : "인증이 필요합니다.") + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 권한 에러 응답 생성 + */ + public static ErrorResponse ofForbidden(String message) { + return ErrorResponse.builder() + .success(false) + .code("FORBIDDEN") + .message(message != null ? message : "접근 권한이 없습니다.") + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 리소스 찾을 수 없음 에러 응답 생성 + */ + public static ErrorResponse ofNotFound(String message) { + return ErrorResponse.builder() + .success(false) + .code("NOT_FOUND") + .message(message != null ? message : "요청한 리소스를 찾을 수 없습니다.") + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 잘못된 요청 에러 응답 생성 + */ + public static ErrorResponse ofBadRequest(String message) { + return ErrorResponse.builder() + .success(false) + .code("BAD_REQUEST") + .message(message != null ? message : "잘못된 요청입니다.") + .timestamp(LocalDateTime.now()) + .build(); + } + + /** + * 생성자 (메시지만) - 기존 호환성 유지 + */ + public ErrorResponse(String message) { + this.success = false; + this.code = "ERROR"; + this.message = message; + this.timestamp = LocalDateTime.now(); + } + + /** + * 생성자 (코드와 메시지) - 기존 호환성 유지 + */ + public ErrorResponse(String code, String message) { + this.success = false; + this.code = code; + this.message = message; + this.timestamp = LocalDateTime.now(); + } + + /** + * 생성자 (코드, 메시지, 데이터) + */ + public ErrorResponse(String code, String message, T data) { + this.success = false; + this.code = code; + this.message = message; + this.data = data; + this.timestamp = LocalDateTime.now(); + } +} \ No newline at end of file diff --git a/common/src/main/java/com/ktds/hi/common/response/ResponseCode.java b/common/src/main/java/com/ktds/hi/common/response/ResponseCode.java index d57cbe2..62114da 100644 --- a/common/src/main/java/com/ktds/hi/common/response/ResponseCode.java +++ b/common/src/main/java/com/ktds/hi/common/response/ResponseCode.java @@ -50,7 +50,30 @@ public enum ResponseCode { // 외부 서비스 오류 SMS_SEND_ERROR("3001", "SMS 전송 실패"), EMAIL_SEND_ERROR("3002", "이메일 전송 실패"), - EXTERNAL_API_ERROR("3003", "외부 API 호출 실패"); + EXTERNAL_API_ERROR("3003", "외부 API 호출 실패"), + + // 인증인가 관련 + INSUFFICIENT_PRIVILEGES("INSUFFICIENT_PRIVILEGES", "권한 부족"), + + // 리소스 관련 + RESOURCE_NOT_FOUND("RESOURCE_NOT_FOUND", "리소스를 찾을 수 없음"), + RESOURCE_ALREADY_EXISTS("RESOURCE_ALREADY_EXISTS", "리소스가 이미 존재함"), + RESOURCE_LOCKED("RESOURCE_LOCKED", "리소스가 잠겨있음"), + + // 파일 처리 관련 + FILE_TOO_LARGE("FILE_TOO_LARGE", "파일 크기가 너무 큼"), + UNSUPPORTED_FILE_TYPE("UNSUPPORTED_FILE_TYPE", "지원하지 않는 파일 형식"), + FILE_UPLOAD_FAILED("FILE_UPLOAD_FAILED", "파일 업로드 실패"), + + // 결제 관련 + PAYMENT_FAILED("PAYMENT_FAILED", "결제 실패"), + INSUFFICIENT_BALANCE("INSUFFICIENT_BALANCE", "잔액 부족"), + PAYMENT_CANCELLED("PAYMENT_CANCELLED", "결제 취소됨"), + + // AI 분석 관련 + AI_ANALYSIS_FAILED("AI_ANALYSIS_FAILED", "AI 분석 실패"), + AI_SERVICE_UNAVAILABLE("AI_SERVICE_UNAVAILABLE", "AI 서비스 이용 불가"), + ANALYSIS_IN_PROGRESS("ANALYSIS_IN_PROGRESS", "분석 진행 중"); private final String code; private final String message;