{
    "componentChunkName": "component---src-templates-category-template-js",
    "path": "/posts/Music_Pipeline",
    "result": {"pageContext":{"currentCategory":"Music_Pipeline","categories":["All","Music_Pipeline","IT_엔지니어를_위한_네트워크_입문","CleanCode","JPA_Basic","EKS"],"edges":[{"node":{"id":"d43844ee-35e5-550c-8c4b-84d8b83c50da","excerpt":"어느 날 애플리케이션이 뜨지 않았다 M3 작업 중 bootRun 이  으로 실패했다.\n어제까지 멀쩡했던 로컬 DB 다. 안에 들어가 보니:  데이터베이스 안에는 이런 내용이 있었다. All your data was backed up by us. You must pay 0.013 bitcoin to …\nor in 48 hours, your data will be publicly disclosed and deleted. 노출된 MySQL/MariaDB 를 스캔해서 약한 비밀번호로 로그인하고, DB 를 삭제한 뒤\n랜섬 노트를 남기는 자동화 봇의 전형적인 수법이다. 뚫린 경로 거창한 취약점이 아니다. 조합이 문제였다. Docker 포트 매핑의 기본값은 모든 인터페이스()다. “로컬 개발용이니까”라고\n쓴 root/root 와 만나는 순간, 네트워크에서 접근 가능한 무인 DB 가 된다.\n공유기 NAT 뒤라고 안심할 수 없다 — IPv6 는 공인 주소가 직접 붙는 경우가 많고,\n같은 네트워크의…","fields":{"slug":"/Music_Pipeline_09/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 09. 번외, 로컬 Docker DB가 랜섬 공격당했다","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_08/"}},"previous":null},{"node":{"id":"aabb9630-b1e7-5303-8dd0-3c3828c61149","excerpt":"선택 모듈 — 오디오를 실제로 흘려보내기 메타데이터와 집계만 있던 파이프라인에 실제 재생 경로를 붙였다.\n제약: 기존 코드 무변경 —  패키지와  테이블만 추가. 원본 음원은 ffmpeg 합성 사인파다. 저작권 문제가 없고, 길이를 \n와 정확히 일치시킬 수 있어 검증이 깨끗하며, 저장소엔 바이너리 대신 재현 방법을\n버전관리한다. 트랙마다 주파수를 trackId 에서 유도해서 “다른 트랙인데 같은 소리” 같은\n배선 오류를 귀로 잡을 수 있게 했다. HLS 구조 — RFC 8216 을 코드에 대응시키기 variant 인코딩·분할은 ffmpeg 에 맡기고 마스터 플레이리스트는 직접 썼다 —\n(비트레이트 + TS 오버헤드)와 (“mp4a.40.2” = AAC-LC)가 어디서\n오는지 코드에 남는다. 플레이어는 이 두 값으로 다운로드 전에 variant 를 고른다.\nABR 의 선택 근거가 마스터에 선언돼 있다는 게 HLS 구조의 핵심이다. 검증은 ffprobe 교차 검증 — 우리가 만든 산출…","fields":{"slug":"/Music_Pipeline_08/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 08. HLS 스트리밍, 온디맨드 패키징이 기각당한 이유","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_07/"}},"previous":{"fields":{"slug":"/Music_Pipeline_09/"}}},{"node":{"id":"294830e9-7d9b-503c-a525-65ad3c21e7e1","excerpt":"문제를 일부러 만들다 이전 직장에서 N+1 로 60~90초 걸리던 조회를 개선한 경험이 있는데, MyBatis 환경이었다.\nJPA 환경에서 같은 문제를 재현하고 개선 전략을 수치로 비교하고 싶었다. 앨범 목록 API(앨범 + 대표 아티스트명 + 트랙 목록)를 만들었다. Album→Artist(ToOne),\nAlbum→Tracks(OneToMany) 모두 LAZY. 리포지토리는  하나 —\n코드 어디에도 반복 조회가 없다. 그런데: 쿼리는 리포지토리가 아니라 DTO 변환 중(지연 로딩 접근)에 나간다. 이게 N+1 이 늦게\n발견되는 이유다. MyBatis 는 resultMap 의 collection 쿼리가 XML 에 보이는데, JPA 는\n 한 줄이 조용히 SELECT 를 만든다. 그리고 응답은 완전히\n정확하다 — N+1 은 틀린 결과가 아니라 느린 결과라서 기능 테스트로는 절대 안 잡힌다. 측정은 Hibernate Statistics()로 했다. “느린 것 같다”가 아니라\n쿼리 수를 …","fields":{"slug":"/Music_Pipeline_07/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 07. N+1, 쿼리 수만 세면 fetch join에 속는다","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_06/"}},"previous":{"fields":{"slug":"/Music_Pipeline_08/"}}},{"node":{"id":"d3715462-713f-5c22-89ad-4fd2525e72a6","excerpt":"문제 집계 테이블 기반 “실시간 TOP 100 차트” API. 모든 사용자가 같은 것을 본다 —\n전형적인 읽기 편중 + 핫키 하나 워크로드다. 결정이 세 겹이었다. 결정 1 — 차트를 어디서 만드나: Redis Sorted Set 기각 “Redis 차트면 ZINCRBY + ZREVRANGE 지” 싶었는데, 기각했다. 결정타는 멱등성이다. 컨슈머가 같은 배치를 재처리하면 DB 는  로 걸러내지만\nZINCRBY 는 그대로 두 번 더해진다. 04편에서 세운 멱등성 체계 밖에 비원자\n이중 쓰기 경로를 만드는 구조다. Redis 에도 중복 판정을 만들면 되지만, 그건 같은\n체계를 두 번 구현하는 것이다. DB 집계(TOP 100 쿼리) + 캐시로 갔다.\n설계 결정은 독립적이지 않다 — 앞의 결정이 뒤의 선택지를 제약한다. 결정 2 — Look-aside Write-through 는 기각: 쓰기 주체(컨슈머, 초당 수백 건)와 읽기 주체(차트 API)가 달라서,\n아무도 안 읽는 사이에도 집계…","fields":{"slug":"/Music_Pipeline_06/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 06. Redis 캐시와 스탬피드, 그리고 캐시가 무의미했던 순간","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_05/"}},"previous":{"fields":{"slug":"/Music_Pipeline_07/"}}},{"node":{"id":"7154d496-001f-5747-805c-4587277d4d14","excerpt":"문제 깨진 JSON 메시지 하나가 파티션에 들어오면 무슨 일이 벌어지나. 무한 재시도 설정이라면 그 메시지가 파티션 전체를 막는다(head-of-line blocking).\n뒤에 쌓인 정상 메시지 수만 건이 한 건 때문에 처리되지 않는다. 이게 poison pill 이다. 설계 — 실패를 두 종류로 가른다 M1 입수에서 “재시도 가능(DB 장애) vs 불가(검증 실패)“를 갈랐던 원칙을 그대로 재적용했다. 실패 유형 판단 처리 역직렬화 실패 백 번 다시 읽어도 같은 바이트는 같은 실패 재시도 없이 즉시 DLQ 처리 실패 (DB 등) 일시적일 수 있다 지수 backoff(0.5s→1s→2s) 3회 → DLQ  가 역직렬화 실패를 예외가 아니라 “값”(null + 원인 헤더)으로\n바꿔준다 — 리스너까지 도달해야 우리가 제어권을 갖는다. 고정 간격 재시도는 기각 — DB 가 과부하로 느려진 상황에서 같은 속도로 계속 두드리면\n회복을 방해한다. 지수 backoff 는 시스템에 숨 쉴 틈을…","fields":{"slug":"/Music_Pipeline_05/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 05. DLQ와 poison pill, 그리고 세 번의 삽질","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_04/"}},"previous":{"fields":{"slug":"/Music_Pipeline_06/"}}},{"node":{"id":"e92214b5-54b4-50b0-ac8b-0c9e19a48bf5","excerpt":"문제 재생 이벤트(초당 수백 건)를 소비해 곡별 재생수를 집계한다. 재생수는 카운터다 —\n두 번 더하면 그냥 틀리고, 틀렸다는 사실조차 알기 어렵다. 그리고 Kafka 는 at-least-once 다. 리밸런싱, 오프셋 커밋 전 종료, 운영자의 오프셋 리셋,\n 초과 — 컨슈머는 정상 동작 중에도 같은 메시지를 다시 받는다.\n중복 소비는 장애가 아니라 전제 조건이다. 흔한 오해부터 ” 켰으니 안전하다”는 말이 자주 나온다. 아니다. 설정 막는 것 못 막는 것 프로듀서 멱등성 프로듀서 재시도로 인한 브로커 측 중복 저장 컨슈머 재소비 Kafka 트랜잭션(EOS) Kafka→Kafka 경로의 중복 외부 DB 쓰기 컨슈머가 DB 에 쓰는 순간, Kafka 가 주는 보장은 끝난다. 멱등성은 우리 몫이다. 대안 비교와 선택 대안 판단 A. eventId UNIQUE + 신규분만 집계 ✅ 채택 B. 오프셋을 DB 에 저장, 집계와 한 트랜잭션 이론상 가장 정확하지만 기각 C. Kafka EOS…","fields":{"slug":"/Music_Pipeline_04/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 04. Kafka 컨슈머 멱등성, 중복은 버그가 아니라 전제다","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_03/"}},"previous":{"fields":{"slug":"/Music_Pipeline_05/"}}},{"node":{"id":"d0d7ea0e-12e8-527a-af70-666f74d2ac39","excerpt":"문제 5,000건짜리 입수 파일 처리 중 3,001번째에서 실패하면 어떻게 해야 하나. 가장 쉬운 답은 “파일 전체를 한 트랜잭션으로 묶고 실패하면 전량 롤백”이다.\n깨끗해 보이지만, 이 프로젝트에서 이 답을 일부러 구현해서 깨뜨렸다. 결론부터: 전량 롤백은 데이터만 되돌리는 게 아니라 실패 원인 기록까지 지운다.\n그 파일을 다시 넣으면 같은 지점에서 같은 실패를 반복한다. 경계 설계 4가지 작업 전파 속성 이유 Delivery 등록  (즉시 커밋) messageId UNIQUE 가 중복 실행 차단 장치 — 커밋돼야 다른 트랜잭션에 보인다 검증 실패 기록  롤백에 휩쓸리면 안 된다. 실패 기록은 재처리의 입력이다 청크(500건) 적재  커밋 단위. 건별 커밋은 fsync 비용, 파일 전체는 undo/락 비용 사후 검증 실패 보상 삭제 이미 커밋된 것은 롤백으로 못 되돌린다 보상 삭제가 필요한 구조적 이유 스트리밍 파싱(StAX)이라 헤더의  와 실제 개수가 맞는지는 파일 끝까지\n읽…","fields":{"slug":"/Music_Pipeline_03/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 03. 트랜잭션 경계, 전량 롤백이 정답이 아닌 이유","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_02/"}},"previous":{"fields":{"slug":"/Music_Pipeline_04/"}}},{"node":{"id":"c5d7d09a-9e82-5065-a87f-08c6c0216000","excerpt":"문제 음원 메타데이터 파일 하나에 Release 5,000건, Track 50,000건이 들어온다.\nMyBatis 시절엔  로 multi-value insert 를 쓰면 끝이었는데,\nJPA 로 오니  이 건별 INSERT 를 날리고 있었다.  을 넣어도 달라지지 않았다. 경고도 로그도 없이. 원인 — IDENTITY 는 batch 를 조용히 끈다 영속성 컨텍스트는 엔티티를 ID 를 키로 관리한다. 그런데  는\nAUTO_INCREMENT 라서 INSERT 를 실제로 실행해야 ID 를 알 수 있다. Hibernate 의 batch 는 write-behind(쓰기 지연) 위에서 동작한다 — INSERT 를 모았다가 flush 에서 묶어 보낸다 IDENTITY 는  시점에 ID 가 필요하므로 즉시 INSERT 할 수밖에 없다 그래서 Hibernate 는 IDENTITY 엔티티의 batch 를 예외 없이 포기한다 코드 차이는 애노테이션 한 줄인데, 이 동작 차이는 어디에도 표시되지 않는다.…","fields":{"slug":"/Music_Pipeline_02/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 02. JPA 배치 insert, IDENTITY가 41배 느린 이유","date":"July 24, 2026"}},"next":{"fields":{"slug":"/Music_Pipeline_01/"}},"previous":{"fields":{"slug":"/Music_Pipeline_03/"}}},{"node":{"id":"cb71b72b-21f2-5639-868c-b331fd519ed5","excerpt":"왜 이 프로젝트인가 MyBatis/MariaDB 중심으로 4~5년을 일했고, JPA·Kafka·Redis 는 “써봤다”와 “설계할 수 있다” 사이 어딘가에 있었다.\n그 간극을 메우려고 음악 스트리밍 서비스의 백엔드 데이터 파이프라인을 축소 구현했다. 두 개의 큰 흐름으로 구성된다. 음원 메타데이터 입수 — 유통사가 보내는 DDEX 스타일 XML 을 스트리밍 파싱·검증해 배치 적재 재생 이벤트 처리 — Kafka 로 초당 수백 건의 재생 이벤트를 수집, 멱등하게 집계해 실시간 차트 제공 이 도메인을 고른 이유는 두 흐름의 실패 모델이 정반대라서다.\n입수는 “파일 하나가 크고 실패가 부분적” — 트랜잭션 경계 문제.\n이벤트는 “건수가 많고 중복이 정상” — 멱등성 문제.\n한 프로젝트 안에서 서로 다른 정합성 전략을 비교할 수 있다. 저장소: github.com/Shim8934/media-project 스택: Java 21, Spring Boot 3.4, JPA + JdbcTemplat…","fields":{"slug":"/Music_Pipeline_01/"},"frontmatter":{"categories":"Music_Pipeline","title":"음악 스트리밍 파이프라인 만들기 - 01. 프로젝트 소개와 세 가지 원칙","date":"July 24, 2026"}},"next":{"fields":{"slug":"/IT엔지니어를_위한_네트워크_입문_08/"}},"previous":{"fields":{"slug":"/Music_Pipeline_02/"}}}]}},
    "staticQueryHashes": ["1073350324","1956554647","2938748437"]}