4편에서 Saga의 실패 복구 전략을 다루었습니다. 보상 트랜잭션과 재시도, 멱등성, 다단계 실패 격리까지 설계하면 Saga의 에러핸들링 체계가 갖춰집니다. 그런데 이 체계가 실제 운영 환경에서 의도대로 동작하고 있는지를 어떻게 확인할 수 있을까요? 보상 트랜잭션이 정상적으로 실행되었는지, Dead Letter Topic에 메시지가 쌓이고 있지는 않은지, 어떤 단계에서 지연이 발생하는지를 파악하려면 체계적인 관찰가능성(Observability)이 필요합니다.또한 여러 Saga가 동시에 실행되면서 같은 데이터에 접근할 때 발생할 수 있는 데이터 이상현상도 고려해야 합니다. 이 글에서는 Saga 시스템의 관찰가능성 설계, 동시 Saga 실행 시의 데이터 정합성 심화 주제, 그리고 시리즈 전체를 관통하는 설계..
3편에서 Outbox 패턴으로 DB 변경과 메시지 발행의 원자성을 보장하는 방법을 살펴보았습니다. Outbox 패턴은 메시지가 "반드시 발행된다"는 보장을 제공하지만, 발행된 메시지를 수신한 서비스가 처리에 실패하면 어떻게 되는지에 대해서는 답하지 않습니다. Saga는 여러 서비스에 걸쳐 단계적으로 진행되는 흐름이므로, 어느 단계에서든 실패가 발생할 수 있고, 이에 대한 체계적인 복구 전략이 필요합니다.이 글에서는 Saga 실패 시 보상 트랜잭션으로 되돌리거나 재시도로 전진하는 두 가지 복구 방향을 정리하고, 재시도의 전제 조건인 멱등성, 그리고 실패 메시지를 격리하는 구체적인 전략을 다룹니다.복구의 두 가지 방향Saga의 특정 단계에서 실패가 발생했을 때, 복구 방향은 크게 두 가지입니다. 이전 단계를..
2편에서 Saga 패턴의 서비스 간 통신이 왜 비동기 메시징으로 설계되는지 살펴보았습니다. 비동기 메시징은 시간적 결합을 제거하고 장애 전파를 차단하여 Saga를 안정적으로 진행할 수 있게 합니다. 그런데 비동기 메시징을 도입하면 곧바로 마주치는 문제가 있습니다. 서비스가 자신의 데이터베이스를 업데이트하고 메시지 브로커에 이벤트를 발행하는 두 가지 작업을, 어떻게 원자적으로 처리할 것인가의 문제입니다.이 글에서는 이 문제의 본질인 이중 쓰기 문제(Dual Write Problem)를 정의하고, 이를 해결하는 Transactional Outbox 패턴의 구조와 Message Relay 구현 전략을 정리합니다.이중 쓰기 문제Saga의 각 단계에서 서비스는 두 가지 작업을 수행해야 합니다. 자신의 데이터베이스..
1편에서 MSA 환경의 분산 트랜잭션 문제와 동기식 해법들의 구조적 한계를 살펴보았습니다. ChainedTransactionManager는 부분 커밋 실패에 대한 보호 장치가 없었고, 2PC는 가용성과 확장성을 희생해야 했습니다. 이번 글에서는 이 문제에 대한 근본적인 대안인 Saga 패턴의 구조를 깊이 들여다보고, 왜 비동기 메시징이 Saga의 표준적인 통신 방식이 되는지 정리합니다.Saga 패턴이란Saga 패턴은 하나의 글로벌 트랜잭션 대신, 각 서비스의 로컬 트랜잭션을 순차적으로 연결하여 분산 데이터 정합성을 보장하는 패턴입니다. Microservices.io에서는 Saga를 다음과 같이 정의합니다."A saga is a sequence of local transactions. Each local ..
모놀리식 애플리케이션에서는 하나의 데이터베이스에 대해 @Transactional 하나면 ACID가 보장됩니다. 비즈니스 로직이 아무리 복잡해도 커밋과 롤백의 경계가 명확하고, 개발자가 트랜잭션 정합성을 의식하지 않아도 프레임워크가 이를 처리해 줍니다. 그런데 마이크로서비스 아키텍처(MSA)로 전환하면 이 전제가 무너집니다. 서비스마다 독립된 데이터베이스를 갖게 되면서, 하나의 비즈니스 작업이 여러 서비스에 걸칠 때 기존의 로컬 ACID 트랜잭션으로는 데이터 정합성을 보장할 수 없게 됩니다. 이 글에서는 이 문제가 왜 발생하는지, 그리고 이를 해결하려는 동기식 접근들이 왜 근본적인 한계를 갖는지 정리합니다. 트랜잭션 경계가 분리되는 순간모놀리스에서 MSA로 전환할 때 가장 먼저 마주치는 구조적 변화 중 ..
LLM 기반 서비스가 일상적인 개발 환경으로 들어왔습니다. 그러나 우리가 호출하는 LLM API 역시 결국 HTTP 위에서 동작합니다. 모델의 파라미터 수나 추론 최적화만으로는 사용자가 체감하는 응답 속도를 설명하기 어렵습니다. 네트워크 계층에서 어떤 프로토콜을 사용하고 있는지에 따라 지연 특성은 달라집니다. HTTP의 진화는 기능 추가의 역사가 아니라 병목을 줄이기 위한 설계 변화의 과정이라고 이해하고 있습니다. 이 글에서는 HTTP/1.1부터 HTTP/2, 그리고 HTTP/3와 QUIC까지 이어지는 흐름을 RFC 기반으로 정리해보고자 합니다. HTTP/1.1의 구조적 한계 HTTP/1.1은 RFC 2616에서 정의되었고, 이후 메시지 문법과 의미는 RFC 7230부터 RFC 7235까지의 문서로 재..
LLM API를 호출하고 스트리밍 응답을 받는 일은 이제 일상이 되었습니다. 그러나 우리가 InputStream.read()를 호출하는 순간, 그 아래에서 어떤 계층과 버퍼를 거쳐 데이터가 올라오는지 설명해보면 생각보다 명확하지 않은 경우가 많습니다. 이 글에서는 소켓이 무엇인지, 파일 I/O와 TCP I/O는 어떻게 다른지, 커널 버퍼는 어떤 역할을 하는지, 그리고 packet·segment·frame은 무엇이 다른지 공식 문서 기반으로 다시 정리해보려 합니다. 개념을 암기하기 위한 글이 아니라, 실무에서 병목을 설명할 수 있는 관점을 정리하는 것이 목적입니다. Socket이란 무엇인가? 소켓은 네트워크 통신을 위한 추상화입니다. 이 추상화는 University of California, Berkel..
JWT와 현대 웹 인증 아키텍처 - Stateless 인증: JWT와 현대 인증 구조 웹 애플리케이션의 인증 방식은 웹 아키텍처의 변화와 함께 지속적으로 발전해 왔습니다. 초기 웹에서는 HTTP의 Stateless 특성 때문에 사용자 상태를 유지하기 어려웠고, 이를 보완하기 위해 Cookie가 등장했습니다. 이후 보안성과 관리 측면에서 개선된 방식으로 Server Session 기반 인증 구조가 널리 사용되었습니다. 그러나 웹 서비스 규모가 커지고 시스템 구조가 점점 분산되면서 Session 기반 인증 방식 역시 여러 한계를 드러내기 시작했습니다. 특히 API 중심 아키텍처와 MSA 환경에서는 서버가 사용자 상태를 직접 저장하는 방식이 확장성 측면에서 부담이 되는 경우가 많았습니다. 이러한 흐름 속에서 ..
- Total
- Today
- Yesterday
- 동시성처리
- DB 인덱스 성능
- DB 트랜잭션
- Spring Batch
- 백엔드 성능
- spring batch 5
- 트랜잭션 관리
- Redis 성능 개선
- mybatis
- Redis 캐시 전략
- Double-Checked Locking
- Cache Avalanche
- 캐시 성능 비교
- Java Performance
- 백엔드 성능 설계
- 캐시 장애
- 스레드 생명주기
- InterruptedException
- 캐시와 인덱스
- Initialization-on-Demand Holder Idiom
- 트래픽 처리
- TTL 설계
- Hot Key 문제
- 백엔드 아키텍처
- Cache Aside
- Cache Penetration
- Redis vs DB
- Eager Initialization
- 백엔드 성능 튜닝
- Enum 기반 싱글톤
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |

