You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
핵심 문제: GlobalExceptionHandler가 처리하는 예외 타입을 확장하여, 다양한 오류 상황에 대해 더 정확한 HTTP 상태 코드와 메시지를 반환하도록 개선합니다. [Issue #186]
주요 변경 사항:
DataIntegrityViolationException 발생 시 409 Conflict 응답을 반환하도록 처리합니다.
AccessDeniedException 발생 시 403 Forbidden 응답을 반환하도록 처리합니다.
NoResourceFoundException 발생 시 404 Not Found 응답을 반환하도록 처리합니다.
MissingRequestHeaderException 발생 시 400 Bad Request 응답을 반환하도록 처리합니다.
MethodArgumentTypeMismatchException 발생 시 400 Bad Request 응답을 반환하도록 처리합니다.
4xx 계열 예외 발생 시 로그 레벨을 WARN으로 설정하여 불필요한 ERROR 로그를 줄였습니다.
주요 변경 파일:
이 PR의 핵심 비즈니스 로직은 src/main/java/com/Rootin/global/exception/GlobalExceptionHandler.java 파일에 집중되어 있습니다. 이 파일에서 새로운 예외 타입에 대한 핸들러 메서드가 추가되었습니다.
백엔드 API 변경 사항:
기존에는 위 예외들이 발생했을 때 일괄적으로 500 Internal Server Error를 반환했지만, 이제는 각 예외 상황에 맞는 HTTP 상태 코드(400, 403, 404, 409)를 반환합니다.
응답 형식은 ApiResponse<Void>로 동일하며, body 내 message 필드에 각 예외에 대한 구체적인 오류 메시지가 포함됩니다.
DataIntegrityViolationException: "이미 처리된 요청이거나 데이터 제약 조건에 위배됩니다."
그 외 예외: ErrorCode에 정의된 메시지 또는 "잘못된 입력입니다."
데이터베이스 스키마 변경:
이 PR에는 데이터베이스 스키마 변경, 인덱스 추가 또는 마이그레이션 스크립트가 포함되어 있지 않습니다.
테스트 시나리오:
리뷰어나 QA 팀은 다음 시나리오를 통해 변경 사항을 검증할 수 있습니다.
409 Conflict (DataIntegrityViolationException):
고유 제약 조건이 있는 필드(예: 사용자 ID, 이메일)에 이미 존재하는 값으로 데이터를 삽입/업데이트를 시도하여 DB 제약 위반을 발생시킵니다.
예시: 동일한 이메일로 회원가입을 두 번 시도합니다.
예상 결과: HTTP 409 Conflict 응답과 "이미 처리된 요청이거나 데이터 제약 조건에 위배됩니다." 메시지를 받습니다.
403 Forbidden (AccessDeniedException):
권한이 없는 리소스에 접근을 시도합니다. (예: 다른 사용자의 개인 정보 조회, 관리자 권한이 필요한 기능 접근)
예상 결과: HTTP 403 Forbidden 응답과 ErrorCode.FORBIDDEN 메시지를 받습니다.
404 Not Found (NoResourceFoundException):
존재하지 않는 API 엔드포인트로 요청을 보냅니다.
예상 결과: HTTP 404 Not Found 응답과 ErrorCode.NOT_FOUND 메시지를 받습니다.
400 Bad Request (MissingRequestHeaderException):
@RequestHeader로 필수 지정된 헤더(예: Authorization)를 누락한 채 요청을 보냅니다.
예상 결과: HTTP 400 Bad Request 응답과 "필수 헤더가 누락되었습니다: [누락된 헤더 이름]" 메시지를 받습니다.
400 Bad Request (MethodArgumentTypeMismatchException):
API 파라미터의 타입이 맞지 않는 값을 전달합니다. (예: Long 타입이 필요한 곳에 문자열 전달)
예상 결과: HTTP 400 Bad Request 응답과 ErrorCode.INVALID_INPUT 메시지를 받습니다.
로그 확인: 각 예외 발생 시 서버 로그에 log.warn 레벨로 해당 예외 메시지가 기록되는지 확인합니다.
의존성 및 환경 설정 변경:
새로운 외부 의존성 패키지가 추가되거나 삭제되지 않았습니다.
Docker 설정 및 환경 변수(.env) 설정 변경은 없습니다.
스프링 프레임워크 내장 예외 클래스(org.springframework.dao.DataIntegrityViolationException, org.springframework.security.access.AccessDeniedException 등)에 대한 import만 추가되었습니다.
잠재적 영향도:
API 견고성 향상: 클라이언트에게 더욱 명확하고 구체적인 오류 정보를 제공하여 API 사용성을 높입니다.
클라이언트 개발 용이성: 프론트엔드 개발자가 특정 오류 상황에 따라 적절한 UI/UX를 구현하기 용이해집니다.
로그 가독성 개선: 4xx 계열 오류에 대한 로그 레벨을 WARN으로 조정하여, 심각한 시스템 오류(ERROR)와 클라이언트 요청 오류를 명확히 구분할 수 있게 되어 모니터링 및 디버깅 효율성이 향상됩니다.
보안 강화: AccessDeniedException에 대한 명확한 403 응답은 권한 없는 접근 시도를 명확히 인지하고 대응하는 데 도움을 줍니다.
Diagram Walkthrough
flowchart LR
A[클라이언트 요청] --> B{예외 발생};
B -- DataIntegrityViolationException --> C[GlobalExceptionHandler];
B -- AccessDeniedException --> C;
B -- NoResourceFoundException --> C;
B -- MissingRequestHeaderException --> C;
B -- MethodArgumentTypeMismatchException --> C;
C -- 처리 --> D{정확한 HTTP 응답};
D -- 409 Conflict --> E1[데이터 제약 위반];
D -- 403 Forbidden --> E2[접근 거부];
D -- 404 Not Found --> E3[리소스 없음];
D -- 400 Bad Request --> E4[잘못된 요청];
DataIntegrityViolationException (64-70 라인) 발생 시 반환되는 메시지 "이미 처리된 요청이거나 데이터 제약 조건에 위배됩니다."는 다소 일반적입니다. 특정 제약 조건 위반(예: 고유 제약 조건, 외래 키 제약 조건)에 따라 더 구체적인 메시지를 제공할 수 있다면 사용자에게 더 유용한 정보를 줄 수 있습니다. 현재 구현도 유효하지만, 향후 개선을 고려해볼 수 있습니다.
@ExceptionHandler(DataIntegrityViolationException.class)
publicResponseEntity<ApiResponse<Void>> handleDataIntegrityViolation(DataIntegrityViolationExceptione) {
log.warn("DataIntegrityViolationException: {}", e.getMessage());
returnResponseEntity
.status(HttpStatus.CONFLICT)
.body(ApiResponse.error("이미 처리된 요청이거나 데이터 제약 조건에 위배됩니다."));
}
MissingRequestHeaderException 및 DataIntegrityViolationException 핸들러에서 사용되는 에러 메시지가 하드코딩되어 있습니다. ErrorCode enum에 해당 메시지를 정의하고 활용하면, 모든 에러 메시지를 중앙에서 관리하여 일관성을 확보하고 향후 다국어 지원 등 확장성을 높일 수 있습니다.
Why: Centralizing error messages in an ErrorCode enum, as suggested, is a good practice for consistency, maintainability, and future internationalization. It prevents hardcoding error messages directly in the handlers.
Medium
동일 응답 예외 핸들러 통합
MethodArgumentTypeMismatchException 핸들러는 HttpMessageNotReadableException 핸들러와 동일하게 HttpStatus.BAD_REQUEST와 ErrorCode.INVALID_INPUT 메시지를 반환합니다. 이처럼 동일한 응답을 반환하는 여러 예외를 하나의 @ExceptionHandler 메서드에서 처리하여 코드 중복을 줄이고 유지보수성을 높일 수 있습니다.
Why: The suggestion correctly identifies that MethodArgumentTypeMismatchException and HttpMessageNotReadableException handlers return identical responses. Consolidating them into a single handler reduces code duplication and improves maintainability.
MissingRequestHeaderException과 DataIntegrityViolationException 핸들러만 메시지가 하드코딩되어 있고 나머지는 ErrorCode를 씁니다. 지금 당장 블로커는 아니지만 일관성을 위해 ErrorCode로 통일하는 걸 고려해주세요.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
🔎 What
🔗 Issue
✅ 체크리스트
PR Type
Enhancement
Description
핵심 문제: GlobalExceptionHandler가 처리하는 예외 타입을 확장하여, 다양한 오류 상황에 대해 더 정확한 HTTP 상태 코드와 메시지를 반환하도록 개선합니다. [Issue #186]
주요 변경 사항:
DataIntegrityViolationException발생 시 409 Conflict 응답을 반환하도록 처리합니다.AccessDeniedException발생 시 403 Forbidden 응답을 반환하도록 처리합니다.NoResourceFoundException발생 시 404 Not Found 응답을 반환하도록 처리합니다.MissingRequestHeaderException발생 시 400 Bad Request 응답을 반환하도록 처리합니다.MethodArgumentTypeMismatchException발생 시 400 Bad Request 응답을 반환하도록 처리합니다.4xx 계열 예외 발생 시 로그 레벨을
WARN으로 설정하여 불필요한ERROR로그를 줄였습니다.주요 변경 파일:
이 PR의 핵심 비즈니스 로직은
src/main/java/com/Rootin/global/exception/GlobalExceptionHandler.java파일에 집중되어 있습니다. 이 파일에서 새로운 예외 타입에 대한 핸들러 메서드가 추가되었습니다.백엔드 API 변경 사항:
기존에는 위 예외들이 발생했을 때 일괄적으로 500 Internal Server Error를 반환했지만, 이제는 각 예외 상황에 맞는 HTTP 상태 코드(400, 403, 404, 409)를 반환합니다.
응답 형식은
ApiResponse<Void>로 동일하며,body내message필드에 각 예외에 대한 구체적인 오류 메시지가 포함됩니다.MissingRequestHeaderException: "필수 헤더가 누락되었습니다: [헤더 이름]"DataIntegrityViolationException: "이미 처리된 요청이거나 데이터 제약 조건에 위배됩니다."ErrorCode에 정의된 메시지 또는 "잘못된 입력입니다."데이터베이스 스키마 변경:
테스트 시나리오:
리뷰어나 QA 팀은 다음 시나리오를 통해 변경 사항을 검증할 수 있습니다.
409 Conflict (
DataIntegrityViolationException):403 Forbidden (
AccessDeniedException):ErrorCode.FORBIDDEN메시지를 받습니다.404 Not Found (
NoResourceFoundException):ErrorCode.NOT_FOUND메시지를 받습니다.400 Bad Request (
MissingRequestHeaderException):@RequestHeader로 필수 지정된 헤더(예:Authorization)를 누락한 채 요청을 보냅니다.400 Bad Request (
MethodArgumentTypeMismatchException):Long타입이 필요한 곳에 문자열 전달)ErrorCode.INVALID_INPUT메시지를 받습니다.로그 확인: 각 예외 발생 시 서버 로그에
log.warn레벨로 해당 예외 메시지가 기록되는지 확인합니다.의존성 및 환경 설정 변경:
새로운 외부 의존성 패키지가 추가되거나 삭제되지 않았습니다.
Docker 설정 및 환경 변수(.env) 설정 변경은 없습니다.
스프링 프레임워크 내장 예외 클래스(
org.springframework.dao.DataIntegrityViolationException,org.springframework.security.access.AccessDeniedException등)에 대한 import만 추가되었습니다.잠재적 영향도:
API 견고성 향상: 클라이언트에게 더욱 명확하고 구체적인 오류 정보를 제공하여 API 사용성을 높입니다.
클라이언트 개발 용이성: 프론트엔드 개발자가 특정 오류 상황에 따라 적절한 UI/UX를 구현하기 용이해집니다.
로그 가독성 개선: 4xx 계열 오류에 대한 로그 레벨을
WARN으로 조정하여, 심각한 시스템 오류(ERROR)와 클라이언트 요청 오류를 명확히 구분할 수 있게 되어 모니터링 및 디버깅 효율성이 향상됩니다.보안 강화:
AccessDeniedException에 대한 명확한 403 응답은 권한 없는 접근 시도를 명확히 인지하고 대응하는 데 도움을 줍니다.Diagram Walkthrough
flowchart LR A[클라이언트 요청] --> B{예외 발생}; B -- DataIntegrityViolationException --> C[GlobalExceptionHandler]; B -- AccessDeniedException --> C; B -- NoResourceFoundException --> C; B -- MissingRequestHeaderException --> C; B -- MethodArgumentTypeMismatchException --> C; C -- 처리 --> D{정확한 HTTP 응답}; D -- 409 Conflict --> E1[데이터 제약 위반]; D -- 403 Forbidden --> E2[접근 거부]; D -- 404 Not Found --> E3[리소스 없음]; D -- 400 Bad Request --> E4[잘못된 요청];File Walkthrough
GlobalExceptionHandler.java
글로벌 예외 핸들러에 5가지 예외 타입 추가 및 로깅 개선src/main/java/com/Rootin/global/exception/GlobalExceptionHandler.java
DataIntegrityViolationException을HttpStatus.CONFLICT(409)로 처리하는 핸들러추가
AccessDeniedException을HttpStatus.FORBIDDEN(403)으로 처리하는 핸들러 추가NoResourceFoundException을HttpStatus.NOT_FOUND(404)로 처리하는 핸들러 추가MissingRequestHeaderException을HttpStatus.BAD_REQUEST(400)로 처리하는 핸들러추가
MethodArgumentTypeMismatchException을HttpStatus.BAD_REQUEST(400)로처리하는 핸들러 추가
log.warn레벨로 로깅하도록 변경