inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

뉴노멀님의 게시글

뉴노멀 뉴노멀

@newnormal

수강생
160
수강평
11
강의 평점
4.7

게시글 5

질문&답변

미션 진행 방식에 대한 질문입니다.

안녕하세요, 꼼꼼히 확인해 주셔서 감사합니다. 말씀하신 게 맞습니다. 챌린지를 생성하는 과정에서 제가 실습 자료를 잘못 올라간 걸 지금 확인했습니다. (현재는 수정했습니다.) 처음 첨부한 ai-handson-v1.1.zip 에 해설편 촬영을 마친 뒤의 폴더가 들어갔습니다. 그래서 module3, 4, 5, 7, 8 은 구현이 끝난 코드였고, 3, 4, 5, 7 의 CLAUDE.md 에는 촬영하면서 추가한 금지 조항까지 남아 있었습니다. 1주차 module2 는 정상이었으니 지난주 진행하신 건 문제없습니다. 시작 상태로 다시 묶은 ai-handson-v1.1-starter.zip 을 미션 첨부에 올렸습니다. 압축을 풀면 ai-handson-v1.1-starter 폴더가 나오고, module3 에서 Redis 를 띄운 뒤 ./gradlew test 를 돌리면 4개가 모두 실패해야 맞습니다. 모듈별 확인 방법은 공지에 정리해 두었습니다. 미리 말씀드리면, 3주차 module4 는 README 에 "7개 테스트가 실패해야 정상" 이라고 적혀 있지만 실제로는 6개만 실패합니다. 키 누락(400)과 없는 결제(404) 테스트는 컨트롤러가 처리해서 처음부터 통과합니다. 이번에는 정상이니 놀라지 않으셔도 됩니다. 이미 보신 금지 조항은 새 스타터로 직접 키운 CLAUDE.md 와 나중에 비교해 보셔도 좋습니다. 같은 자리를 잡았는지, 다른 걸 잡았는지 보는 것도 공부가 됩니다. 덕분에 다른 분들이 헛걸음하기 전에 바로잡을 수 있었습니다. 감사합니다.

좋아요수
0
댓글수
1
조회수
31

질문&답변

파킹 페이지와 대기열 큐 질문입니다.

안녕하세요. 좋은 질문입니다. 세 개 다 실제로 만들 때 고민하는 지점이라 순서대로 답변드리겠습니다. 먼저 한 가지만 짚어두면, 강의에서 보여드린 도면은 제가 참여했던 프로젝트를 공개 가능한 수준으로 재구성한 것입니다. 회사 내부 구현을 그대로 옮긴 건 아니라서, "그 회사가 정확히 이랬다"보다는 "이런 구조에서 어떤 선택지가 있고 무엇을 포기하게 되는가"로 답변드리겠습니다. 1. 직접 만드는가, 기성 솔루션을 쓰는가 둘 다 씁니다. 판단 기준은 보통 이겁니다. 기성 솔루션(Cloudflare Waiting Room, AWS의 Virtual Waiting Room 템플릿, Queue-it 같은 상용 서비스)은 발매 이벤트가 1년에 몇 번 없고, 그때만 트래픽이 수십 배 뛰는 경우에 유리합니다. 대기열은 평소에 안 쓰다가 제일 중요한 날에 처음 돌아가는 컴포넌트라, 직접 만들면 "그날 처음 터지는" 위험이 큽니다. 직접 만드는 건 발매가 일상이고(매일 드롭이 있다거나) 대기 화면을 서비스 브랜드에 맞춰 세밀하게 통제하고 싶을 때입니다. Redis의 Sorted Set이나 Stream으로 순번을 관리하고 입장 토큰을 발급하는 수준이면 구조 자체는 복잡하지 않습니다. 어려운 건 만드는 게 아니라 민원/운영 대응이나 장애 대응입니다. 2. 대기열은 어디에 있는가 WAS 안쪽은 안 됩니다. 이게 핵심입니다. 필터나 인터셉터로 막으면 이미 톰캣 스레드와 커넥션을 하나 점유한 뒤에 "기다리세요"를 응답하는 겁니다. 10만 명이 몰리면 대기열이 있으나 없으나 WAS는 똑같이 죽습니다. 앞단에서 막는다는 말의 의미가 "WAS에 요청이 도달하기 전에 끊는다"여야 합니다. 그래서 보통 이렇게 나눕니다. - 파킹 페이지 자체는 정적 파일이라 CDN에서 내려줍니다. 오리진 부하가 0입니다. - 입장 토큰 검사는 CDN의 엣지 함수나 API 게이트웨이에서 합니다. 토큰이 없으면 애플리케이션까지 못 갑니다. - 순번과 입장 토큰 같은 상태만 Redis에 둡니다. 주의하실 점은 대기열 컴포넌트 자체가 단일 장애점이 된다는 겁니다. 대기열이 죽으면 아무도 못 들어옵니다. 대기열이 죽었을 때 전원 통과로 열어줄지 전원 차단으로 막을지를 미리 정해두셔야 합니다. 3. 나간 걸 어떻게 감지하는가 결론부터 말씀드리면, 정확히는 감지 못 합니다. 그래서 대부분 감지하지 않는 쪽으로 설계합니다. 창을 닫는 건 사실상 감지가 안 됩니다. 브라우저 종료 시점에 신호를 보내는 방법이 있긴 한데 모바일에서는 거의 안 날아옵니다. 그래서 이걸 전제로 만들면 유령 세션이 쌓여서, 실제로는 아무도 없는데 "정원이 찼다"고 판단해 입장이 막히는 상황이 생깁니다. 실무에서는 두 가지를 씁니다. - 입장 토큰에 TTL을 겁니다. 예를 들어 10분짜리 토큰을 주고, 결제 완료되면 즉시 회수, 아니면 10분 뒤 자동 만료입니다. 명시적 퇴장 대신 만료로 처리하는 겁니다. 3-5에서 본 TTL 재고 복구와 같은 발상입니다. - 동시 접속 인원을 맞추는 대신 입장 속도를 조절합니다. "안에 1,000명 유지"가 아니라 "초당 50명씩 넣는다"입니다. 질문에 쓰신 두 번째 방식이 이쪽이고, 실제로 훨씬 안정적입니다. 유령 세션 문제가 아예 없고, 뒷단이 버티는 속도를 그대로 숫자로 쓸 수 있습니다. 그러면 초당 몇 명이 맞느냐가 남는데, 이건 미리 정하는 게 아니라 부하 테스트로 찾습니다. 뒷단 응답시간 p95와 DB 커넥션 사용률을 보면서 올려보다가 꺾이는 지점 바로 아래로 잡습니다. 운영 중에는 이 지표를 보고 입장 속도를 자동으로 조절하기도 합니다. 감사합니다.

좋아요수
0
댓글수
1
조회수
39

질문&답변

구현 방법에 대한 문의

안녕하세요, 좋은 질문 감사합니다. 먼저 붙여넣기 방식에 대해 말씀드리면, 타이핑하는 시간을 줄이고 "왜 이렇게 판단했는가"에 시간을 쓰려고 그렇게 했습니다. 스타터 코드에 TODO 주석으로 채울 자리를 표시해 뒀으니 영상을 멈추고 직접 채워보실 수 있습니다. 질문하신 두 방식 중 하나를 고르실 필요는 없습니다. 강의에 둘 다 들어 있습니다. 앞쪽 실습 레슨들(2-3, 2-4, 7-2~7-4, 8-3 등)은 손으로 채우는 스타터입니다. 그리고 각 모듈 마지막에 AI Hands-on 레슨이 하나씩 있습니다(2-7, 3-7, 4-7, 5-6, 6-7, 7-7, 8-9). 이쪽은 손으로 타이핑하지 않고, 모듈에서 배운 판단을 CLAUDE.md에 제약으로 적어 에이전트에게 구현시킨 뒤 테스트와 k6로 검증하고 비판합니다. 어제 추가된 레슨이라 아직 안 보셨을 수도 있습니다. 권하는 순서는 이렇습니다. 1. 앞쪽 실습은 영상을 멈추고 직접 타이핑하세요. 손으로 해봐야 어디서 막히는지, 왜 그 순서인지가 몸에 남습니다. 막히면 영상을 재생해서 제 구현과 대조하세요. 2. 그다음 AI Hands-on 레슨으로 같은 주제를 에이전트에게 시켜보세요. 같은 문제를 두 번 푸는 셈인데, 두 번째는 "구현"이 아니라 "지시하고 검증하기"입니다. [AI에게 시키는 방법 요약 - AI Hands On 실습 참조] ❌ 이 코드 어때? 개선점 알려줘 ✅ 이 코드가 아래 기준을 지키는지 파일과 줄로 지목해서 알려줘. (1) 확인과 차감이 한 번의 원자 연산 안에서 끝난다 (2) JVM 락을 쓰지 않는다: 서버가 두 대가 되면 무의미하다. (3) 실패는 예외가 아니라 결과 타입으로 돌려준다 감사합니다!

좋아요수
0
댓글수
2
조회수
74

질문&답변

안녕하세요 질문있습니다.!

노트북의 H2나 로컬 MySQL로 잰 값은 참고용입니다. 실제 Mysql의 경우 저장되어 있는 레코드 수에 따라서도 편차가 있습니다. k6로 테스트할 API를 높은 속도로 때리면서 Kafka consumer lag을 봅니다. lag이 계속 늘면 컨슈머가 못 따라가는 것이고, lag이 일정하게 유지되는 최대 발급 속도가 시스템 전체의 처리량입니다.

좋아요수
0
댓글수
2
조회수
68

질문&답변

안녕하세요 질문있습니다.!

안녕하세요!! 답변 드립니다. 1. 재는 대상은 컨슈머가 아니라 "DB 쓰기 경로"입니다 k6는 HTTP를 두드리는 도구라 Kafka 컨슈머를 직접 재지 못합니다. 대신 컨슈머가 DB에 하는 일(주문 INSERT + 재고 UPDATE, 같은 트랜잭션)을 그대로 실행하는 테스트용 엔드포인트를 하나 만들고, 그걸 k6로 두드립니다. 그러면 "이 DB가 이 쓰기를 초당 몇 건까지 받아주는가"가 나오고, 그 숫자가 컨슈머 쓰로틀의 상한입니다. 2. VU 고정이 아니라 "초당 요청 수를 계단식으로 올리는" 실행기를 씁니다 constant-vus 는 응답이 느려지면 요청 속도도 같이 느려져서 한계가 안 보입니다. ramping-arrival-rate 로 50 → 100 → 200 → 400 → 800 req/s 계단을 올리면서 어느 계단에서 꺾이는지 봅니다. import http from 'k6/http'; export const options = { scenarios: { find_knee: { executor: 'ramping-arrival-rate', startRate: 50, timeUnit: '1s', preAllocatedVUs: 50, maxVUs: 500, stages: [ { target: 50, duration: '1m' }, { target: 100, duration: '1m' }, { target: 200, duration: '1m' }, { target: 400, duration: '1m' }, { target: 800, duration: '1m' }, ], }, }, thresholds: { http_req_duration: ['p(95)

좋아요수
0
댓글수
2
조회수
68