6.1 애플리케이션 시작 시
┌─────────────────────────────────────────┐
│ Spring Boot 애플리케이션 시작 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ spring.factories 스캔 │
│ → LoggerAutoConfiguration 발견 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Bean 생성 │
│ ├─ ObjectMapper │
│ ├─ AsyncExecutor │
│ ├─ TraceIdFilter (Filter 등록) │
│ ├─ MethodLoggingAspect (AOP 등록) │
│ ├─ DatabaseDetector │
│ ├─ DependencyLogSender │
│ └─ DependencyCollector │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 모든 Bean 생성 완료 │
│ 의존성 주입 완료 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ ApplicationReadyEvent 발생 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ DependencyCollector.collectDependencies()│
│ │
│ 1. Controller 수집 │
│ ├─ @RestController Bean 찾기 │
│ └─ 생성자 분석 → 의존성 추출 │
│ │
│ 2. Service 수집 │
│ ├─ @Service Bean 찾기 │
│ └─ 생성자 분석 → 의존성 추출 │
│ │
│ 3. Repository 수집 │
│ ├─ Interface-based (JPA) │
│ │ └─ Spring Data Repository 찾기 │
│ └─ Class-based (@Repository) │
│ └─ 생성자 분석 → 의존성 추출 │
│ │
│ 4. Database 감지 │
│ ├─ spring.datasource.url 파싱 │
│ ├─ NoSQL 설정 확인 │
│ └─ DB 타입 리스트 생성 │
│ │
│ 5. 데이터 전송 │
│ ├─ [1단계] 컴포넌트 전송 │
│ └─ [2단계] 의존성 관계 전송 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 애플리케이션 준비 완료 │
│ 요청 처리 가능 │
└─────────────────────────────────────────┘6.2 런타임: HTTP 요청 처리
┌─────────────────────────────────────────┐
│ HTTP 요청 도착 │
│ GET /api/users/123 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ TraceIdFilter.doFilter() │
│ │
│ 1. 헤더에서 X-Trace-Id 확인 │
│ └─ 없으면 UUID 생성 │
│ │
│ 2. Client IP 추출 │
│ ├─ X-Forwarded-For 우선 │
│ └─ 없으면 RemoteAddr 사용 │
│ │
│ 3. MDC에 저장 │
│ ├─ MDC.put("traceId", ...) │
│ └─ MDC.put("client_ip", ...) │
│ │
│ 4. 응답 헤더 추가 │
│ └─ X-Trace-Id: a1b2c3d4-... │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ DispatcherServlet │
│ → UserController.getUser(123) 호출 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ MethodLoggingAspect (Before) │
│ │
│ 1. 메서드 정보 수집 │
│ ├─ Class: UserController │
│ ├─ Method: getUser │
│ ├─ Layer: CONTROLLER │
│ └─ Parameters: {userId: 123} │
│ │
│ 2. HTTP 정보 추출 │
│ ├─ Method: GET │
│ ├─ URI: /api/users/123 │
│ └─ QueryString: null │
│ │
│ 3. Request 로그 출력 │
│ { │
│ "trace_id": "a1b2c3d4-...", │
│ "component_name": "UserController",│
│ "layer": "CONTROLLER", │
│ "message": "Request received: getUser",│
│ "request": { │
│ "http": {...}, │
│ "parameters": {userId: 123} │
│ } │
│ } │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ UserController.getUser(123) 실행 │
│ → UserService.findById(123) 호출 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ MethodLoggingAspect (Before) │
│ │
│ 1. 메서드 정보 수집 │
│ ├─ Class: UserService │
│ ├─ Method: findById │
│ ├─ Layer: SERVICE │
│ └─ Parameters: {userId: 123} │
│ │
│ 2. HTTP 정보 추출 │
│ └─ null (Service 계층) │
│ │
│ 3. Request 로그 출력 │
│ { │
│ "trace_id": "a1b2c3d4-...", │
│ "component_name": "UserService", │
│ "layer": "SERVICE", │
│ "message": "Request received: findById",│
│ "request": { │
│ "parameters": {userId: 123} │
│ } │
│ } │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ UserService.findById(123) 실행 │
│ → UserRepository.findById(123) 호출 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ MethodLoggingAspect (Before) │
│ │
│ 1. 메서드 정보 수집 │
│ ├─ Class: UserRepository (프록시) │
│ ├─ 실제 인터페이스: UserRepository │
│ ├─ Method: findById │
│ ├─ Layer: REPOSITORY │
│ └─ Parameters: {id: 123} │
│ │
│ 2. HTTP 정보 추출 │
│ └─ null (Repository 계층) │
│ │
│ 3. Request 로그 출력 │
│ { │
│ "trace_id": "a1b2c3d4-...", │
│ "component_name": "UserRepository",│
│ "layer": "REPOSITORY", │
│ "message": "Request received: findById",│
│ "request": { │
│ "parameters": {id: 123} │
│ } │
│ } │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ UserRepository.findById(123) 실행 │
│ → DB 쿼리 실행 │
│ → User 엔티티 반환 │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ MethodLoggingAspect (After) │
│ [UserRepository] │
│ │
│ 실행 시간: 15ms │
│ │
│ Response 로그 출력 │
│ { │
│ "trace_id": "a1b2c3d4-...", │
│ "component_name": "UserRepository",│
│ "layer": "REPOSITORY", │
│ "message": "Response completed: findById",│
│ "execution_time_ms": 15, │
│ "response": { │
│ "result": { │
│ "id": 123, │
│ "name": "John" │
│ } │
│ } │
│ } │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ MethodLoggingAspect (After) │
│ [UserService] │
│ │
│ 실행 시간: 25ms │
│ │
│ Response 로그 출력 │
│ { │
│ "trace_id": "a1b2c3d4-...", │
│ "component_name": "UserService", │
│ "layer": "SERVICE", │
│ "message": "Response completed: findById",│
│ "execution_time_ms": 25, │
│ "response": { │
│ "result": { │
│ "id": 123, │
│ "name": "John", │
│ "email": "john@example.com" │
│ } │
│ } │
│ } │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ MethodLoggingAspect (After) │
│ [UserController] │
│ │
│ 실행 시간: 50ms │
│ HTTP 상태 코드: 200 │
│ │
│ Response 로그 출력 │
│ { │
│ "trace_id": "a1b2c3d4-...", │
│ "component_name": "UserController",│
│ "layer": "CONTROLLER", │
│ "message": "Response completed: getUser",│
│ "execution_time_ms": 50, │
│ "response": { │
│ "http": { │
│ "method": "GET", │
│ "endpoint": "/api/users/123", │
│ "statusCode": 200 │
│ }, │
│ "result": { │
│ "id": 123, │
│ "name": "John Doe" │
│ } │
│ } │
│ } │
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ TraceIdFilter (Finally) │
│ │
│ 1. MDC.remove("traceId") │
│ 2. MDC.remove("client_ip") │
│ │
│ 3. 완료 로그 출력 │
│ "MDC 정리 완료: [GET] /api/users/123 - Status 200"│
└─────────────┬───────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ HTTP 응답 반환 │
│ │
│ Status: 200 OK │
│ Headers: │
│ X-Trace-Id: a1b2c3d4-... │
│ Body: │
│ {"id": 123, "name": "John Doe"} │
└─────────────────────────────────────────┘6.3 로그 출력 타임라인
같은 TraceID로 모든 로그가 연결됩니다:
10:30:45.123 [INFO] {"trace_id":"a1b2c3d4-...","component_name":"UserController","layer":"CONTROLLER","message":"Request received: getUser",...}
10:30:45.130 [INFO] {"trace_id":"a1b2c3d4-...","component_name":"UserService","layer":"SERVICE","message":"Request received: findById",...}
10:30:45.135 [INFO] {"trace_id":"a1b2c3d4-...","component_name":"UserRepository","layer":"REPOSITORY","message":"Request received: findById",...}
10:30:45.150 [INFO] {"trace_id":"a1b2c3d4-...","component_name":"UserRepository","layer":"REPOSITORY","message":"Response completed: findById","execution_time_ms":15,...}
10:30:45.155 [INFO] {"trace_id":"a1b2c3d4-...","component_name":"UserService","layer":"SERVICE","message":"Response completed: findById","execution_time_ms":25,...}
10:30:45.173 [INFO] {"trace_id":"a1b2c3d4-...","component_name":"UserController","layer":"CONTROLLER","message":"Response completed: getUser","execution_time_ms":50,...}