-
Notifications
You must be signed in to change notification settings - Fork 3
07 31
📄 원본(노션): https://app.notion.com/p/3ae19935b8ae80b5aa3be7f8e3ee5b9b — 최종 동기화 2026-07-31
- 회의 날짜: 2026-07-31
- 석희
- 어제 야근해서 너무 힘듬,,,
- 프론트 시연 가능하게 만듬
- 오늘 할일
- ❗️부르미 도메인 계속 구현, 결제 도메인 고민하기
- 동혁
- 주문 취소 구현해서 컨트롤러 연결
- 시연을 돕기 위해 매끄러운 트랜지션 PR
- PR 리뷰 함
- 오늘 할일
- ❗️브랜치 파서 할거 하기
- 현성
- 배달 테스트 화면에 시연에서 보기 좋게 픽업지 도착지 출발지 추가
- PR Approve
- 오늘 할일
- ✅ SSE 시연용 페이지 PR 올리기
- ✅ 어제 바이브코딩 한거 분석
- 현서
- 시연용 프론트 구현
- ERD 이상한 부분 찾음.
- 오늘 할일
- ✅ pr 올린거에서 클로드가 리뷰한거 수정하고 배포 어떻게 할지 얘기해보기
- ✅ Reviewer, Assignee 달기
이거 제가 해야하는건데 뼈대 잡아주셔서 감사합니다 🙇♂️
2번째 문단: "지금 구현은 최선이 아닌 MVP"의도 명확히 하기 위해서 아래와 같이 수정하고 싶네요
MVP 단계에서는 복잡한 동시성 제어보다 상태 변경을 직렬화하는 방식을 선택하였다. 부르미와 드리미의 요청 등록, 수락, 거절, 취소 등의 행위를 각각 Action 객체로 표현하고, 생성된 Action을 하나의 Queue에 등록하여 순차적으로 처리하도록 설계하였다. 이를 통해 동시에 여러 요청이 발생하더라도 먼저 처리된 Action만 상태 변경에 성공하고, 이후 Action은 변경된 상태를 기준으로 처리되어 매칭 상태의 일관성을 유지할 수 있다.
현재 대기 중인 드리미와 매칭을 요청한 부르미의 상태는 서버 메모리에서 관리한다. 초기 MVP에서는 단일 서버 환경을 전제로 단순한 인메모리 구조를 사용하되, 추후 다중 서버 환경에서도 상태를 공유하고 일관성을 유지할 수 있는 구조로 확장할 예정이다.
남은 과제 부분에 이런것도 추가할 수 있을 것 같습니다:
이후 사용자 수가 증가하면 위치 기반 Cell 인덱스를 적용하여 후보 탐색 범위를 줄일 수 있다. 또한 단일 Queue가 처리량의 병목이 되면 주문 ID를 기준으로 Action을 여러 Queue에 분산하는 Queue sharding을 적용할 수 있다. 예를 들어 주문 ID의 해시값을 shard 개수로 나눈 결과에 따라 Action을 16개의 Queue 중 하나에 배치하고, 각 Queue를 전담하는 단일 스레드가 순차적으로 처리한다. 이를 통해 동일한 주문의 Action은 항상 같은 shard에서 순서대로 처리하면서도, 서로 다른 주문은 여러 스레드에서 병렬로 처리할 수 있다.
2.1 단일 스레드 직렬화 (Actor 유사 모델)
(기존 글) 모든 매칭 상태 변경은 matching-engine 이라는 이름의 가상 스레드 단 하나가 큐에서 액션을 꺼내 순차 실행한다. 여러 요청 스레드가 동시에 들어와도, 실제 상태 변경은 항상 한 스레드에서 한 번에 하나씩만 일어난다. 따라서 HashMap 가변 필드를 락 없이 그대로 써도 경합(race condition)이 발생하지 않는다. 한 액션이 예외를 던져도 소비 스레드가 죽지 않도록 run()에서 방어한다 (MatchingEngine.java:36).
이건 actor 모델 찾아보고 검증할게요.
추가적으로 아직 view는 직렬화 안해놨었는데 석희님께서 snapshot으로 알아서 잘 해주셔서 현재 상태에는 문제 없는 것으로 알고 있음. 저것도 나중에 확장성을 위해서 snapshot을 반환하든 concurrenthashmap을 사용하든 action으로 만들던 해서 view 안깨지게 조심할게요
2.4 패스트패스(fast-path) 검증
startMatching은 호출 스레드에서 즉시 확인 가능한 중복만 빠르게 걸러 409 CONFLICT로 응답하고 (MatchingService.java:86), 실제 방 생성은 엔진 스레드에 맡긴다. 엔진 스레드에서도 큐 대기 중 다른 액션이 먼저 방을 만들었을 수 있으므로 한 번 더 확인한다 (MatchingService.java:96).
이거 설계 바뀐 상태인데 이전 것 기준으로 정리된 것 같아요. 409가 아니고 개인적으로는 석희님께 확인가능한 것만 걸러서 false로 내보냄. 아무튼 fast path는 맞다.
이번주 내로 MatchingService API (이미 javadoc 주석에 행위는 정리 되어있음) 문서화해서 노션이나 github wiki? 에 올려놓을게요
- 아키텍처 구조
이거 재진입 고려 안한거라 한거 머메이드로 다시 뽑을게요. DelayQueue 구조도 꼭 넣겠습니다.
- 자주 발생하는 에러
- 로그:
Failed to read candidate component class: file [/Users/admin/dev/WEB-Team3-NaengSam/backend/build/classes/java/main/com/naengsam/quick/domain/user/sms/DevSmsSender.class] - 해결법
- .env의 환경변수가 제대로 주입되었는지 확인한다.
- 로그:
- Https를 넣어야 하는 이유 원인 정적 파일의 JS에 무심코 crypto 라이브러리를 넣었음. Localhost를 통해서는 접근이 잘 되었지만
- 시연 직전 CORS관련 사고
-
로그 localhost에선 되다가 배포를 했을때만 S3의 presigned URL에 업로드가 안되던 문제가 있었음. console을 찾아보니 이렇게 하고 CORS 오류가 뜨고 있었다.
Access to fetch at 'https://symboorm-s3.s3.ap-northeast-2.amazonaws.com/uploads/\*\*\*' from origin 'http://43.202.52.6:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
-
해결 AWS S3 설정에
[ { "AllowedHeaders": ["*"], "AllowedMethods": ["GET", "PUT", "POST", "HEAD"], "AllowedOrigins": ["http://localhost:8080", "http://43.202.52.6:8080"], "ExposeHeaders": [], "MaxAgeSeconds": 3600 } ]다음과 같이 origin을 지정해주어서 해결.
-
- S3 업로드 테스트
- 매칭 시연
- 배달 시연 — 배달 시연의 경우 매칭 시연에서 매칭되면 넘어갈 수 있다.
- 프론트 시연
user@example.com
string
- 단일 was만 하는게 아니라 확장 가능성 고려해서.
- 경로 패턴 설정해서 same 경로 → cors 안남. cloud front만 사용해서 서버 호출하는 방식으로
- 라이더가 요청을 서버에 보냈을 때 서버가 위치정보 처리하는 방식
- gps 이용해서 보낼 때 오차가 있을 수 있음
- 예전 위치가 네트워크 지연 때문에 느리게 오는 경우
- 200을 주되 받은거는 서버에서 이걸로 추가 처리는 하지 않음
- redis에 있는 위치랑 지금 받은 위치랑 계산해서 거리 재기. 단말기에서 위치정보 보낼 때 정확도도 보내주는 게 있다
- 너무 빨리 이동하는 경우는 서버에서는 처리하지 않고 200만 돌려줌. 최신점과 과거점을 하버사인 방식으로 계산해서 거리랑 속도 시간 계산
- redis lua를 사용해서 스크립트 언어를 통으로 줘서 원자적으로 처리하게
- TTL만 바꿔서 보내줌
- 고객이 브라우저를 켰을 때 sse 구독한다
- 모든 인스턴스에 보냄
- was는 여러개고 redis는 하나
- 인메모리에 구독 정보가 있음
- for if로 이게 내 고객이라고 판별되면 push 한다
- 양방향이 아니니까 웹소켓은 아예 생각 안함
- 폴링과 sse 둘 다 개발해보고 비교 예정
- 고객이 여는 브라우저 창마다 구독이 들어가므로 3개로 제한한다.
- 레디스 geo 라이브러리 사용하기 위해서. 여러 인스턴스 쓰니까 레디스 쓸 수밖에 없게 됨
- cloud front가 끊어버리는 시간 간격보다 하트비트가 더 짧아야 함
- 네이글 알고리즘. sse
- os ulimit를 이용해 소켓 수 조절
- 양방향으로 정보 주고 받는거니까 웹소켓
- 카드 하나당 소켓 하나
- STOMP 사용해서 구현
- 시작 준비중인걸 어떻게 시작으로 바꾸지
- polling
- 시스템에서 예약 시간이 있음
- db에서 1초마다 스케줄러에서 검사해서 올리는걸로
- query dsl 로 정렬해서 백엔드 서버에서 정렬해서 프론트로 넘겨주기
- 동시성 제어
- 분산락 vs DB
- 분산락: 외부 의존성으로 관리하면 stop the world 걸리면. 락을 제 시간 안에 반환하지 못해 이슈
- RDB에서 동시성 제어하는 방식 사용
- 분산락 vs DB
- 상태 관리는 스케줄러 사용
- 현재 시간과 마감 시간 비교
- 레코드 많을 때 입찰 관리
- redis
- 집계 테이블 따로 사용해서 시세
- 일정 시각에 스케줄러 사용해서
- k6 스크립트: 테스트용도의 컨트롤러 만들어서
- sse 기반 방식
- 경매 하면서 돈이 묶이게
- 완벽하게 낙찰 성공하면 돈 빠져나가게
- 묶이는 방식은 포인트 레코드 로그 쌓아서 반환하게
- 알림도 sse.
- 채널 한개로 이벤트 3개
- jwt 읽어서 필터 거쳐서 인증 안되어 있으면
- 세션 하려면 별도의 storage 써야하는게
- 수평확장까지 고려해서
- onceperrequest
- 검색할 때 디바운싱
- 사람 10명 매칭 됐는데 1명이 수락하고 나머지 9명이 거절함
- 그 1명(드리미)의 평점을 보고 부르미가 거절
- 그러면 기존에 우선순위가 높았던 9명은 넘어가고 그 다음 우선순위가 낮은 10명
- instance metadata service version
- presigned url
드리미의 경우 사용자에게 안내문구로 "당근-XX를 물품에 적어주세요" 알림 문구를 넣는 것도 고려해볼만함.
엔티티만을 위한 상위 폴더를 만들고 나서 작업하기. (미리미리 만들어보자)
- PR 단위 최소화 하기
- 본인 작업 현황 정리해서 docs 폴더에 저장. 실시간으로 확인할 수 있는 방법 생각해보기
- 피그잼!
- DB에서 사용되는 엔티티는 공용으로 충돌없이 사용할 수 있도록 구조 마련
- 도메인으로 나눠서 작업하는 것 좋다. 이대로 하자
- 꼼꼼하게 작업하되, 너무 깊이 생각해서 전체 작업 속도를 늦추지 말자
- 픽업 완료 / 배달 완료시 실제 GPS 거리 계산 #100 클라이언트에서의 GPS 오차를 고려하여야 하므로 나중에 논의하는 것으로 결정.
- Wallet 식별관계 wallet_id → money/point_wallet_id로 승격, 기존의 money/point_wallet_id 삭제.
- 확장성에 대해서 더 연구하기
- Kafka, redis (Event queue) 공부해오기
Team 3 · 석희 · 현성 · 동혁 · 현서
Softeer Bootcamp 8th · WEB Team 3 · 이 위키는 팀 노션에서 동기화됩니다 📄
🏠 시작하기
🤝 협업
📋 기획안
🧠 기술 결정 기록 (ADR)
- 세션 vs 토큰
- 세션 및 다중 탭 처리 정책
- 실시간 배달 상태 전달에 SSE를 선택한 이유
- SSE 연결은 왜 1개였다가 5개가 되고, 다시 1개가 되었을까
- 드리미 GPS 끊김 감지 정책
- Redis 기반 로그인 대기열 도입기
- 카카오 API 응답 Redis 캐시 설계
- 활동 내역 조회를 커서 기반 페이지네이션으로 진행
- 알림 - WebPush 도입 이유와 SSE의 한계
- S3 Presigned URL 도입 결정
- 포인트, 머니 시스템 설계
🕸️매칭 시스템
- 매칭 시스템 설계
- Command와 Producer Consumer를 조합한 single writer 구조의 매칭 엔진
- 제안은 누구에게 해야 할까
- 쉼, 부름의 부르미‐드리미 매칭은 어떻게 동작할까
- 배정 정책에 Greedy 배정을 선택한 이유
- 매칭 시스템 구현
🧪 부하 테스트
- 매칭 부하테스트
- 매칭 부하테스트 보고서 (8.12)
- 매칭 부하테스트 보고서 (8.13)
- 매칭 부하테스트 보고서 (8.13 · 외부 API 트랜잭션)
- 매칭 부하테스트 보고서 (8.18 · 배포환경 720명)
🔧 트러블슈팅
- UploadSession - 옛 키 재사용 공격 방어 설계
- 8/6 · EC2 SSH 접속 불가
- 8/7 · 매칭 확정 후 Delivery가 생성되지 않는 고아 Order 문제
- 8/8 · 영속성 컨텍스트 detach로 dirty checking 미반영 문제 (@Modifying(clearAutomatically = true))
- 매칭 확정 후 Delivery가 생성되지 않는 고아 Order 문제
- 매칭이 성공하지 않았음에도 Orders 테이블에 PENDING으로 상태 변경하는 문제
- 부르미 확인 타임아웃 시 주문 DB·매칭 메모리 불일치
- 주변 콜 조회 시 반복되던 주문 조회 개선
- 드리미 오프라인 조회에 필요한 복합 인덱스 추가
- 매칭 단계 취소시 포인트 이중 환불 문제
- 로컬 DevStorage 사용시 로그인 상태에서도 401 UNAUTHORIZED 뜨던 문제
🗓️ 데일리 스크럼