이번 글에서는 분산 시스템 환경에서 서로 다른 서버의 로그에 동일한 TraceId를 적용한 과정을 간단하게 정리해보고자 한다.
분산 아키텍처에서는 하나의 요청이 여러 서비스(예: API 서버, 메시지 큐 컨슈머)를 거쳐 처리되는 경우가 많다.
이때 각 시스템에 분산된 로그를 하나의 흐름으로 묶어 추적할 수 없다면, 장애 발생 시 원인을 파악하기 매우 어려워진다.
현재 진행 중인 개인 프로젝트(쿠폰 시스템)에서 쿠폰 발급 요청이
API 서버에서 시작되어 카프카(Kafka)를 통해 컨슈머 서버로 전달되는 과정이 있다.
이 두 서버의 로그에 동일한 식별자를 부여하여 요청 흐름을 쉽게 추적할 수 있도록 GlobalTraceId
를 적용한 경험을 공유한다.
참고
: 본 글에서 소개되는 코드 예시는 현재 시점의 구현을 바탕으로 작성되었으며, 프로젝트가 발전함에 따라 내용이 변경되거나 개선될 수 있음을 미리 알려드립니다.이 글에서 다루는 모든 코드는 깃허브에서 확인하실 수 있습니다.
이번 포스팅에서는 성능 테스트와 시스템 운영 환경에서 어떤 지표를 주시해야 하는지, 그리고 Spring Boot 환경에서 Prometheus와 Grafana를 활용해 직접 모니터링 환경을 구축한 경험을 공유하고자 합니다.
빠른 응답 시간은 사용자 이탈률을 낮추고, 안정적인 시스템은 비즈니스 신뢰도를 높입니다. 그렇기 때문에 이러한 지표를 꾸준히 관찰하고 개선하는 것은 매우 중요하다고 생각합니다.
이전 포스팅이었던 “2편. Spring Boot 요청 흐름 추적: Logging Filter와 traceId 적용기”에 이어, 이번 글에서는 3편을 작성해보고자 합니다.
이 글은 경험을 바탕으로 한 하나의 접근법이며, 정답이라기보다는 여러분이 각자의 상황에 맞는 최적의 방법을 찾아가는 데 도움이 되기를 바라는 마음으로 작성했습니다.
성능 테스트나 Prometheus, Grafana에 대한 기본적인 개념을 알고 계신다면 이 글을 수월하게 읽으실 수 있을 겁니다.
이 글은 아래에 해당하는 분들께 도움이 될 것입니다.
성능 테스트 시 어떤 지표를 봐야 할지 막막하신 분
Prometheus가 수집하는 핵심 지표의 의미가 궁금하신 분
Spring Boot 애플리케이션의 지표를 Grafana 대시보드로 직접 만들어보고 싶으신 분
참고
: 본 글에서 소개되는 코드 예시는 현재 시점의 구현을 바탕으로 작성되었으며, 프로젝트가 발전함에 따라 내용이 변경되거나 개선될 수 있음을 미리 알려드립니다.이 글에서 다루는 모든 코드는 깃허브에서 확인하실 수 있습니다.
이번 포스팅에서는 개인적으로 진행한 쿠폰 발급 시스템 프로젝트에서 분산락(Distributed Lock) 메커니즘을 개선했던 경험을 공유하고자 합니다. 초기 시스템은 단일 Redis 서버 환경을 기준으로 SETNX
명령어를 직접 사용하여 분산락을 구현했습니다.
물론 SETNX
는 간단하게 분산락을 구현할 수 있는 방법이지만, 몇 가지 불편한 점과 단일 인스턴스 환경에서도 고려해야 할 점들이 있었습니다. 예를 들어, 락 획득 및 해제 로직이 비즈니스 코드와 섞여 가독성을 해치거나, 반복적인 try-finally
구문을 사용해야 하는 점, 그리고 락 임대 시간(Lease Time) 관리의 복잡성 등이 그것입니다.
본 글에서는 이러한 점들을 개선하기 위해 Redisson의 RLock
과 Spring AOP를 도입하여, 비즈니스 로직과 락킹 로직을 분리하고 보다 안정적이며 재사용 가능한 분산락 코드를 작성한 과정을 상세히 설명드리겠습니다. 현재는 Redis 단일 인스턴스 환경을 기준으로 설명하며, 고가용성 환경으로의 확장은 향후 과제로 남겨두었습니다.
이번 포스팅에서는 Spring Boot 프로젝트에서 HTTP 요청과 응답을 효과적으로 로깅하고,
멀티쓰레드 환경에서 요청 흐름을 명확히 추적할 수 있도록 traceId
를 활용하는 방법을 소개합니다.
일반적으로
requestId
로 요청을 구분하고,traceId
로 전체 요청 흐름을 추적합니다.이 글에서는 단일 서비스 환경을 다루지만, 초기부터 traceId
를 적용하여 향후 분산 시스템에서도 확장 가능한 구조를 제공합니다.
특히, 실무에 적용한 내용을 중심으로 프로덕션 환경에서도 활용 가능한 실용적인 예제를 설명합니다.
Spring Boot 프로젝트에 Logging Filter를 적용하고자 하는 분
Filter와 HandlerInterceptor의 차이점을 알고 싶은 분
OncePerRequestFilter의 동작 원리와 사용 이유가 궁금한 분
멀티쓰레드 환경에서 로그가 뒤섞이는 문제를 해결하고 싶은 분
프로덕션 환경에 바로 적용 가능한 실용적인 예제를 찾는 분
관련 포스팅
해당 섹션에 대한 자세한 내용은 이 글을 참고해 주시기 바랍니다.
아래 세부 섹션에 있는 내용은 해당 글과 다른 자료들을 종합해서 정리했습니다.
Filter
는 Spring Framework의 일부가 아닌 웹 서버(servlet container) 수준의 컴포넌트입니다.
요청과 응답을 서블릿이 처리하기 전후로 가로채어 조작할 수 있습니다.
대표적인 예로 Spring Security
가 있습니다.
Spring Security
에서는 인증/인가를 위해 여러 개의 Filter 체인을 사용하며, 이를 Spring과 연동하기 위해 DelegatingFilterProxy
를 활용합니다.
이 구조 덕분에 Spring Security
는 Spring MVC에 종속되지 않고도 동작할 수 있습니다.
Filter는 다음과 같은 메서드를 제공합니다.
init
: 필터 초기화 시 호출doFilter
: 요청과 응답을 가로채어 처리 (핵심 메서드)destroy
: 필터 종료 시 호출멀티 모듈 프로젝트로 전환하면서 환경별 로그 설정의 필요성을 절실히 느꼈습니다.
운영 환경에서는 로그의 형식과 수준이 서비스 안정성과 직결되기 때문에 더욱 중요합니다.
이번 글은 실제 운영 환경에서 적용하는 것 보다는 멀티 모듈 구조에서 환경별로 logback.xml
을 구성한 경험을 공유하기 위해 작성했습니다.
관련 포스팅