ClOr

ClOr

백엔드 실무 트러블슈팅과 AI 에이전트 구조 분석을 기록합니다.

Claude Code 해부학 (완결)

51만 줄 소스코드를 19편에 걸쳐 분석한 완결 시리즈

전체 시리즈 보기 →

백엔드 트러블슈팅

실무에서 겪은 장애와 해결 과정 기록

전체 시리즈 보기 →

최신 글

article thumbnail
WebClient .block() → Kotlin Coroutine 전환기: suspend · @Transactional 충돌 해결
백엔드 트러블슈팅 2026. 3. 29. 03:14

📑 목차들어가며문제: .block()이 위험한 이유선택: RxJava 3 vs Kotlin Coroutine전환 과정1단계: EngineApiClient 전환 (성공)2단계: Service/Controller 전파 (suspend 전염)3단계: suspend + @TenantTransactional 충돌 (롤백)최종 결정: 범위를 좁힌다결과배운 점들어가며사내 업무 자동화 프로젝트에서 Camunda 엔진 API 호출이 전부 WebClient의 .block()으로 처리되고 있었다. 동시 요청이 몰리면 Tomcat 스레드풀이 고갈될 위험이 있어 비동기 전환이 필요했다.이전 세대에서는 RxJava 3을 사용했지만, Kotlin 프로젝트에서는 Coroutine을 선택했다. 그런데 suspend 함수와 @Tran..

article thumbnail
Schema-per-Tenant 멀티테넌시 구현: JPA 대신 Exposed를 선택한 이유와 실전 삽질
백엔드 트러블슈팅 2026. 3. 29. 03:07

📑 목차들어가며멀티테넌시 전략: Row-Level vs Schema-per-Tenant선택: Schema-per-TenantORM 선택: JPA vs Exposed구현테넌트 식별 (3가지 소스)커넥션 풀 분리커스텀 트랜잭션 어노테이션Flyway 이중 마이그레이션실제로 만난 문제들결과배운 점들어가며엔터프라이즈 SaaS 플랫폼을 설계할 때 멀티테넌시 전략은 아키텍처의 근간을 결정한다. 사내 업무 자동화 프로젝트에서 Kotlin MSA로 재설계하면서, 멀티테넌시 전략과 ORM 선택이라는 두 가지 의사결정을 동시에 해야 했다.이 글에서는 왜 Row-Level이 아닌 Schema-per-Tenant을, JPA가 아닌 Exposed를 선택했는지, 그리고 실제 구현에서 어떤 문제를 만났는지를 공유한다.멀티테넌시 전..

article thumbnail
Kafka 동기화 삽질기 4편: 멀티테넌시 + @Async에서 ThreadLocal이 사라지는 문제
백엔드 트러블슈팅 2026. 3. 29. 02:35

시리즈 목차1편: 트랜잭션 중첩 문제2편: batchInsert & Lock Wait Timeout3편: Reconciliation4편: ThreadLocal 소실 (현재 글)📑 목차이전 편 요약증상: "Tenant context not set"원인: ThreadLocal은 스레드를 넘어가지 않는다해결 1: @Async — TaskDecorator로 컨텍스트 전파Before (컨텍스트 소실)After (TaskDecorator 적용)해결 2: Coroutine — CoroutineContext로 전파두 방식 비교함정: MDC도 같이 사라진다결과배운 점이전 편 요약1~3편에서 트랜잭션 중첩, Lock Wait Timeout, reconciliation을 모두 해결했다. 동기화 로직은 완벽해 보였다. 그래..