Skip to content

응답 & 로깅

모든 API 응답은 ApiResponse<T> 제네릭 DTO로 감싸서 반환합니다. HTTP 상태 코드는 항상 200이며, 실제 상태는 응답 바디의 status 필드에 담깁니다.

{
"status": 200,
"code": null,
"message": "성공 메시지",
"data": { ... }
}
필드타입설명
statusint실제 HTTP 상태 코드 (200, 201, 400, 401, 404, 500 등)
codeString에러 코드 식별자 (성공 시 null)
messageString사람이 읽을 수 있는 메시지
dataT응답 데이터 (에러 시 null 가능)
ApiResponse.success(message, data) // status: 200
ApiResponse.created(message, data) // status: 201
ApiResponse.error(status, code, message) // 에러 (data 없음)
ApiResponse.errorWithData(status, code, message, data) // 에러 + 추가 데이터

컨트롤러는 ResponseEntity<ApiResponse<T>>를 반환합니다.


GlobalExceptionHandler (@RestControllerAdvice)가 모든 예외를 잡아서 ApiResponse 형태로 변환합니다.

예외 타입로깅 레벨
MethodArgumentNotValidException (유효성 검증)INFO
IllegalArgumentExceptionWARN
CustomException (비즈니스 로직)조건부
ImwebOAuthExceptionWARN
DataAccessException (DB 에러)ERROR
NoResourceFoundException (404)DEBUG
Exception (기타)ERROR

비즈니스 로직 예외의 기본 타입입니다. 도메인별 예외 Enum과 함께 사용합니다.

throw new CustomException(CrawlingExceptionEnum.INVALID_BUSINESS_USER);
Enum용도
ApiExceptionEnum인증/보안 에러
CrawlingExceptionEnum크롤링/데이터 에러
PayExceptionEnum결제 에러
CandyPaymentsExceptionEnumCandyPay 에러
BudgetExceptionEnum캠페인 예산 에러
FileExceptionEnum파일 업로드 에러
AppiliateExceptionEnum제휴 상품 에러
ImwebExceptionEnumImweb OAuth 에러

SLF4J + Logback 조합을 사용합니다.

MDC(Mapped Diagnostic Context) 기반의 구조화된 로그를 출력합니다.

2025-01-15 14:30:00.123 [http-nio-8081-exec-1] INFO c.a.g.controller.CollabController -
traceId=abc123 spanId=def456 userId=user01 userRole=ROLE_BUSINESS
clientIp=192.168.1.1 - [API_REQUEST] GET /ai/collab
필드설명설정 주체
traceIdOpenTelemetry 트레이스 ID (32자리 hex)OTel 자동
spanIdOpenTelemetry 스팬 ID (16자리 hex)OTel 자동
userId인증된 사용자 IDMdcLoggingFilter
userRole사용자 역할MdcLoggingFilter
clientIp클라이언트 IP (프록시 고려)MdcLoggingFilter
JwtAuthFilter (인증)
MdcLoggingFilter (MDC 세팅: userId, userRole, clientIp)
Spring Security Filters
Controller

MdcLoggingFilterJwtAuthFilter 이후에 실행되어, 인증된 사용자 정보를 MDC에 넣습니다. 요청 완료 후 MDC를 정리하여 스레드풀 메모리 누수를 방지합니다.

비즈니스 코드에 로깅 코드를 넣지 않고, AOP Aspect로 분리합니다.

@RestController, @Controller 메서드를 대상으로 요청/응답을 로깅합니다.

로그 태그설명
[API_REQUEST]요청 수신 (메서드, URI, 파라미터)
[API_RESPONSE]정상 응답 (소요 시간, 상태)
[API_RESPONSE] [SLOW]느린 응답 (500ms 초과)
[API_RESPONSE] [ERROR]에러 응답

주요 기능:

  • 민감 데이터 마스킹: 비밀번호, 토큰, 카드번호, 주민번호, 전화번호 자동 마스킹
  • 요청 바디 로깅: 2000자 제한으로 truncate
  • 느린 요청 감지: 500ms 임계값
  • 트래픽 샘플링: 설정 가능한 비율 (기본: 비활성화, 활성화 시 50%)
  • 항상 로깅 경로: 결제(/payments), 인증(/auth), 주문(/order) 관련
  • 스킵 경로: /health, /actuator, /ai/token, /ai/refresh
  • Micrometer 메트릭: api.request.duration, api.errors.total

@LogExecutionTime 어노테이션이 붙은 메서드와 Repository 메서드의 실행 시간을 로깅합니다.

레벨조건
DEBUG정상 실행
WARN느린 실행 (기본 200ms 초과, 어노테이션으로 커스텀 가능)
ERROR실행 실패

Service/Controller 레이어에서 발생하는 CustomException의 컨텍스트를 로깅합니다.

  • 파라미터 로깅 (100자 제한)
  • 민감 파라미터 마스킹 (password, token, secret, key, credential)
  • 스택 트레이스 (DEBUG 레벨, 20줄 제한)
어노테이션용도
@LogExecutionTime메서드 실행 시간 로깅 (slowThresholdMs, operation 설정 가능)
@NoLogging로깅 제외 (헬스체크, 유틸리티 등)
Appender설명
CONSOLE실시간 콘솔 출력
ASYNC_FILE비동기 롤링 파일 (100MB/파일, 30일 보존, 최대 10GB)
ASYNC_OTLPOpenTelemetry OTLP HTTP (Grafana LGTM 스택 연동)
SENTRY에러 트래킹 (WARN 이상)레거시, 현재 미사용
환경Appender
localCONSOLE
devCONSOLE + ASYNC_FILE + ASYNC_OTLP
staging-saasCONSOLE + ASYNC_FILE + ASYNC_OTLP
prodCONSOLE + ASYNC_FILE + ASYNC_OTLP
  • OpenTelemetry: http://localhost:4318 (Grafana LGTM 스택)으로 트레이스/로그 내보내기
  • Sentry: 레거시, 현재 미사용
  • Micrometer: API 요청 시간, 에러 수 메트릭 수집