전체 글 236

타임아웃은 실패가 아니다 외부 API 연동 다루는 법

들어가며PG사 결제 API를 연동하면서 가장 먼저 마주친 질문은 이거였다."결제 요청을 보냈는데 응답이 안 오면, 실패로 처리하면 되지 않나?"직관적으로 맞는 것 같았다. 타임아웃이 나면 실패인 거고, 실패면 롤백하면 된다고 생각했다.틀렸다.타임아웃은 실패가 아니다. "모른다"는 뜻이다. 이 한 줄을 이해하는 데 설계 전체가 바뀌었고, 그 과정에서 내가 세운 원칙이 하나 있다.응답을 받았으면 결과를 안다. 못 받았으면 모른다. 모르면 행동하지 말고, 알아낸 다음에 행동한다.이 글은 이 원칙을 발견하기까지의 과정이다.1. 왜 타임아웃이 실패가 아닌가DB와 PG는 근본적으로 다르다. DB 트랜잭션은 하나의 프로세스 안에서 ACID를 보장하지만, PG 연동은 네트워크를 사이에 둔 분산 트랜잭션(distribu..

운영 2026.03.20

느려진 서비스의 본질은 코드가 아니라 구조에 있다

"주니어 백엔드 개발자가 반드시 알아야 할 실무 지식" 2장·3장을 읽고, CS 개념과 실무 경험을 엮어 정리한 글입니다.들어가며서비스가 느려지면 가장 먼저 떠오르는 생각은 "코드를 최적화해야 하나?"이다. for문을 줄이고, 알고리즘을 개선하고, 불필요한 연산을 없애는 것. 물론 중요하다. 하지만 실무에서 마주치는 대부분의 성능 문제는 코드의 계산 복잡도가 아니라 I/O 경계에서 발생한다.이 책의 2장과 3장은 그 경계를 정확히 짚는다. DB 연동, 외부 API 호출, 커넥션 풀 설정, 캐시 전략, 인덱스 설계. 이것들이 실제 서비스 응답 시간의 70~90%를 지배한다는 사실을 데이터로 보여준다.이 글에서는 책에서 다루는 핵심 키워드들을 CS 관점에서 깊이 있게 풀어보고, 내가 실무에서 겪었던 경험을 ..

도서 2026.03.15

인덱스를 만들었는데 왜 안 타죠 ? 옵티마이저의 비용 계산을 파헤치다

인덱스를 만들었는데 왜 안 타죠? — 옵티마이저의 비용 계산을 파헤치다인덱스를 걸었는데 풀스캔이 나왔다프로젝트에서 Soft Delete를 쓰고 있었다. 상품 조회 쿼리에 WHERE deleted_at IS NULL 조건이 붙는데, deleted_at에 인덱스를 걸어봤자 EXPLAIN을 찍으면 type: ALL — 풀 테이블 스캔이 나온다.인덱스가 분명히 있는데 왜 안 쓸까? "선택도가 낮아서"라는 답은 알고 있었지만, 왜 선택도가 낮으면 풀스캔이 더 나은 건지 — 그 물리적인 이유를 몰랐다.이번에 옵티마이저의 비용 계산 구조를 파면서, 그 "왜"를 찾았다.옵티마이저 — SQL의 "어떻게"를 결정하는 두뇌SQL을 던지면 MySQL이 바로 실행하는 게 아니다. 3단계를 거친다.SQL 입력 → [1] Par..

데이터베이스 2026.03.14

WIL - 5주차 ("왜?"를 멈추지 않았더니 보이기 시작한 것들)

이번 주에 새로 배운 것"왜?"라는 질문이 깊이를 만든다이번 주는 유독 "왜?"를 많이 물었다. 복합 인덱스를 공부하다가 "카디널리티가 높은 컬럼을 앞에 놓으라"는 규칙을 만났다. 예전 같았으면 그대로 외웠을 것이다. 그런데 이번엔 "왜?"를 던져봤다. 왜 카디널리티가 높으면 앞이어야 하지? B+Tree에서 실제로 어떤 차이가 생기지? 등호 조건과 범위 조건이 섞이면 어떻게 되지? 파고 들어가니까 답이 달라졌다. 카디널리티보다 등호 조건이 먼저라는 게 진짜 규칙이었다. 카디널리티가 아무리 높아도 범위 조건이면 그 뒤 컬럼은 인덱스를 못 탄다. B+Tree의 리프 노드가 정렬되는 방식을 이해하고 나니, "왜 그런지"가 보였다. 외운 규칙이 아니라 원리에서 나온 판단이 되니까, 새로운 상황을 만나도 스스로 ..

스터디/루퍼스 2026.03.13

RedisTemplate을 까보고 나서야 캐시를 제대로 쓸 수 있었다

redisTemplate.opsForValue().set(key, json, ttl) — 이 한 줄 뒤에 뭐가 있는지 모르고 쓰면, 캐시가 서비스를 살리는 게 아니라 죽인다 TL;DR이커머스 프로젝트에 Cache-Aside 패턴을 직접 구현했다. @Cacheable 대신 RedisTemplate으로 캐시 흐름을 직접 제어했는데, 구현하면서 get() 한 줄이 Master/Replica 라우팅을 거친다는 것, 커밋 전에 캐시를 삭제하면 stale 데이터가 영구화된다는 것, 같은 캐시 삭제인데 트랜잭션 관리 방식에 따라 무효화 전략이 달라야 한다는 것을 알게 됐다. RedisTemplate의 동작 흐름을 코드 레벨로 추적하고 나서야, 왜 이런 처리를 해줘야 하는지 납득이 됐다."그냥 쓰면 되지, 왜 까봐?"..

카디널리티가 높으면 앞에 놓으라는 규칙을 믿었다가 느려졌다

복합 인덱스 컬럼 순서의 진짜 1순위는 카디널리티가 아니었다 TL;DR복합 인덱스를 설계할 때 "카디널리티 높은 컬럼을 앞에"라는 규칙을 따랐다. 근데 EXPLAIN을 찍어보니 인덱스를 걸었는데도 filesort가 사라지지 않았다. 원인을 파보니 컬럼 순서의 진짜 1순위는 카디널리티가 아니라 조건 유형(등호 vs 범위)이었다. B+Tree 리프 노드의 정렬 원리를 이해하고 나서야 인덱스 설계가 풀렸다."카디널리티 높은 컬럼을 앞에" 이 규칙을 의심 없이 따랐다상품 목록 API에 복합 인덱스를 걸어야 했다. products 테이블 약 20만 건, 자주 쓰이는 WHERE 조건은 status와 brand_id.brand_id: 카디널리티 500 (고유 값 500개)status: 카디널리티 3 (ACTI..

데이터베이스 2026.03.13

캐시 삭제했는데 stale data가 살아 돌아왔다

afterCommit DELETE면 충분하지 않나? — Cache-Aside 레이스 컨디션을 발견하고, 근본 원인을 찾기까지 TL;DRCache-Aside + afterCommit DELETE면 캐시 무효화는 끝이라고 생각했습니다. 그런데 "DB 읽기와 캐시 SET 사이의 시간 간격"이라는 구조적 허점을 발견했고, 처음에는 캐시 레이어에서 사후 패치하려 했습니다. 한 발 물러서 보니, 이 문제의 근본 원인은 캐시가 아니라 DB 쓰기 프로세스의 동시성 제어였습니다. 쓰기 쪽을 비관적 락과 원자적 UPDATE로 잠근 뒤에는, afterCommit DELETE + TTL 안전망만으로 충분했습니다.캐시가 필요한 이유: 속도가 아니라 DB 보호인덱스 최적화 + Cursor 페이지네이션까지 적용하고 나니, 상품 목..

데이터베이스 2026.03.12

배타락을 걸었는데 다른 트랜잭션이 조회된다고?!

이커머스 프로젝트에서 재고 차감에 비관적 락을 적용하고 나서, 하나 궁금한 게 생겼다.배타락을 걸면 다른 트랜잭션이 이 데이터를 아예 못 읽나? 못 읽을 줄 알았다. 근데 읽힌다. 일반 SELECT는 배타락을 무시하고 데이터를 그냥 가져온다.공식 문서를 찾아봤는데 이렇게 적혀있다.Consistent reads ignore any locks set on the recordsthat exist in the read view.Consistent read는 읽기 뷰에 존재하는 레코드에 설정된 모든 잠금을 무시합니다.출처: MySQL 8.0 - InnoDB Locking ReadsConsistent read is the default mode in which InnoDB processesSELECT stateme..

데이터베이스 2026.03.08

Redis 분산락의 TTL이 만료됐는데, 트랜잭션이 아직 끝나지 않았다면

혹시 이런 상황, 생각해본 적 있으신가요?분산락을 공부하면 보통 이런 흐름으로 배운다."Redis에 Lock을 잡고 → 작업하고 → Lock을 해제한다"여기까지는 별로 어렵지 않다. 근데 공부하다가 문득 이런 생각이 들었다."Lock에 TTL이 5초인데... 내 트랜잭션이 6초 걸리면 어떻게 되지?" 처음엔 "설마 그런 일이 있겠어?" 하고 넘겼다. 근데 생각해보면 현실에서 충분히 일어날 수 있다. GC가 길어질 수도 있고, 네트워크가 느려질 수도 있고, 쿼리가 걸릴 수도 있다. 이 글은 그 "만약"이 실제로 터졌을 때 어떻게 대응할 수 있는지 정리한 내용이다.먼저, 문제 상황을 정확히 그려보자클라이언트 A Redis 클라이언트 B━━━━━━━━..

WIL - 4주차 (환경을 바꿀 수 없을 때, 나를 바꾸는 법)

이번 주에 새로 배운 것이상과 현실 사이에서 할 수 있는 건 생각보다 많다회사에서 새 프로젝트가 들어왔다. 보험 도메인이다. 처음 기획서를 받았을 때 정책이 빠져 있는 부분이 많았고, 고려사항도 불명확했다. 예전 같았으면 "기획이 덜 된 거 아닌가"라고 생각하고 기다렸을 것이다.이번엔 다르게 움직였다. AI를 활용해서 보험 도메인의 일반적인 정책, 예외 케이스, 고려해야 할 사항들을 먼저 정리했다. 다른 프로젝트에서 사람들이 어떤 부분을 놓쳤는지, 어떤 정책이 나중에 문제가 됐는지를 조사하고 참고했다. 그걸 바탕으로 기획 쪽에 질문을 던지고, 정책을 같이 구체화해나갔다.결과는 예상 밖이었다. 정책이 명확해지니 단순 CRUD는 물론이고, 복잡한 비즈니스 로직도 흐름이 보였다. 데드라인보다 빠르게 치고 나갈..

스터디/루퍼스 2026.03.08

락을 잘 골랐는데 왜 더 위험해졌을까

락을 잘 골랐는데 왜 더 위험해졌을까 — 주문 트랜잭션의 락 3개를 1개로 줄인 이야기TL;DR이커머스 주문 흐름에 동시성 제어를 붙이면서, 도메인마다 "맞는 락"을 골랐더니 하나의 트랜잭션에 비관적 락 2개 + 낙관적 락 1개가 공존하게 됐다. 데드락 위험, 락 보유 시간 증가, 팀원이 알아야 할 규칙 증가. 결국 "락을 잘 고르는 것"보다 "공유 자원 자체를 줄이는 것"이 더 근본적인 해법이었고, 원자적 UPDATE로 트랜잭션 내 락을 1개로 줄였다.동시성 문제가 뭔지부터 고민을 시작했다.과제를 받고 처음 든 생각은 단순했다. "공유 자원이면 동시성 문제가 생긴다." 재고, 포인트, 쿠폰, 좋아요, 여러 사용자가 건드리는 데이터를 쭉 나열했다.근데 이 정의가 틀렸다. 상품 상세를 100명이 동시에 조..

데이터베이스 2026.03.06

WIL - 3주차 (정답이 여러 개일 때, 자기 기준을 세우는 법)

이번 주에 새로 배운 것같은 질문에 다른 답이 나올 수 있다이번 주 과제는 도메인 모델링 + 레이어드 아키텍처 + DIP 적용이었다. 코드를 짜는 것보다 더 많이 배운 건, 여러 시각의 피드백을 비교 분석하면서였다."Repository 호출은 누구의 책임인가?"라는 질문 하나에 대해서도 사람마다 답이 달랐다. Application에서 직접 호출해야 한다는 관점, 도메인이 이미 필요한 상태를 가지고 있어야 한다는 관점, 비즈니스 로직의 위치를 먼저 정하면 자연스럽게 따라온다는 관점. 전부 근거가 있고, 전부 틀린 말은 아니다.나는 Blue Book 스타일(Domain Service → Repository 직접 호출)을 택했는데, 이 방식에 직접 동의하는 시각은 많지 않았다. 대부분 "Repository 호..

스터디/루퍼스 2026.03.01

DIP를 끝까지 적용해본 경험 - 순수 POJO 도메인 설계의 트레이드오프

"왜 과한지"를 모르면서 "과하다"고 말하고 싶지 않았다TL;DR이커머스 프로젝트에서 도메인 모델을 순수 POJO로 분리하고 JPA Entity를 Infrastructure에 배치하는 Entity-level DIP를 끝까지 적용해봤다. Dirty Checking을 포기하고 36곳에 명시적 save()를 호출하는 비용을 치렀지만, "과하다"는 것을 아는 것과 "왜 과한지"를 직접 체감하는 것은 완전히 다른 경험이었다. 이 글을 쓰게 된 배경나는 기술적으로 넓은 경험을 쌓아오기 위해 노력했다. 다양한 프로젝트를 거치면서 여러 기술 스택을 다루고, 실무에서 마주치는 문제들을 부딪히며 해결해 왔다.그런데 이번에 이커머스 서비스의 핵심 도메인 상품, 브랜드, 좋아요, 주문, 결제을 레이어드 아키텍처 + DIP(의..

티스토리 자동 목차(TOC) 만들기: 클릭 이동 안 됨 현상 완벽 해결!

블로그 포스팅이 길어질수록 독자들은 원하는 정보를 찾기 힘들어합니다. 이때 꼭 필요한 게 바로 목차라고 생각합니다.!구글 SEO(검색 최적화)에도 도움이 된다는 사실, 알고 계셨나요?하지만 인터넷에 나온 코드를 그대로 따라 해도 "클래스명이 달라서 안 보이거나", "클래식하면 해당 위치로 이동하지 않는" 문제로 고생하시는 분들이 많습니다. 오늘은 어떤 스킨에서도 완벽하게 작동하는 자동 목차 설치법을 정리하겠습니다. 1. 왜 자동 목차를 써야 할까?사용자 편의성: 독자가 원하는 부분으로 바로 점프할 수 있습니다.SEO 점수 상승: 구글 로봇이 글의 구조를 파악하기 쉬워져 검색 노출에 유리합니다.체류 시간 증가: 깔끔한 정돈은 블로그의 전문성을 높여줍니다.2. 1분 만에 끝내는 자동 목차 설치법Step 1:..

카테고리 없음 2026.02.16

소프트웨어 아키텍처 스터디 회고 - 완독보다 오래 남은 것은 ‘의사결정의 방식’이었다

소프트웨어 아키텍처 스터디가 2월 12일을 마지막으로 마무리됐다.회사 업무가 바빠지면서 몇 번은 참석하지 못했지만, 이번 스터디는 결과적으로 혼자 읽는 독서와는 다른 종류의 완주였다. 단순히 책을 끝까지 읽었다는 성취보다, 읽는 과정에서 아키텍처를 바라보는 시야와 의사결정 습관이 더 분명해졌다.스터디를 하면서 가장 자주 떠올랐던 문장은 이것이다.아키텍처는 정답을 맞히는 일이 아니라, 무엇을 포기할지 합의하는 일이다.혼자 읽을 때는 “개념을 이해했는가”에 초점이 갔다면, 함께 읽을 때는 자연스럽게 “이 개념이 실무 의사결정에서 어떤 역할을 하는가”로 질문이 이동했다. 이 이동이 이번 스터디의 가장 큰 가치였다.1) 약속이 만든 실행력, 실행이 만든 학습출석률이 완벽하진 않았지만, 스터디가 약속이라는 사실은..

스터디 2026.02.16

WIL - 2주차 유비쿼터스 언어를 먼저 고정하니 설계가 따라왔다

이번 주에 새로 배운 것이번 주 과제는 이커머스 도메인(상품, 브랜드, 좋아요, 주문 등)을 대상으로 설계 산출물만으로 PR을 제출하는 것이었다. 요구사항 정리부터 시퀀스 다이어그램, 클래스 다이어그램, ERD까지. 코드 없이 설계를 완성한다는 게 처음엔 막막했다.그래서 나는 시작점부터 명확히 잡았다.유비쿼터스 언어(Glossary)를 가장 먼저 정의하고, 그 언어 위에서 설계를 진행한다.이 선택은 “문서 작성 순서”가 아니라 “설계의 품질을 결정하는 규약”을 먼저 고정하는 일이었다.실무에서 설계가 흔들리는 순간을 떠올려보면, 대부분은 기술이 아니라 단어의 혼용에서 시작한다.“상품”과 “아이템”을 같은 의미로 쓰거나“주문”과 “결제”를 동일시하거나“장바구니”와 “주문서” 경계를 흐리거나이런 상태로 ERD..

스터디/루퍼스 2026.02.15

문서화는 협업의 언어다. AI 도메인 전문가와 브레인스토밍하고, 실무에서 수십 개 문서를 쓰며 배운 것

TL;DR이번 이커머스 설계 과제에서 AI를 "도메인별 전문가"로 세워놓고 브레인스토밍하며 요구사항을 명확히 했다. 대화에서 나온 결정을 문서(결정 로그)로 고정했다. AI 시대에 문서화는 단순한 이해 도구가 아니라, “왜 이 결정을 했는지”를 남겨 팀이 다시 흔들리지 않게 하는 운영 자산이 된다.1. AI에게 "당신의 의견이 궁금합니다"라고 물었다이번 과제의 도메인은 이커머스였다. 상품, 브랜드, 주문, 재고, 쿠폰, 결제. 각각이 하나의 전문 영역이고, 나 혼자 모든 도메인을 깊이 있게 설계하기엔 한계가 있었다. 각 도메인은 결국 서로 얽히고, 작은 정책 차이가 데이터 모델과 트랜잭션 경계를 흔든다. 혼자 모든 도메인을 깊이 있게 설계하려 하면, 금방 “그럴듯한 정답”에 기대게 된다.그래서 AI를..

아키텍처 2026.02.13

"나중에 바뀔 수 있어요" 그 한마디가 설계를 바꿨다

법령 프로젝트에서 전제 조건이 깨진 경험이, 이커머스 설계에서 내 판단을 어떻게 바꿨는지에 대한 이야기 TL;DR회사에서 법령 번역 서비스를 만들며, 기획과 함께 꼼꼼하게 정의한 전제 조건이 한 번에 무너지는 걸 경험했다. "외국 법령은 수정 불가"라는 핵심 제약이 깨지면서 데이터 정합성이 무너졌고, 운영 데이터가 쌓인 상황에서 DB를 쉽게 바꾸지 못해 애플리케이션 레벨에서 분기 처리를 억지로 끼워 맞추느라 코드가 복잡해졌다. 그 결과 코드가 빠르게 복잡해졌고, 그 경험이 이번 이커머스 설계 과제에서 "요구사항을 꼼꼼하게 보고, 전제가 바뀌어도 테이블이 흔들리지 않는 최소한의 여유"를 우선으로 두게 되었다.1. 기획과 분명히 합의했는데, 그게 깨졌다회사에서 세무법인을 위한 법령 서비스를 맡았던 적이 있다..

아키텍처 2026.02.13

WIL - 1주차 (TDD & Hello Agent)

WIL - 1주차 (TDD & Hello Agent)이번 주에 새로 배운 것TDD는 “테스트 먼저”가 아니라, 설계를 이끌어내는 도구였다과제를 시작할 때 “기능 구현에 앞서 테스트 코드를 먼저 작성하라”는 요구를 받았다. 처음에는 단순히 “테스트를 먼저 쓰고 통과시키면 되겠지”라고 생각했다. 그런데 막상 시작하니, 어디서부터 어떤 순서로 무엇을 테스트해야 하는지부터 불명확했다.처음에는 요구사항을 기준으로 기능 단위로 구현하려 했다. 하지만 곧 흐름이 무너졌다. PasswordValidator부터 시작해 검증 로직 → Entity → Service → Controller 순서로 접근하려니, 기능이 이곳저곳에 흩어졌다. 결과적으로 “지금 내가 무엇을 검증하고 있는가?”를 잃어버린 상태가 됐다.방향을 다시 잡..

스터디/루퍼스 2026.02.08

AI와 TDD를 함께하며 배운 것 - 개발자의 역할은 어떻게 바뀌는가

TL;DRAI와 협업하면서 개발자의 역할이 "코드를 작성하는 사람"에서 "의도를 정의하고 판단하는 사람"으로 바뀌고 있음을 체감했다. 단, 테스트 코드만큼은 직접 작성해야 진짜 내 것이 된다.왜 이 글을 쓰게 되었는가?1주차 과제를 Claude Code와 함께 진행했다. 처음에는 "AI가 코드를 다 짜주겠지"라는 막연한 기대가 있었다. 하지만 실제로 협업해보니, AI를 잘 쓰려면 내가 더 명확해야 했다.무엇을 만들지, 어떤 구조로 할지, 어디까지 허용할지 — 이런 판단들을 내가 하지 않으면 AI는 엉뚱한 방향으로 달려갔다. 이 글에서는 AI와 TDD를 함께하며 느낀 점들을 정리해본다.CLAUDE.md - AI에게 규칙을 알려주는 것부터 시작Claude Code를 사용할 때 가장 먼저 한 일은 CLAUDE..

스터디/루퍼스 2026.02.06

단위 테스트를 넘어서 - 통합 테스트가 잡아준 JPA 버그 이야기

테스트는 통과했는데 버그였다 - 트랜잭션 경계에서 배운 것 TL;DRMock 테스트의 한계를 마주한 순간 - JPA Detached Entity 디버깅 경험단위 테스트(Mock)에서는 절대 발견할 수 없는 버그가 있다. 비밀번호 변경 기능이 "성공"했는데 DB에 반영되지 않는 버그를 통합 테스트를 작성하면서 발견했고, 원인은 JPA의 Detached Entity 상태였다.왜 이 글을 쓰게 되었는가?1주차 과제로 회원가입, 내 정보 조회, 비밀번호 변경 API를 TDD로 구현하고 있었다.단위 테스트는 모두 통과했다. E2E 테스트도 작성해뒀다. 그런데 Facade 통합 테스트를 작성하는 과정에서 이상한 현상을 발견했다.비밀번호 변경 API 호출 → 성공 응답새 비밀번호로 로그인 → 실패이전 비밀번호로 로그..

스터디/루퍼스 2026.02.06

[소프트웨어 아키텍처] Ch.17 오케스트레이션 주도 SOA

오케스트레이션 주도 서비스 지향 아키텍처 (SOA) 완벽 가이드들어가며: 아키텍처 스타일의 흥망성쇠아키텍처 스타일은 예술 사조와 비슷한 측면이 있다. 그것이 발전하던 시대의 아키텍트에게는 의미가 있지만, 이후 시대에는 유관성(relevance)이 사라진다. 오케스트레이션 주도 서비스 지향 아키텍처(Orchestration-Driven Service-Oriented Architecture)가 바로 그런 경향을 보여주는 대표적 사례다.이 아키텍처는 논리적으로는 타당해 보이는 조직의 아이디어가 어떻게 개발 프로세스의 가장 중요한 부분을 저해할 수 있는지 보여주는 훌륭한 본보기다. 특히, 소프트웨어 아키텍처의 제1법칙인 "소프트웨어 아키텍처의 모든 것은 트레이드오프"라는 점을 무시할 때 생기는 위험을 잘 보여준..

도서 2026.02.02

[소프트웨어 아키텍처] Ch.16 공간 기반 아키텍처 스타일 (Space-Based Architecture) 완벽 가이드

1. 공간 기반 아키텍처란?공간 기반 아키텍처(Space-Based Architecture)는 높은 확장성, 탄력성, 동시성(concurrency)과 관련한 문제를 해결하기 위해 특별히 설계된 아키텍처 스타일입니다.1.1 이름의 유래: 튜플 공간 (Tuple Space)튜플 공간은 여러 병렬 프로세서가 공유 메모리를 통해 통신하게 함으로써 병렬 처리의 이점을 취하는 기법입니다.1.2 핵심 아이디어보통의 시스템에서 중앙 데이터베이스는 시스템의 동기적 제약조건입니다. 공간 기반 시스템은 중앙 데이터베이스를 두는 대신 메모리 안에서 데이터 그리드를 복제함으로써 높은 확장성과 탄력성, 성능을 달성합니다.1.3 주요 특징애플리케이션 데이터는 메모리에 유지: 모든 활성 처리 단위 사이에서 복제비동기 데이터베이스 갱..

도서 2026.02.01

[소프트웨어 아키텍처] Ch.15 이벤트 주도 아키텍처 스타일 (Event-Driven Architecture) 완벽 가이드

목차이벤트 주도 아키텍처란?요청 기반 모델 vs 이벤트 기반 모델토폴로지 개요이벤트 vs 메시지파생 이벤트와 확장 능력비동기 역량브로드캐스팅과 이벤트 페이로드오류 처리데이터 손실 방지요청-응답 처리중재자 토폴로지데이터 토폴로지아키텍처 특성 평가예시와 용례1. 이벤트 주도 아키텍처란?이벤트 주도 아키텍처(Event-Driven Architecture, EDA)는 인기 있는 분산 비동기 아키텍처 스타일로, 고확장성·고성능 애플리케이션을 만드는 데 흔히 사용됩니다.1.1 핵심 특징적응성이 매우 높음: 소규모 애플리케이션부터 대규모 복합 애플리케이션까지 다양한 규모에 적용 가능분리된 컴포넌트: 결합이 느슨한(decoupled) 이벤트 처리 컴포넌트들로 구성비동기 처리: 컴포넌트들이 비동기적으로 이벤트를 발생하고..

도서 2026.02.01

루퍼스 루프클럽 후기: “최적해”보다 “태도와 실행”이 커리어를 만든다

최근 루퍼스 루프클럽에 참여했다. 연사는 이동욱(인프랩 CTO)님, 루퍼스 1기 수료자 엄준서님, 그리고 루퍼스 멘토 Alen님이었다. 세션은 서로 다른 관점에서 “개발자 커리어와 학습, 그리고 실무에서의 문제 해결”을 이야기했는데, 흥미로웠던 점은 결론이 하나로 수렴했다는 것이다.개발자는 결국 환경을 탓하기보다, 주어진 제약 속에서 문제를 정의하고 실행하며, 그 과정에서 다음 단계로 나아가는 힘을 만들어야 한다. 나는 최근 이직 이후 기대했던 개발 문화와 현실 사이의 간극을 체감하고 있었다. “도망친 곳엔 낙원이 없다”는 문장이 떠오를 만큼, 새로운 환경도 완벽하지 않았다. 다만 이번 세미나는 그 간극을 해석하는 프레임을 바꿔 주었다. “좋은 환경을 찾는 것”과 “지금 환경에서 성장하는 것”은 대립이 ..

스터디 2026.01.19

[소프트웨어 아키텍처] Ch.8~11 읽고 난 뒤: “구조”를 코드와 팀과 장애까지 연결하는 방법

컴포넌트로 사고하고, 스타일로 옮겨 담고, 운영에서 증명하기들어가며: 내가 아키텍처를 다시 보게 된 순간 백엔드 개발에서 “구현”은 늘 할 수 있습니다. 문제는 시간이 지나면 항상 같은 질문으로 돌아옵니다. 이 코드는 어디까지가 한 덩어리(경계) 인가?장애가 나면 어디까지 같이 죽는가(격리)?변경이 생기면 어디까지 같이 바뀌는가(결합)?팀이 늘어나면 충돌과 병목이 구조적으로 줄어드는가(조직-구조 정렬)? 챕터 8~11은 이 질문에 답하는 순서를 제시합니다. 논리적 컴포넌트로 먼저 생각하고(Ch.8)그 다음에 아키텍처 스타일로 물리화하며(Ch.9)현실에서 가장 흔한 계층형의 장단을 정확히 보고(Ch.10)“모놀리스의 현실성 + 도메인 경계”를 함께 가져가는 모듈형 모놀리스로 타협점을 잡는다(Ch.11) 그..

도서 2026.01.15

[소프트웨어 아키텍처] Ch.1~7 읽고 난 뒤: “설계도”가 아니라 “의사결정 체계”로서의 아키텍처

들어가며: 왜 지금 ‘아키텍처’가 더 중요해졌나책의 초반부는 아키텍처를 “정답을 그리는 활동”이 아니라 트레이드오프를 인지하고, 조직이 합의 가능한 형태로 결정하는 체계로 정의합니다. 특히 인상 깊었던 문장은 “중요한 결정은 양자택일이 아니라 스펙트럼 위의 한 점을 고르는 일”이라는 관점이었습니다.실무에서 제가 겪은 대부분의 논쟁도 결국 “A vs B”가 아니라 성능·비용·운영 난이도·변경 용이성 같은 축 위에서 어디에 무게를 둘지의 문제였습니다.1) Ch.1: 아키텍처는 ‘산출물’이 아니라 ‘구성 요소들의 결합’책에서는 아키텍처를 단일 문서나 다이어그램이 아니라, 다음의 결합으로 설명합니다.아키텍처 스타일: 시스템을 구성하는 기본 형태(예: 계층형, 이벤트 기반, 마이크로서비스 등)아키텍처 특성(qua..

도서 2026.01.07

[도서] 도메인 주도 설계를 위한 함수형 프로그래밍 Domain Modeling Made Functional

도메인 주도 설계를 위한 함수형 프로그래밍 - 서평(스콧 블라신, 『도메인 주도 설계를 위한 함수형 프로그래밍: Domain Modeling Made Functional – 코틀린과 타입스크립트로 구현하는 실전 도메인 모델링』)들어가며최근 마이크로서비스 아키텍처 포트폴리오 프로젝트를 진행하면서 도메인 설계의 중요성을 절실히 느끼고 있었습니다. 특히 서비스 간 경계를 어떻게 나누고, 각 도메인을 어떻게 모델링할지 고민이 많았는데, 이번에 『도메인 주도 설계를 위한 함수형 프로그래밍』 서평단에 당첨되어 책을 읽게 되었습니다. 이 책은 스콧 블라신의 명저를 코틀린과 타입스크립트로 재구성한 것으로, 실무에서 바로 적용 가능한 형태로 제공된다는 점이 매력적이었습니다.소프트웨어 개발의 본질: 코딩이 아닌 문제 해결..

도서 2025.12.13

PostgreSQL 파티셔닝 환경에서 복합 PK + bigserial의 함정: 1,100건의 중복 키 장애 분석과 복구

서론문제: Range 파티셔닝된 테이블에서 PRIMARY KEY (event_time, event_id) 구조로 설계했으나, event_id bigserial 값이 파티션 간 중복 발생원인: 복합 PK는 조합의 유일성만 보장하며, bigserial은 전역 시퀀스를 사용하지만 파티션별 삽입 시점 차이로 동일 값 할당 가능영향: 약 1,100건의 중복 키 발생, FK 참조 무결성 위협, 통계 집계 왜곡해결: created_at DESC 기준 최신 레코드 유지 정책으로 중복 제거 후, PK 구조 재설계 (event_id 단독 PK + event_time 인덱스)1. 배경: 거래 시스템의 대용량 데이터 처리 요구사항시스템 개요소상공인 대상 금융 거래 통합 플랫폼에서 다음과 같은 데이터 특성을 처리합니다- 일평균..

데이터베이스 2025.11.28

[JPA] N+1 문제와 Fetch/Lazy 설명 with Batch Fetch Size

들어가며JPA를 사용하다 보면 피할 수 없는 성능 문제 중 하나가 바로 N+1 문제입니다. 이 글에서는 N+1 문제가 무엇인지, 왜 발생하는지, 그리고 어떻게 해결할 수 있는지를 실제 예시와 함께 살펴보겠습니다.1. N+1 문제란?1.1 예시 상황다음과 같이 주문(Order)과 고객(Customer) 엔티티가 N:1 관계를 맺고 있다고 가정해봅시다.@Entity@Builderpublic class Order { @Id @GeneratedValue private Long id; private String productName; private Integer amount; @ManyToOne @JoinColumn(name = "customer_id") pri..