[{"data":1,"prerenderedAt":543},["ShallowReactive",2],{"post-document:\u002Fbackend\u002Fkafka\u002F2026\u002F08\u002F27\u002Fcore-principles\u002F":3},{"id":4,"title":5,"body":6,"categories":524,"date":527,"description":528,"extension":529,"image":530,"key_concepts":530,"last_modified_at":530,"legacyPath":531,"meta":532,"navigation":534,"part":530,"path":535,"published":534,"robots":530,"seo":536,"series":530,"stem":537,"strengths":530,"summary":530,"tags":538,"tradeoffs":530,"__hash__":542},"posts\u002Fposts\u002FBackend\u002FKafka\u002F핵심.md","Kafka의 핵심 설계 원리",{"type":7,"value":8,"toc":518},"minimark",[9,13,18,24,27,38,41,44,63,66,69,75,78,81,84,90,93,97,100,105,109,114,117,120,123,126,132,135,138,141,147,150,153,159,162,165,168,182,185,188,193,197,200,203,209,212,226,229,232,243,246,249,252,258,261,266,270,273,278,281,287,290,293,299,302,308,311,314,328,331,336,340,343,346,352,355,358,364,367,370,381,384,390,393,396,404,410,413,424,429,432,438,441,497,503,509,515],[10,11,12],"p",{},"Decoupling + Buffering + Fan-out + Replay + Load Balancing",[14,15,17],"h1",{"id":16},"decoupling","Decoupling",[19,20,21],"blockquote",{},[10,22,23],{},"서비스 간 직접 의존성을 끊는 것",[10,25,26],{},"REST 직접 호출이면:",[28,29,35],"pre",{"className":30,"code":32,"language":33,"meta":34},[31],"language-text","Order Service\n   ↓ REST\nPayment Service\n","text","",[36,37,32],"code",{"__ignoreMap":34},[10,39,40],{},"Order Service는 반드시 Payment Service를 알아야 한다.",[10,42,43],{},"그래서 뭐.. 아래와 같은 사항을 알아야 한다.",[45,46,47,51,54,57,60],"ul",{},[48,49,50],"li",{},"주소는?",[48,52,53],{},"API는?",[48,55,56],{},"지금 상태가?",[48,58,59],{},"응답은 언제 오니?",[48,61,62],{},"실패하면 어떻게 처리?",[10,64,65],{},"딱 봐도 귀찮잖아요?",[10,67,68],{},"그래서 Kafka에서는 이 의존성을 줄여버린다.",[28,70,73],{"className":71,"code":72,"language":33,"meta":34},[31],"Order Service\n      ↓\nORDER_CREATED\n      ↓\n    Kafka\n      ↓\nPayment Service\n",[36,74,72],{"__ignoreMap":34},[10,76,77],{},"Order Service는 Payment Service를 몰라도 된다.",[10,79,80],{},"Order Service가 ORDER_CREATED라는 이벤트를 발행하기만 하면, Payment Service는 ORDER_CREATED를 소비하는 것으로 만들어 줄 수 있다.",[10,82,83],{},"말로 하니깐 좀 헷갈리긴 하는데,",[28,85,88],{"className":86,"code":87,"language":33,"meta":34},[31],"Order ─X─ Payment\n\nOrder → Kafka ← Payment\n",[36,89,87],{"__ignoreMap":34},[10,91,92],{},"이와 같이 구성할 수 있다.",[94,95,96],"h2",{"id":96},"정리",[10,98,99],{},"서비스와 서비스를 직접 연결하지 않고 이벤트를 매개로 연결",[19,101,102],{},[10,103,104],{},"Decoupling = 서비스 사이의 결합도를 낮추는 것",[14,106,108],{"id":107},"buffering","Buffering",[19,110,111],{},[10,112,113],{},"처리 속도 차이를 Kafka가 중간에서 흡수하는 것",[10,115,116],{},"자자 주문이 폭주했다고 쳐보자,",[10,118,119],{},"Order Service\n초당 10,000건 발생",[10,121,122],{},"Payment Service\n초당 3,000건 처리 가능",[10,124,125],{},"직접 호출하면",[28,127,130],{"className":128,"code":129,"language":33,"meta":34},[31],"Order → Payment\n       ↑\n   감당 못함\n",[36,131,129],{"__ignoreMap":34},[10,133,134],{},"Payment에 요청이 몰리면서 장애가 날 수 있다.",[10,136,137],{},"하지만~ 킹갓 개발자성님들이 만들어놓은 Kafka가 있다면",[10,139,140],{},"이러만 문제를 해결해 줄 수 있다",[28,142,145],{"className":143,"code":144,"language":33,"meta":34},[31],"Producer\n초당 10,000\n     ↓\n   Kafka\n██████████████\n     ↓\nConsumer\n초당 3,000\n",[36,146,144],{"__ignoreMap":34},[10,148,149],{},"Kafka는 Consumer가 지금 못 처리한 7,000건을 Kafka가 일단 가지고 있고,",[10,151,152],{},"Consumer는 자기 속도 처리에 맞춰서",[28,154,157],{"className":155,"code":156,"language":33,"meta":34},[31],"1\n2\n3\n4\n5\n...\n",[36,158,156],{"__ignoreMap":34},[10,160,161],{},"계속 처리하면 된다.",[10,163,164],{},"쉽게 말하면 Kafka가 대기줄 역할",[10,166,167],{},"식당으로 생각하면..",[45,169,170,173,176,179],{},[48,171,172],{},"손님 100명",[48,174,175],{},"번호표 뽑기",[48,177,178],{},"대기열",[48,180,181],{},"직원들이 주문을 순차로 쳐냄",[94,183,96],{"id":184},"정리-1",[10,186,187],{},"순간적인 트래픽 폭증이 바로 Consumer 장애로 이어지는 것을 줄인다.",[19,189,190],{},[10,191,192],{},"Buffering = Producer와 Consumer의 처리 속도 차이를 중간에서 흡수",[14,194,196],{"id":195},"fan-out","Fan-out",[10,198,199],{},"하나의 이벤트를 여러 시스템이 각각 이용할 수 있는 것",[10,201,202],{},"예를 들어",[28,204,207],{"className":205,"code":206,"language":33,"meta":34},[31],"ORDER_CREATED\n      ↓\n    Kafka\n      │\n ┌────┼──────┬──────┐\n↓    ↓      ↓      ↓\n결제  재고   이메일    분석\n",[36,208,206],{"__ignoreMap":34},[10,210,211],{},"주문 이벤트 하나 생성되었다고 하자,",[45,213,214,217,220,223],{},[48,215,216],{},"Payment: 결제 처리",[48,218,219],{},"Inventory: 재고 감소",[48,221,222],{},"Email: 주문 완료 메일",[48,224,225],{},"Analytics: 매출 통계",[10,227,228],{},"와 같은 각자 같은 이벤트를 다른 목적으로 사용한다.",[10,230,231],{},"특히 중요한 건 Producer가:",[45,233,234,237,240],{},[48,235,236],{},"Payment가 있는지",[48,238,239],{},"Email이 있는지",[48,241,242],{},"Analytics가 있는지",[10,244,245],{},"굳이 알 필요가 없다.",[10,247,248],{},"그래서 확장이 매우 용이하다",[10,250,251],{},"서비스를 계속 추가할 수 있다",[28,253,256],{"className":254,"code":255,"language":33,"meta":34},[31],"            Kafka\n              │\n ┌────┬────┬──┴────┬────────┐\n↓    ↓    ↓       ↓        ↓\n결제  재고 이메일     분석    사기탐지\n",[36,257,255],{"__ignoreMap":34},[10,259,260],{},"Producer는 안 건드려도 될 수 있다.",[19,262,263],{},[10,264,265],{},"Fan-out = 하나의 이벤트를 여러 독립적인 Consumer에게 전달",[14,267,269],{"id":268},"replay-중요","Replay (중요)",[10,271,272],{},"Kafka의 중요한 특징",[19,274,275],{},[10,276,277],{},"과거 이벤트를 다시 읽을 수 있다.",[10,279,280],{},"Kafka에는 이런 로그가 있다고 해보자",[28,282,285],{"className":283,"code":284,"language":33,"meta":34},[31],"offset\n100  ORDER_CREATED\n101  ORDER_PAID\n102  ORDER_CREATED\n103  ORDER_CANCELLED\n104  ORDER_CREATED\n105  ORDER_PAID\n",[36,286,284],{"__ignoreMap":34},[10,288,289],{},"Analytics Service가 버그 때문에 100~105를 잘못 처리했다고 할 때,",[10,291,292],{},"Kafka에서는 offset을 다시 돌려서 다시 읽을 수 있는 기능을 제공한다.",[28,294,297],{"className":295,"code":296,"language":33,"meta":34},[31],"현재\n        ↓\n100 101 102 103 104 105\n                    ↑\n\noffset reset\n\n↓\n100 101 102 103 104 105\n",[36,298,296],{"__ignoreMap":34},[10,300,301],{},"예를 들어 AI팀이 새로운 추천 모델을 만들었다고 해보자.\n과거 3개월 주문 데이터를 다시 흘려서:",[28,303,306],{"className":304,"code":305,"language":33,"meta":34},[31],"Kafka 과거 이벤트\n      ↓\n새로운 AI 모델\n      ↓\n재처리\n",[36,307,305],{"__ignoreMap":34},[10,309,310],{},"와 같이 처리할 수도 있다.",[94,312,96],{"id":313},"정리-2",[45,315,316,319,322,325],{},[48,317,318],{},"버그 수정 후 재처리",[48,320,321],{},"새로운 Consumer 추가",[48,323,324],{},"데이터 재계산",[48,326,327],{},"분석 파이프라인 복원",[10,329,330],{},"등에 유용하다.",[19,332,333],{},[10,334,335],{},"Replay = 저장된 과거 이벤트를 다시 소비할 수 있는 기능",[14,337,339],{"id":338},"load-balancing","Load Balancing",[10,341,342],{},"한 서비스의 처리량을 여러 서버에 나눠주는 것",[10,344,345],{},"Payment Service가 한 대라고 생각해보자",[28,347,350],{"className":348,"code":349,"language":33,"meta":34},[31],"Kafka\n  ↓\nPayment A\n",[36,351,349],{"__ignoreMap":34},[10,353,354],{},"이 경우에 트래픽이 많아지면 감당하기가 힘들어진다.",[10,356,357],{},"그래서 Payment 서버를 3개 띄운다.",[28,359,362],{"className":360,"code":361,"language":33,"meta":34},[31],"              Kafka\n                ↓\n          payment-group\n         ┌──────┼──────┐\n         ↓      ↓      ↓\n         A      B      C\n",[36,363,361],{"__ignoreMap":34},[10,365,366],{},"Kafka는 Partition을 기반으로 이벤트를 나눠준다.",[10,368,369],{},"예를 들어 Topic에 Partition이 3개라면:",[45,371,372,375,378],{},[48,373,374],{},"Partition 0 → Payment A",[48,376,377],{},"Partition 1 → Payment B",[48,379,380],{},"Partition 2 → Payment C",[10,382,383],{},"그러면 처리량을 분산할 수 있다.",[28,385,388],{"className":386,"code":387,"language":33,"meta":34},[31],"주문 1 → A\n주문 2 → B\n주문 3 → C\n주문 4 → A\n...\n",[36,389,387],{"__ignoreMap":34},[10,391,392],{},"Kafka에서는 이걸 Consumer Group이라는 개념으로 구현",[10,394,395],{},"중요한 차이는",[45,397,398,401],{},[48,399,400],{},"서로 다른 Consumer Group → 같은 이벤트를 각각 받음",[48,402,403],{},"같은 Consumer Group → 이벤트를 나눠서 처리",[28,405,408],{"className":406,"code":407,"language":33,"meta":34},[31],"                     Kafka\n\n              ┌────────┼─────────┐\n              ↓        ↓         ↓\n\n      payment-group  email-group  analytics-group\n          │             │             │\n       P1 P2 P3       E1 E2        A1 A2 A3\n",[36,409,407],{"__ignoreMap":34},[10,411,412],{},"Payment 내부에서는:",[45,414,415,418,421],{},[48,416,417],{},"P1",[48,419,420],{},"P2",[48,422,423],{},"P3",[19,425,426],{},[10,427,428],{},"Load Balancing = 같은 역할을 하는 여러 Consumer가 이벤트 처리량을 분산",[14,430,431],{"id":431},"결론",[28,433,436],{"className":434,"code":435,"language":33,"meta":34},[31],"                    ORDER_CREATED\n                         ↓\nOrder Service ─────────> Kafka\n                         │\n                         │ Buffering\n                         │ 이벤트를 쌓아둠\n                         │\n          ┌──────────────┼──────────────┐\n          ↓              ↓              ↓\n   payment-group     email-group   analytics-group\n          │              │              │\n      P1  P2  P3       E1 E2         A1 A2\n",[36,437,435],{"__ignoreMap":34},[10,439,440],{},"여기서",[442,443,444,457],"table",{},[445,446,447],"thead",{},[448,449,450,454],"tr",{},[451,452,453],"th",{},"개념",[451,455,456],{},"의미",[458,459,460,468,475,482,490],"tbody",{},[448,461,462,465],{},[463,464,17],"td",{},[463,466,467],{},"Order와 Payment가 직접 연결되지 않음",[448,469,470,472],{},[463,471,108],{},[463,473,474],{},"Consumer가 느려도 Kafka가 이벤트를 보관",[448,476,477,479],{},[463,478,196],{},[463,480,481],{},"같은 이벤트를 Payment, Email, Analytics가 각각 사용",[448,483,484,487],{},[463,485,486],{},"Replay",[463,488,489],{},"이미 지나간 이벤트를 다시 읽을 수 있음",[448,491,492,494],{},[463,493,339],{},[463,495,496],{},"Payment 서버 여러 대가 작업을 나눠 처리",[28,498,501],{"className":499,"code":500,"language":33,"meta":34},[31],"Kafka가 이벤트를 저장한다\n        ↓\nBuffering 가능\n        ↓\nConsumer가 나중에 읽을 수 있음\n        ↓\nReplay 가능\n",[36,502,500],{"__ignoreMap":34},[28,504,507],{"className":505,"code":506,"language":33,"meta":34},[31],"Producer와 Consumer가 Kafka로 분리됨\n        ↓\nDecoupling\n        ↓\n여러 Consumer가 붙을 수 있음\n        ↓\nFan-out\n",[36,508,506],{"__ignoreMap":34},[28,510,513],{"className":511,"code":512,"language":33,"meta":34},[31],"Consumer Group을 여러 인스턴스로 구성\n        ↓\nLoad Balancing\n",[36,514,512],{"__ignoreMap":34},[10,516,517],{},"그래서 결론적으로는 Kafka는 이벤트를 중간에 저장해서 Producer와 Consumer를 분리하고, 여러 Consumer가 각자의 속도로 이벤트를 독립적으로\n처리하거나 재처리하고, 필요하면 여러 서버로 처리량까지 분산할 수 있게 해주는 분산 이벤트 스트리밍 플랫폼",{"title":34,"searchDepth":519,"depth":519,"links":520},2,[521,522,523],{"id":96,"depth":519,"text":96},{"id":184,"depth":519,"text":96},{"id":313,"depth":519,"text":96},[525,526],"Backend","Kafka","2026-08-27 07:29:47 +0900","Kafka의 Decoupling, Buffering, Fan-out, Replay와 Load Balancing 원리를 서비스 구조와 함께 정리한다.","md",null,"\u002Fbackend\u002Fkafka\u002F2026\u002F08\u002F27\u002Fcore-principles\u002F",{"layout":533},"post",true,"\u002Fposts\u002Fbackend\u002Fkafka",{"title":5,"description":528},"posts\u002FBackend\u002FKafka\u002F핵심",[526,539,540,541],"Messaging","Event Streaming","Distributed System","_LRwCKPaNUTKLUGaEi2dLrswd2eG8nIlZRFfe5TvUbc",1788744785204]