콘텐츠로 이동

api-log

Spring Boot용 이벤트 드리븐 API 호출 로깅. 비동기 이벤트 파이프라인 + PostgreSQL JSONB. 요청 경로를 막지 않고 외부 API 호출을 모두 기록합니다.

시작하기 GitHub


한눈에 보기

스타터를 클래스패스에 올리면 — 요청 본문, 응답 본문, 상태 코드, 에러, 재시도까지 — 모든 외부 HTTP 호출이 자동으로 PostgreSQL에 기록됩니다. HTTP 호출은 로그 쓰기를 기다리지 않습니다. 이벤트가 비동기로 처리됩니다.

@Service
public class UserService {

    private final RestApiClientUtil api;

    public UserService(RestApiClientUtil api) {
        this.api = api;
    }

    public User createUser(User newUser) {
        // HTTP 호출은 동기적으로 즉시 반환됩니다.
        // 백그라운드에서 INITIATED → SUCCESS 또는 ERROR 두 줄이 api_log에 기록됩니다.
        return api.postSyncTyped("/api/users", newUser, User.class);
    }
}

한 번의 호출로 api_log 테이블에:

SELECT event_type, endpoint, status_code, timestamp FROM api_log ORDER BY id DESC LIMIT 3;

 event_type | endpoint     | status_code | timestamp
------------+--------------+-------------+----------------------
 SUCCESS    | /api/users   |         201 | 2026-05-18 10:02:14
 INITIATED  | /api/users   |             | 2026-05-18 10:02:14

본문(payload, response, error_message)은 JSONB로 저장되어 ->, ->>, GIN 인덱스로 자유롭게 조회 가능합니다. "그 벤더에 뭘 보냈는지 모르겠어"가 더 이상 없습니다.

핵심 가치

  • 논블로킹 설계

    ApplicationEventPublisher로 별도 스레드에서 로그 기록. HTTP 호출은 응답이 오는 즉시 리턴되고, 로그 행은 그 뒤에 비동기로 영속화됩니다.

  • PostgreSQL JSONB 저장

    요청·응답·에러 본문이 JSONB로 저장. GIN 인덱스, ->, ->>, jsonb_path_query 그대로 사용. 필요한 곳은 구조화, 유연해야 할 곳은 스키마리스.

  • 재시도 인식

    Spring Retry와 통합. 재시도 실패마다 RETRY_ERROR 행이 별도로 생성되며 retry_count가 함께 기록되어 모든 시도의 타임라인을 복원할 수 있습니다.

  • Virtual Threads 지원

    Java 21+ 비동기에 맞춰 설계. spring.threads.virtual.enabled=true와 호환 — 적은 메모리로 높은 동시성.

  • Drop-in 스타터

    자동 구성으로 ApiEventListener, ApiLogService, RestApiClientUtil@ConditionalOnMissingBean으로 등록. 직접 빈을 정의하면 모두 오버라이드 가능.

  • 운영 검증

    오픈소스 공개 전에 Devslab SaaS 인프라에서 먼저 사용. Testcontainers 기반 PostgreSQL 통합 테스트 31개 포함.

언제 쓰면 좋은가

api-log가 적합한 경우 — 외부 API 호출 이력이 영구적이고 조회 가능해야 할 때. 벤더 통합 디버깅, 컴플라이언스 감사, 결제 정산, 고객용 사용량 리포트 작성 등.

다른 도구가 더 적합한 경우 — 일시적 관측만 필요하다면 OpenTelemetry + 트레이스 백엔드, 단순 fire-and-forget 전송 로그라면 stdout + 로그 수집기.

아키텍처

Caller code
RestApiClientUtil  (또는 자체 HTTP 클라이언트)
   ↓ publishEvent
ApplicationEventPublisher
   ↓ @EventListener (async)
ApiEventListener
ApiLogService
ApiLogRepository  (JPA)
PostgreSQL  (api_log · JSONB columns)

호출마다 최소 두 행이 생성됩니다: INITIATED (즉시) 그리고 종료 행 (SUCCESS, ERROR, 또는 RETRY_ERROR). 모든 이벤트가 request_id로 연결되어 한 호출의 전체 흐름을 단일 쿼리로 복원할 수 있습니다.

다음 단계