안녕하세요.
멘토링을 하면서 주니어 개발자들이 어려워 하는 개념들에 대해 어떻게 하면 쉽게 전달할 수 있을지에 대해서 많은 고민을 하고 있는 푸(Foo)라고 합니다.
잘 부탁 드리겠습니다.
이력
2019. 08 ~ 현재 : 카카오 자바 백엔드 개발자
2021. 08 ~ 현재 : programmers 백엔드 데브코스 멘토
2021. 12 ~ 현재 : F-Lab 자바 백엔드 멘토
책
이것이 취업을 위한 백엔드 개발이다 with 자바(링크)
기타 이력 및 타 플랫폼 강의들은 아래 GitHub 링크에서 확인할 수 있습니다.
GitHub - https://github.com/lleellee0
Khóa học
Đánh giá khóa học
- Chiến lược triển khai và mẹo để triển khai dịch vụ ổn định
- Xây dựng hệ thống mạnh mẽ cho phép lỗi
- Xây dựng hệ thống mạnh mẽ cho phép lỗi
- Kiểm tra hiệu suất ứng dụng phụ trợ
- Xây dựng hệ thống mạnh mẽ cho phép lỗi
Bài viết
Hỏi & Đáp
카프카 질문
ssunn0812님 안녕하세요~우선 답변이 늦어서 죄송합니다. (_ _) 질문 주신 내용에 대해 답변드려보겠습니다. 실무에서는 이 문제를 해결하기 위해 여러 가지 전략을 조합해서 사용합니다. 1. 컨슈머의 '처리 속도' 자체를 조절하기가장 기본적이고 직접적인 방법입니다. DB가 처리할 수 있는 양만큼만 컨슈머가 작업을 수행하도록 조절하는(Throttling) 것입니다.배치 크기 조절 (max.poll.records): 카프카 컨슈머는 한 번에 여러 개의 메시지(배치)를 가져와서 처리합니다. 이 max.poll.records 옵션 값을 의도적으로 낮게 설정(예: 500개 -> 50개)하면, 한 번의 루프에서 DB로 보내는 INSERT 쿼리의 수가 줄어듭니다. 이는 DB의 부하를 즉각적으로 낮춰주는 가장 간단한 튜닝 방법입니다.컨슈머 사이드 Rate Limiting: 컨슈머 애플리케이션 코드 내에 Google Guava의 RateLimiter 같은 라이브러리를 사용하여 "초당 1000개의 트랜잭션만 처리"하도록 명시적으로 제한을 걸 수 있습니다. 2. 'Backpressure'를 구현하여 능동적으로 방어하기단순히 속도를 줄이는 것을 넘어, DB의 '상태'를 확인하고 컨슈머의 동작을 일시적으로 멈추는, 더 지능적인 방법입니다.Circuit Breaker 적용 : 강의의 핵심 주제인 '견고한 시스템'과 직결됩니다. 컨슈머가 DB에 INSERT를 시도할 때, DB에서 커넥션 타임아웃이나 응답 지연 같은 오류가 일정 비율 이상 발생하면 Circuit Breaker를 'Open' 상태로 전환합니다.pause()와 resume()의 활용: Circuit Breaker가 Open이 되었을 때가 중요합니다. 이때 컨슈머는 단순히 에러를 로그에 남기고 다음 메시지를 처리하려 하면 안 됩니다. (그러면 DB는 계속 공격당하겠죠.) 대신, 카프카 컨슈머의 pause() 메서드를 호출해야 합니다.consumer.pause()가 호출되면, 컨슈머는 브로커에게 "나 지금 바쁘니(혹은 내 뒷단이 아프니) 메시지를 더 이상 주지 마"라고 신호를 보냅니다.컨슈머는 브로커로부터 새로운 메시지를 받아오지 않고(poll X), Circuit Breaker가 닫힐 때까지(예: 1분 뒤) 대기합니다.이후 DB 상태가 정상으로 돌아와 Circuit Breaker가 'Close'되면, 그때 consumer.resume()을 호출하여 다시 메시지 처리를 시작합니다.이 pause()/resume()와 Circuit Breaker의 조합이 DB 과부하를 막는 가장 세련되고 효과적인 실무 기법입니다. 3. 실패한 메시지 처리 및 재시도 전략트래픽 급증으로 인해 DB가 처리하지 못한 메시지는 어떻게 해야 할까요?재시도 최대 횟수 제한: DB가 아파서 실패한 요청을 컨슈머가 곧바로 재시도(retry)하면, 이는 불난 집에 부채질하는 격입니다. DB 부하를 더욱 가중시켜 '재시도 폭풍(Retry Storm)'을 일으킵니다.Dead Letter Queue (DLQ): 일반적으로 3회 정도의 재시도(exponential backoff 적용) 후에도 실패하는 메시지는, 처리를 포기하고 별도의 'Dead Letter Queue (DLQ)' 토픽으로 보냅니다.이렇게 하면 컨슈머는 일단 해당 메시지의 오프셋을 커밋(commit)하고 다음 메시지를 처리할 수 있게 되어, 전체 파이프라인이 막히는 것을 방지합니다.DLQ로 간 메시지들은 나중에 개발자가 원인을 분석하거나, DB 부하가 적은 새벽 시간에 별도의 배치 작업으로 재처리할 수 있습니다. 요약하자면,실무에서는 1) max.poll.records 같은 옵션으로 기본 처리량을 튜닝하고, 2) DB 상태를 모니터링하는 Circuit Breaker를 구현하며, 3) DB 장애 시 pause()를 호출하여 컨슈머를 능동적으로 멈추는(Backpressure) 방식을 가장 많이 사용합니다. 그리고 4) 반복적으로 실패하는 메시지는 DLQ로 격리하여 시스템 전체의 안정성을 확보합니다.이러한 장치들을 통해 트래픽이 급증하더라도 카프카 토픽에 메시지가 좀 쌓일지언정(Lag 발생), 최종 관문인 DB가 다운되는 최악의 장애 상황을 방지할 수 있습니다. 다만 시스템 요구사항에 따라 위 내용이 적용 불가능한 상황도 있을겁니다. 상황에 따라 적절한 방식을 도입해야하고, 필요하다면 DB가 받는 부하를 분산하는 방법도 적용해보면 좋습니다. DB 부하 분산 전략을 위한 핵심 키워드들은 다음과 같습니다.Read / Write 분리 (CQRS)데이터베이스 복제 (Replication): Read 부하 분산을 위한 'Read Replica(읽기 전용 복제본)' 활용데이터베이스 샤딩 (Sharding / Partitioning): Write 부하의 근본적인 분산캐시 (Cache) 활용: Redis, Memcached 등을 이용해 DB 조회 자체를 줄이기 혹시 질문에 대한 답변이 됐을까요?추가적으로 궁금한 내용 있으면 질문 남겨주세요.감사합니다.
- 1
- 2
- 25
Hỏi & Đáp
안녕하세요 혹시 multipart request요청일때는 파라미터가 손실 되시지 않는가요??
강현수님 안녕하세요~ 음.. 강의에서는 multipart request 관련해서는 다루지 않았던 것 같은데 혹시 문제되는게 있으신가요?multipart request 자체가 일반 요청과는 다르기 때문에 당연히 강의에서 진행한 코드 만으로는 정상적으로 동작하지 않을 수 있습니다.혹시 문제 겪고 있으신 상황 좀 더 자세히 설명해주시면 도움 드릴 수 있을 것 같습니다. 😄 감사합니다.
- 1
- 2
- 18
Hỏi & Đáp
Artillery에서 VUSER는 어떻게 측정되는 걸까요?
김형준님 안녕하세요!우선 답변이 늦어서 죄송합니다. (_ _) 질문 주신 내용에 대해 답변드리겠습니다! Artillery에서 VUser(가상 유저)는 '하나의 정해진 시나리오(사용자 여정)를 수행하는 독립적인 행위자'로 정의됩니다.예를 들어, "1. 로그인한다 → 2. 상품 목록을 조회한다 → 3. 특정 상품을 장바구니에 담는다"라는 3개의 API 요청으로 구성된 하나의 '시나리오'가 있다고 가정해 보죠.Artillery의 VUser 1명은 이 3단계의 흐름 전체를 처음부터 끝까지 수행하는 '가상의 사용자 1명'을 의미합니다. 단순히 요청 1개를 보내는 존재가 아닙니다. 여기서 nGrinder와의 결정적인 차이가 나옵니다.김형준님께서 언급하신 nGrinder의 VUser = (프로세스 수) * (스레드 수) 공식은 '동시에 실행될 스레드의 총합'을 의미합니다. 즉, "총 500개의 스레드(VUser)를 띄워서 계속 요청을 보내라"는 방식(찾아보니 이걸 Closed Model이라고 부르더라구요)에 가깝습니다. VUser가 스레드라는 리소스와 강하게 연결되어 있죠.하지만 Artillery는 (k6나 Gatling처럼) '초당 몇 명의 새로운 VUser가 도착(Arrival)할 것인가'를 설정하는 방식(반대로 이 방식은 Open Model이라고 부른답니다)을 주로 사용합니다.Artillery 설정 파일에서 핵심은 concurrency (동시 접속자 수) 보다는 arrivalRate (초당 도착률)입니다.즉, arrivalRate: 10 이라고 설정하면, 매초 10명의 새로운 VUser가 시스템에 도착해서 각자의 시나리오(로그인 -> 조회 -> 장바구니)를 수행하기 시작한다는 의미입니다. 혹시 질문에 대한 답변이 됐을까요?!추가적으로 질문 있으시면 질문 남겨주세요~감사합니다.
- 1
- 2
- 18
Hỏi & Đáp
안녕하세요. 타임아웃 시간에 관하여 질문있습니다.
정인호님 안녕하세요!우선 답변이 늦어서 죄송합니다. (_ _) 질문주신 내용에 대해 답변드리자면, 타임아웃을 설정하고 테스트하는 것은 '정답'이 있다기보다는, 시스템의 특성과 비즈니스 요구사항, 그리고 장애 전파를 막기 위한 전략에 따라 결정됩니다. 실무에서 일반적으로 이 문제를 어떻게 접근하는지 '결정'하는 과정과 '테스트'하는 과정으로 나누어 설명해 드리겠습니다. 1. 타임아웃 시간 '결정'하기먼저 타임아웃 시간을 '결정'하는 방법입니다. 가장 중요한 것은 감이 아니라 데이터를 기반으로 판단하는 것입니다.실무에서는 Datadog이나 New Relic 같은 APM(모니터링 툴)을 통해 실제 서비스의 응답 시간을 확인합니다. 이때 '평균 응답 시간'이 아니라 'p95 또는 p99 백분위수'를 기준으로 삼는 것이 핵심입니다.예를 들어, 어떤 API의 p99 응답 시간이 800ms라면, 이는 "전체 요청의 99%가 800ms 안에 처리되지만, 1%는 그보다 오래 걸린다"는 뜻이죠. 이 경우 타임아웃을 1초(1000ms) 정도로 설정하는 것을 고려해볼 수 있습니다. 99%의 정상 요청은 허용하되, 비정상적으로 지연되는 1%의 요청은 '실패'로 간주하고 빠르게 연결을 끊어내는 것입니다. 이것이 바로 장애가 다른 시스템으로 전파되는 것을 막는 첫걸음입니다.물론 데이터만 보는 것은 아닙니다. 비즈니스 요구사항과 사용자 경험(UX)도 중요합니다. 사용자가 화면에서 직접 응답을 기다리는 '상품 목록 조회' 같은 기능이라면 1~3초 이내로 매우 짧게 잡아야 하지만, 사용자가 즉각적인 결과를 보지 않는 '야간 배치 통계' 작업이라면 30초나 1분 이상으로 길게 설정할 수도 있습니다.또한, 우리가 호출하는 대상이 결제 API처럼 외부 서드파티 서비스라면, 해당 업체가 제공하는 SLA(서비스 수준 협약) 문서를 확인해야 합니다. 그들이 "3초 이내 응답 보장"이라고 명시했다면, 우리도 그에 맞춰 3~5초 정도로 설정하는 것이 합리적이겠죠.마지막으로 강의에서 배운 '장애 전파 방지' 개념이 여기서 중요하게 쓰입니다. 시스템 전체의 '타임아웃 예산'을 고려해야 합니다. 예를 들어, 사용자 요청이 A(앱서버)를 거쳐 B(인증서버), 그리고 C(DB)로 전달된다고 해보죠. 만약 A의 최종 타임아웃이 3초라면, A가 호출하는 B는 2초, B가 호출하는 C는 1초처럼, 요청의 끝단으로 갈수록 타임아웃을 더 짧게 설정하는 것이 좋습니다. 이렇게 해야 C에서 2.5초가 걸려도 B가 2초 시점에 이미 타임아웃 처리를 해버리기 때문에, 장애가 A까지 거슬러 올라와 전체 시스템을 마비시키는 것을 막을 수 있습니다.2. 타임아웃 '테스트'하기다음으로, 이렇게 결정한 타임아웃을 어떻게 '테스트'하는지 말씀드릴게요. 설정한 값이 잘 동작하는지, 그리고 타임아웃이 발생했을 때 우리 시스템이 의도대로 반응하는지 검증하는 것은 매우 중요합니다.가장 기본은 단위 테스트나 통합 테스트 단계에서 Mock(가짜 객체)을 활용하는 것입니다. 테스트 코드를 작성할 때 실제 외부 API나 DB를 호출하는 대신, 'Mock' 객체가 설정한 타임아웃 시간(예: 1초)보다 일부러 더 늦게(예: 2초) 응답하도록 조작합니다.그리고는 정말로 1초 뒤에 TimeoutException 같은 예외가 발생하는지, (그리고 이것이 정말 중요한데) 타임아웃 발생 시 사용자에게 에러를 그대로 보여주는 것이 아니라 "잠시 후 다시 시도해주세요" 같은 준비된 '폴백(Fallback) 로직'이 잘 실행되는지 반드시 검증해야 합니다.여기서 더 나아가 부하 테스트도 진행합니다. nGrinder나 k6 같은 툴을 사용해 개발(Staging, 부하를 테스트하기 위한 환경으로 Prod 환경과 동일하게 세팅) 환경에 대규모 트래픽을 가해봅니다. 호출되는 서비스가 과부하로 느려지기 시작할 때, 우리 서비스에 설정된 타임아웃이 실제로 동작하는지, 그리고 시스템 전체가 마비되지 않고 버텨내는지(견고성) 확인합니다. 혹시 질문에 대한 답변이 됐을까요?!추가적으로 궁금한 내용 있으면 질문 남겨주세요~감사합니다.
- 1
- 2
- 30
Hỏi & Đáp
분산 시스템 인증/인가 관련 질문 ..
아자님 안녕하세요~우선 답변이 늦어져서 죄송합니다. 제가 분산환경에서 인증/인가에 대해 잘 아는건 아니지만(저는 주로 내부에서 분산 시스템간 통신은 많이 처리해봤지만, 사용자와 외부 시스템이 엮여있는 상황은 API 게이트웨이 관련 개발하시는분이 잘 아실듯하네요 ㅎ..), 질문주신 내용에 대해 알고있는 내용으로 답변드리자면, 1⃣API 인증 전파 관련우리 서버가 회사1·2 서버로 요청을 보낼 때,상대 서버에서는 “이 요청이 실제 인증된 사용자로부터 온 것”임을 어떻게 검증하는 게 일반적인가요? -> 이 문제의 핵심은 "회사1·2의 API가 '우리 서버'를 신뢰할 수 있는가?"와 "신뢰하는 '우리 서버'가 '특정 사용자'를 대신해 요청한 것임을 어떻게 증명하는가?"입니다.여기에는 크게 두 가지 접근 방식이 있습니다. 먼저 'Trusted Subsystem (신뢰할 수 있는 하위 시스템) 모델'인데, 가장 간단하고 많이 쓰이는 방식입니다. 내부에서 통신하는 시스템들도 일반적으로 이 방식을 활용합니다. 외부 회사랑 어떤 관계에 있는지 모르겠지만, 원활하게 커뮤니케이션 할 수 있고, 우리쪽과 인증/인가 방식을 협의할 수 있는거라면 이 방식이 적절할 것 같습니다.서버 간 인증: '우리 서버'는 '회사1·2'와 미리 약속된 API Key, Client ID/Secret 등을 사용하여 서버 자체를 인증합니다.사용자 식별자 전달: '우리 서버'는 API 요청의 본문(Body)이나 헤더(Header)에 "이 요청은 '사용자 A'를 위한 것입니다"라는 사용자 ID를 포함하여 전송합니다.검증: '회사1·2'의 서버는 일단 API Key 등을 통해 '우리 서버'가 신뢰할 수 있는 출처임을 확인합니다. 그리고 '우리 서버'가 이미 사용자 인증을 완료했을 것이라고 신뢰하고, 함께 전달된 '사용자 ID'를 기반으로 비즈니스 로직을 처리합니다. 또 다른 방식은 'OAuth 2.0 (위임 인증 표준)'을 사용하는 방식인데, 회사1·2에서 OAuth 2.0을 제공하는지가 확인해보셔야 할 것 같습니다. OAuth 2.0에 대한 내용은 제가 따로 설명드릴 필요 없이 관련된 내용을 찾아보시면 나올 것 같습니다.2⃣브라우저 SSO 관련새 탭을 열어 회사2 웹 서비스로 이동 시,재로그인 없이 자동으로 인증(Single Sign-On) 되게 하려면 어떤 방식이 많이 사용되나요? -> OAuth 2.0 기반으로 만들어진 OIDC (OpenID Connect)를 사용하는게 일반적입니다. 이것도 이미 일반적으로 알려져있는 프로토콜이라서 제가 따로 설명드릴 필요는 없을 것 같습니다.다만 이런 프로토콜을 도입하기 어려운 상황이고, 일회성으로 사용할만한 기능을 원하는거라면 아래와 같이 JWT 문자열을 파라미터로 넘기는 방법도 활용해볼 수 있습니다. https://company2.com/sso/jwt-login?token=eyJhbGciOi... 질문에 대한 답변이 됐을까요? 혹시 또 궁금한 내용 있으면 질문 남겨주세요.감사합니다.
- 1
- 2
- 30
Hỏi & Đáp
안녕하세요 주문처리에 관하여 질문있습니다 ㅠ ㅁ ㅜ
정인호님 안녕하세요!우선 좋은 질문 주셔서 감사합니다. 말씀하신 것처럼 상황에 따라 데이터 일관성을 맞추기 위한 로직들이 비효율적, 비합리적이라고 느껴지는 상황이 분명 있습니다.데이터 일관성을 맞추기 위한 여러가지 방법들 중 어떤 하나의 방식이 절대적으로 좋은 것은 없으며, 비즈니스 요구사항과 트래픽 패턴에 따라 최적의 해법이 달라집니다. 크게 세 가지 상황으로 나누어 어떤 전략을 사용하는지 먼저 말씀드리겠습니다.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, 메시지 큐, 별도의 워커 프로세스 등 관리해야 할 시스템 구성요소가 늘어납니다.적용 사례인터파크 같은 콘서트, 스포츠 경기 티켓 예매 시스템나이키 드로우 같은 한정판 신발/의류 판매대학교 수강신청 시스템 일반적인 케이스는 위에 있는 사례들로 모두 커버될 것 같습니다. 사용자, 시스템이 느끼기에 불합리적이거나 비효율적인 부분이 각각의 방식에 다 존재합니다. 따라서 방식과 주의점을 확인해보고 우리 서비스에 적절한 방식을 선택하면 됩니다!혹시 추가적으로 궁금한 내용 있으면 추가 질문 남겨주세요!감사합니다.
- 2
- 2
- 49
Hỏi & Đáp
kibana > dicover 화면이 다르게 나와요
ewgregerg c님 안녕하세요!아마 ES에 아무 데이터도 없어서 (아무 인덱스가 없어서) 이렇게 나오는 것 같은데요, 혹시 앞선 단계에서 진행했던 ES에 로그를 쌓는걸 진행하신게 맞을까요?! ES에 아무 데이터도 색인하지 않은 상태에서는 지금 보고 계신것처럼 나오는게 정상입니다.한번 확인해보시고 추가 질문 주시면 답변 드리겠습니다!
- 0
- 2
- 27
Hỏi & Đáp
[데이터 버저닝을 활용한 멱등성 처리] 멱등성 보장을 위한 version 비교 질문
100and님 안녕하세요!제가 최근 인프런 질문글을 확인 못해서 답변이 늦었습니다. ㅠ 죄송합니다. 질문 주신 내용은 바로 직전에 다른분께서 질문주신 내용이랑 동일한 내용 같은데 한번 아래 질문-답변 읽어보시고 추가적으로 궁금한 내용 있으면 질문 남겨주세요!! https://inf.run/Dj9Hs 다시한번 너무 늦게 답변 드려 죄송합니다. (_ _)
- 1
- 2
- 59
Hỏi & Đáp
데이터 버저닝 질문
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
- 52
Hỏi & Đáp
배포에대한 질의..
이경용님 안녕하세요~몇가지 방법이 있긴한데 혹시 DB 비밀번호 등 GitHub로 노출되지 않았으면 좋겠는 값(Secret 이라고 부릅니다)이 있어서 그런걸까요? 어떤 의도냐에 따라 방법이 달라질 것 같습니다~! 만약 수동배포 그 자체를 하고 싶으신거라면 로컬 개발환경에서 package 하여 jar 파일을 생성한 후 scp 등 명령어로 직접 서버에 업로드하여 실행시키는 방법도 가능합니다. 그게 아니라 Secret을 숨기고 싶은거라면,서버에 환경 변수를 설정해주거나Jenkins 등에서 배포할 때 스크립트로 주입시켜 주거나Vault 같은 시크릿 저장소를 활용하거나쿠버네티스(K8s) 같은걸 사용한다면 클러스터 내부의 Secret을 활용하는 방법 등 다양하게 있을 것 같습니다.혹시 어떤 의도인지 이야기해주시면 추가적으로 답변 드리겠습니다!
- 1
- 1
- 26






