안녕하세요.
멘토링을 하면서 주니어 개발자들이 어려워 하는 개념들에 대해 어떻게 하면 쉽게 전달할 수 있을지에 대해서 많은 고민을 하고 있는 푸(Foo)라고 합니다.
잘 부탁 드리겠습니다.
이력
2019. 08 ~ 현재 : 카카오 자바 백엔드 개발자
2021. 08 ~ 현재 : programmers 백엔드 데브코스 멘토
2021. 12 ~ 현재 : F-Lab 자바 백엔드 멘토
책
이것이 취업을 위한 백엔드 개발이다 with 자바(링크)
기타 이력 및 타 플랫폼 강의들은 아래 GitHub 링크에서 확인할 수 있습니다.
GitHub - https://github.com/lleellee0
講義
受講レビュー
- 障害のないサービスを作成するための Resilience4j - CircuitBreaker
- ポートフォリオ超簡易展開
投稿
Q&A
안녕하세요 주문처리에 관하여 질문있습니다 ㅠ ㅁ ㅜ
정인호님 안녕하세요!우선 좋은 질문 주셔서 감사합니다. 말씀하신 것처럼 상황에 따라 데이터 일관성을 맞추기 위한 로직들이 비효율적, 비합리적이라고 느껴지는 상황이 분명 있습니다.데이터 일관성을 맞추기 위한 여러가지 방법들 중 어떤 하나의 방식이 절대적으로 좋은 것은 없으며, 비즈니스 요구사항과 트래픽 패턴에 따라 최적의 해법이 달라집니다. 크게 세 가지 상황으로 나누어 어떤 전략을 사용하는지 먼저 말씀드리겠습니다.1. 일반적인 쇼핑몰 환경일 때 → 재고 예약 (가재고 차감)상황: 대부분의 이커머스처럼 사용자가 상품을 고르고 결제하는 데 수 분의 시간이 걸리며, 트래픽이 예측 가능한 수준일 때.이유: 사용자 경험과 시스템 부하 사이의 균형이 가장 좋습니다. 결제 시간 동안 재고를 보장해주면서도, 전체 시스템에 락(Lock)을 걸지 않아 성능 저하를 막을 수 있습니다. 2. 서버 내에서 모든 처리가 매우 짧게 끝날 때 → 비관적 락 (Pessimistic Lock)상황: 외부 시스템(PG사 등) 연동이나 사용자 대기 없이, 서버 내부 API 호출만으로 모든 비즈니스 로직(재고 확인, 차감, 상태 변경 등)이 수십 ~ 수백 밀리초(ms) 안에 끝날 때.이유: 데이터 정합성을 가장 확실하게 보장할 수 있는 방법입니다. 트랜잭션이 매우 짧아 락으로 인한 성능 저하 영향이 미미할 때 효과적입니다. 3. 특정 시간에 트래픽이 폭주할 때 → 선착순 대기열 (Queueing)상황: 한정판 상품 판매, 공연 티켓팅, 명절 기차표 예매, 수강 신청 등 특정 시간에 예측 불가능한 대규모 트래픽이 몰릴 때.이유: DB와 서버를 보호하고, 사용자에게 공정한 선착순 경험을 제공하는 것이 최우선 목표일 때 사용합니다. 위 방식들 각각에 대해 어떤 방식인지, 주의할 점과 적용 사례를 중심으로 이야기드리면 다음과 같습니다. 1. 재고 예약 (가재고 차감)어떤 방식인가? 사용자가 결제를 시작하기 직전, 재고를 미리 '예약' 상태로 선점하는 방식입니다. 실제 재고를 차감하거나, '예약된 재고' 수량을 별도로 관리합니다. 사용자가 결제를 완료하면 예약 상태를 '확정'으로 변경하고, 일정 시간 내에 결제하지 않으면 예약을 자동으로 취소하여 재고를 복구시킵니다.주의할 점예약 자동 취소 로직 필수: 결제 실패나 사용자 이탈로 인해 선점된 재고(유령 재고)가 영원히 남아있지 않도록, 스케줄러(배치) 등을 이용해 일정 시간 이상 된 '결제 대기' 주문을 찾아 재고를 복구시키는 로직을 반드시 구현해야 합니다.상태 관리의 복잡성: 주문의 상태('결제 대기중', '결제 완료', '주문 취소' 등)를 명확하게 관리해야 합니다.적용 사례대부분의 온라인 쇼핑몰(의류, 전자제품 등)항공권, 숙박 등 예약 후 일정 시간 내 결제가 필요한 예약 시스템 2. 비관적 락 (Pessimistic Lock)어떤 방식인가? 특정 공유 자원(예: 상품 재고)에 대한 접근을 한 번에 하나의 스레드(또는 프로세스)만 가능하도록 먼저 잠금을 획득하고 처리하는 방식입니다. 한 트랜잭션이 재고를 수정하는 동안 다른 트랜잭션은 잠금이 해제될 때까지 대기해야 합니다. 구현 방식은 서버 환경에 따라 나뉩니다.데이터베이스 락 활용: 서버가 1대일 때 간단하게 사용할 수 있는 방법입니다. 데이터베이스의 SELECT ... FOR UPDATE 같은 기능을 이용해 특정 데이터 행(row)에 잠금을 겁니다. 트랜잭션이 종료되면 잠금은 자동으로 해제됩니다.분산 락 (Distributed Lock) 활용: 트래픽 분산을 위해 서버가 여러 대(Scale-out)인 환경에서 필수적입니다. 각 서버가 동일한 DB 데이터에 접근하려고 할 때 DB 락만으로는 동시성을 제어하기 어렵거나 비효율적일 수 있습니다. 이때 Redis나 Zookeeper 같은 별도의 중앙 관리 시스템을 통해 잠금을 획득하고 해제합니다.동작 원리 (Redis 예시):재고를 수정하려는 서버가 Redis에 setnx(set if not exists) 명령어로 product:123:lock과 같은 고유한 키(Key)를 생성하려고 시도합니다.키 생성을 성공한 서버가 '잠금 획득'으로 간주하고 비즈니스 로직을 처리합니다.다른 서버들은 키가 이미 존재하므로 잠금 획득에 실패하고 대기하거나 재시도합니다.처리가 끝나면 해당 키를 삭제하여 잠금을 해제합니다.주의할 점락(Lock) 점유 시간 최소화: 락을 거는 시간이 길어지면 시스템 전체 성능이 급격히 저하됩니다. 트랜잭션 내에 PG사 연동이나 외부 API 호출처럼 시간이 오래 걸리는 로직이 포함되면 절대 안 됩니다.데드락(Deadlock) 가능성: 여러 데이터에 순서를 지키지 않고 락을 걸면 트랜잭션들이 서로를 기다리는 데드락 상태에 빠질 수 있어 주의가 필요합니다.(분산 락) 락 해제 보장: 잠금을 획득한 서버가 비즈니스 로직 처리 중 장애로 다운되면 잠금이 해제되지 않는 문제가 발생할 수 있습니다. 이를 방지하기 위해 잠금에 유효시간(TTL)을 설정하는 등의 추가적인 처리가 반드시 필요합니다.적용 사례사용자 개입 없이 서버 간 통신으로 빠른 처리가 가능한 경우여러 서버에 걸쳐있는 분산 환경에서 특정 작업(예: 선착순 쿠폰 발급)의 동시 실행을 막아야 할 때 3. 선착순 대기열 (Queueing)어떤 방식인가? 주문 요청이 들어오면 DB에 바로 반영하지 않고, Redis나 Kafka 같은 대기열 시스템에 요청을 먼저 쌓습니다. 별도의 처리기(Worker)가 대기열에서 요청을 하나씩 꺼내 순서대로 처리하며 재고를 차감합니다.주의할 점사용자 피드백 구현: 사용자는 자신이 대기열에 들어갔다는 사실과 예상 순번/시간 등을 알아야 합니다. 이를 위한 프론트엔드-백엔드 간의 실시간 통신(Polling, WebSocket 등) 구현이 필요합니다.시스템 복잡도 증가: Redis, 메시지 큐, 별도의 워커 프로세스 등 관리해야 할 시스템 구성요소가 늘어납니다.적용 사례인터파크 같은 콘서트, 스포츠 경기 티켓 예매 시스템나이키 드로우 같은 한정판 신발/의류 판매대학교 수강신청 시스템 일반적인 케이스는 위에 있는 사례들로 모두 커버될 것 같습니다. 사용자, 시스템이 느끼기에 불합리적이거나 비효율적인 부분이 각각의 방식에 다 존재합니다. 따라서 방식과 주의점을 확인해보고 우리 서비스에 적절한 방식을 선택하면 됩니다!혹시 추가적으로 궁금한 내용 있으면 추가 질문 남겨주세요!감사합니다.
- 1
- 2
- 18
Q&A
kibana > dicover 화면이 다르게 나와요
ewgregerg c님 안녕하세요!아마 ES에 아무 데이터도 없어서 (아무 인덱스가 없어서) 이렇게 나오는 것 같은데요, 혹시 앞선 단계에서 진행했던 ES에 로그를 쌓는걸 진행하신게 맞을까요?! ES에 아무 데이터도 색인하지 않은 상태에서는 지금 보고 계신것처럼 나오는게 정상입니다.한번 확인해보시고 추가 질문 주시면 답변 드리겠습니다!
- 0
- 2
- 15
Q&A
[데이터 버저닝을 활용한 멱등성 처리] 멱등성 보장을 위한 version 비교 질문
100and님 안녕하세요!제가 최근 인프런 질문글을 확인 못해서 답변이 늦었습니다. ㅠ 죄송합니다. 질문 주신 내용은 바로 직전에 다른분께서 질문주신 내용이랑 동일한 내용 같은데 한번 아래 질문-답변 읽어보시고 추가적으로 궁금한 내용 있으면 질문 남겨주세요!! https://inf.run/Dj9Hs 다시한번 너무 늦게 답변 드려 죄송합니다. (_ _)
- 1
- 2
- 41
Q&A
데이터 버저닝 질문
HAHA님 안녕하세요~우선 강의 잘 봐주시고, 좋은 질문 남겨주셔서 감사합니다. 날카로운 질문이네요. ㅎㅎ 단순히 이벤트 버전과 데이터베이스 버전을 비교해서 다르면 무시하는 방식만으로는, 동시에 발생하는 '동일한 상품에 대한 진짜 서로 다른' 재고 감소 요청 중 뒤에 발행되는 요청이 유실되는 문제가 발생할 수 있습니다.이 문제는 동일한 이벤트의 '중복 처리'를 막는 멱등성 문제와는 다른, 여러 유효한 요청이 경합하는 동시성 제어의 문제입니다. 문제 상황: 유효한 주문의 유실말씀하신 시나리오를 흐름으로 정리하면 다음과 같습니다.초기 상태: 상품 A의 재고는 10개, 데이터베이스(DB)의 버전은 5입니다.주문 1 발생: 프로듀서가 상품 A의 정보(버전 5)를 읽고, 재고 감소 이벤트(A)를 발행합니다.주문 2 발생: 거의 동시에, 아직 주문 1의 이벤트가 컨슈머에 의해 처리되기 전에, 다른 프로듀서가 상품 A의 정보(여전히 버전 5)를 읽고, 재고 감소 이벤트(B)를 발행합니다.컨슈머 처리:이벤트 A가 먼저 도착합니다. DB 버전(5)과 이벤트 버전(5)이 일치하므로 재고를 9로 감소시키고, DB 버전을 6으로 업데이트합니다. (성공)이벤트 B가 도착합니다. 이벤트에 담긴 버전은 5이지만, 현재 DB 버전은 6입니다. 버전이 다르므로 컨슈머는 이 요청을 무시합니다. (실패 및 유실)이 경우, 분명히 유효한 주문이었던 '주문 2'가 그냥 무시되어버리는 문제가 발생합니다.(이걸 물어보신게 맞겠죠? ㅎㅎ) 이 문제를 해결하려면 컨슈머의 로직이 더 정교해져야 합니다. 이 문제를 해결하는 가장 좋은 방법은 고유 ID를 사용한 멱등성 처리와 버전을 사용한 동시성 제어를 모두 적용하는 것입니다. 1단계: 멱등성 키(Idempotency Key)로 중복부터 확인모든 이벤트는 eventId나 orderId와 같이 절대 중복되지 않는 고유 ID를 가져야 합니다.컨슈머는 로직을 시작하기 전에, "이미 처리한 ID인지"를 별도의 processed_events 같은 테이블에 확인(INSERT 시도)합니다.만약 ID가 이미 있다면? → 이것은 '진짜 중복' 이벤트입니다. 즉시 처리를 중단하고 무시합니다. 이 단계에서 실제 중복 문제는 완벽히 걸러낼 수 있습니다.2단계: 버전으로 동시성 충돌 확인ID가 처음 들어온 것이라면? → 이제 이것은 '중복'이 아닌 '정상' 이벤트(순서가 밀렸을 수는 있는)임이 보장됩니다.이 상태에서 이전 답변에서 설명한 버전 비교 로직을 수행합니다.버전 일치: 첫 처리이므로 재고를 감소시킵니다.버전 불일치: 다른 정상 주문에 의해 순서가 밀린 것이므로, 현재 DB 상태를 기준으로 재고를 재확인하고 업데이트를 재시도합니다. 이러한 'ID로 중복을 먼저 거르고, 버전으로 순서를 제어하는 방법'을 통해, 질문해주신 상황에 대해 데이터 정합성을 지킬 수 있을겁니다. 본 영상에서는 동시성 제어보다는 장애 상황으로 인해 재시도 되는 등 중복 발행된 데이터에 대해 멱등성이 있는지에 포커스를 맞춰서 강의에서 이야기 한 것처럼 설명되었습니다! 이 질문글은 강의 노트에도 링크 추가해두겠습니다~혹시 또 궁금한 내용 있으면 질문 남겨주세요~!감사합니다!
- 1
- 2
- 39
Q&A
배포에대한 질의..
이경용님 안녕하세요~몇가지 방법이 있긴한데 혹시 DB 비밀번호 등 GitHub로 노출되지 않았으면 좋겠는 값(Secret 이라고 부릅니다)이 있어서 그런걸까요? 어떤 의도냐에 따라 방법이 달라질 것 같습니다~! 만약 수동배포 그 자체를 하고 싶으신거라면 로컬 개발환경에서 package 하여 jar 파일을 생성한 후 scp 등 명령어로 직접 서버에 업로드하여 실행시키는 방법도 가능합니다. 그게 아니라 Secret을 숨기고 싶은거라면,서버에 환경 변수를 설정해주거나Jenkins 등에서 배포할 때 스크립트로 주입시켜 주거나Vault 같은 시크릿 저장소를 활용하거나쿠버네티스(K8s) 같은걸 사용한다면 클러스터 내부의 Secret을 활용하는 방법 등 다양하게 있을 것 같습니다.혹시 어떤 의도인지 이야기해주시면 추가적으로 답변 드리겠습니다!
- 1
- 1
- 23
Q&A
안녕하세요 무중단 배포에대해 질문드립니다.
이경용님 안녕하세요!우선 강의 잘 봐주셔서 감사합니다. ncp나..ec2도 같은 원리일까요?-> 넵 동일하게 VM(가상 머신)을 클라우드 서비스를 이용해 생성하면 리눅스 운영체제가 설치되어있는 서버가 생성되는거고, 거기에서 우리가 실행시키고 싶은 자바 애플리케이션을 실행시키는겁니다. Blue-Green, Rolling Update이것을 좀 깊게 학습하고싶은데 추천해주실만한 학습자료가 있을까요?-> 해당 개념 자체를 깊게 학습할만한 자료는 저도 잘 모르겠네요 ㅎ... 각각의 개념은 꽤 심플한 개념입니다. 차라리 CD(지속적 배포) 그 자체에 대해 학습하시면 어떨까 생각되는데, 그런거라면 https://product.kyobobook.co.kr/detail/S000217112008 이 책도 괜찮을 것 같습니다. 또 만약에 리액트나 별도의 프론트를 추가할경우?서버 3개가 아니라.. 4개가 되는지 궁금합니다.-> 이건 구성하기 나름인데, 같은 서버에 올리는 것도 가능합니다. (스프링 부트 애플리케이션에 리액트 프론트엔드를 포함하는 것도 가능하고, 서로 다른 포트로 프론트엔드 서버를 띄우는 것도 가능) 다만 프론트엔드 개발, 유지보수 과정에서 백엔드 서버가 영향을 받지 않는게 더 유리하기 때문에 통상적으로 분리하여 운영하는게 일반적입니다. 따라서 서버 숫자가 더 늘어난다고 보셔도 될 것 같습니다! 궁금하신 내용에 대한 답변이 됐을까요? 궁금한 내용 있으면 추가로 질문 남겨주세요.감사합니다. :)
- 1
- 2
- 41
Q&A
수강 추천
이진아 님 안녕하세요!만약 배포 경험이 없으셨다면 다음 강의 먼저 수강해보시는걸 추천드립니다!포트폴리오 초간단 배포하기 https://inf.run/My8ci 스프링 부트 애플리케이션 베이스로 만들어진 강의인데, 아마 지금 강의보다 훨씬 쉬울겁니다.혹시 이전에 개발 경험 적어주시면 좀 더 타겟해서 다른 강의 추천드리겠습니다. :)
- 1
- 2
- 27
Q&A
복제 관련 질문입니다!
오래 기다리셨습니다. 일반적으로는 Primary-Replica 간의 복제 지연이 크게 문제가 되진 않지만, 만약 신경 써야하는 상황이라면 근본적인 DB 복제 지연 시간 줄이기 '방금 글 쓴 사용자(시스템)'의 읽기 요청은 Primary DB로 보내주기위 2가지 방법이 함께 적용되면 좋을 것 같습니다.1번은 복제 지연 시간을 줄여 가급적 복제 지연으로 인한 데이터 불일치가 발생하지 않도록 하는겁니다. 방법은 여러가지겠지만, DB 서버들의 사양을 올리고 쿼리 튜닝, 병렬 복제 등 다양한 수단을 활용하면 됩니다. 다만 이 부분은 백엔드 개발자보다는 DBA 레벨에서 다뤄야할 내용들 인 것 같아요. 그럼 2번은 복제 지연이 발생하면 안되는 요청과 아닌 요청을 구분하여 복제 지연이 발생하면 안되는 요청에 대해선 읽기 연산도 Primary에서 이루어지도록 하는겁니다. 이 때에는 당연히 사용자나 시스템을 구분할 수 있는 Key를 두어 구분해야하고, 시스템마다 공유할 수 있게 Redis 같은 공유 저장소를 활용해야합니다.그리고 스프링 부트 애플리케이션 기준으로 DataSource 를 Primary와 Replica 양쪽에 대해 설정해주고, 요청에 따라 읽기 연산이지만 Primary로 연결해야할 요소를 구분해줘야합니다. AOP를 활용하면 좋겠죠?다만 이렇게 설정하는게 정말 우리 시스템에 필요한지 검토해볼 필요가 있습니다. DataSource 설정이 두개가 되는 것도 설정의 복잡함을 만들고, 일반적으로 Primary-Replica 구조에서 사용하는 DB Proxy를 활용한 자동 Failover가 동작하지 않을 수도 있습니다. 애플리케이션 레벨에서 Failover를 직접 처리해줘야할 수도 있어요. 이런 불편함을 감수할 필요가 있는지 검토가 필요합니다. 제가 대략 알고있는, 경험해본 내용은 이정도인데 답변이 됐을까요? 추가적으로 궁금한 내용 있으면 질문 남겨주세요~ :)
- 1
- 2
- 74
Q&A
복제 관련 질문입니다!
공부맛있다님 안녕하세요! 좀 더 구체적으로 복제 지연 때문에 어떤게 문제가 되는지 이야기 해주시면 저도 같이 고민해볼 수 있을 것 같습니다~DB 레벨에서의 복제 지연에 대한 내용일까요~?어쩌면 CAP 이론에 대한 내용 읽어보시면 궁금하셨던 내용을 해소하거나 좀 더 구체화시켜서 질문주실 수 있을 것 같습니다!한번 확인해보시고 마저 질문 남겨주세요~
- 1
- 2
- 74
Q&A
현업에서 서킷브레이커 상태 전파를 할 때 Actuator를 사용 하시는지 궁금합니다!
드루와라잇님 안녕하세요~다른 인스턴스들로 서킷 브레이커의 상태를 전파하기 위해서는 Kafka 같은 메시지큐나 Spring Cloud Config 같은 분산 설정 관리 도구를 사용합니다. Actuator는 특정 인스턴스의 서킷 브레이커 상태를 확인하거나 강제로 변경하기위해서는 활용할 수 있지만, 상태 전파가 목적이라면 메시지큐나 분산 설정 관리 도구를 활용하는게 좋습니다~ 서킷 브레이커 상태를 전파하는 상황에 대해 경험을 이야기 드리자면, '추천' 로직을 수행하기 위해 여러 머신러닝, 딥러닝 모델을 호출하곤 하는데요, 일부 모델이 높은 부하를 받아서 응답이 느려지거나 분석에 실패하는 경우 해당 모델로 가는 서킷을 OPEN 시키는 상황이 있었습니다. 궁금하셨던 내용에 대한 답변이 됐을까요?또 궁금한 내용 있으면 질문 남겨주세요.감사합니다.
- 1
- 1
- 40