쇼핑 활동은 「사이트 접속 → 둘러보기 또는 검색 → 찾으면 상품 보기 → 장바구니 담기 → 더 쇼핑하거나 장바구니 보기·수정 → 결제」의 반복이다. 시퀀스는 세 개로 나눈다.
시퀀스
메시지
카탈로그 검색
Customer → Catalog.searchProducts(string) → Product.getInfo(string) → 상품 정보 → 일치하는 상품 목록
장바구니 담기
Customer → ShoppingCart.addItem(productId, quantity) → Item.verifyItem() → 품절이면 오류, 아니면 성공
결제와 주문
아래 그림
sequenceDiagram
actor C as Customer
participant SC as ShoppingCart
participant O as Order
participant I as Item
participant P as Payment
participant S as Shipment
C->>SC: getItems()
SC-->>C: Items
C->>C: getBillingInfo(), getShippingInfo()
C->>O: createOrder(Items, billingInfo, address)
O->>I: verifyItem()
I-->>O: 확인 결과
alt 상품이 없음
O-->>C: 오류
else 확인됨
O->>P: processPayment(billingInfo, amount)
P-->>O: paymentStatus
alt 결제 실패
O-->>C: 오류
else 결제 성공
O->>S: processShipment(address)
S-->>O: 배송 상태
O-->>C: 주문 상태
end
end
flowchart TB
a["회원이 질문하기 클릭"] --> b["제목과 본문 입력"]
b --> t{"태그가 있나?"}
t -->|"없음"| val{"검증 통과?"}
t -->|"있음"| ex{"이미 있는 태그인가?"}
ex -->|"예"| val
ex -->|"아니요"| rep{"태그를 만들 평판이 되나?"}
rep -->|"아니요"| err["사용자에게 오류"]
rep -->|"예"| mk{"태그 생성 성공?"}
mk -->|"아니요"| err
mk -->|"예"| val
val -->|"아니요"| err
val -->|"예"| post["질문 저장과 게시"]
시퀀스로 보면 Member가 Question.setTitle(), setBody()를 부르고, Tag.getTags(tagText)로 태그 ID를 받거나 없으면 createTag(tagText, tagDescription), addTag(tag)를 거친다. 이어서 createQuestion(questionText, tagId, bountyValue)가 Bounty.createBounty(bountyValue)로 현상금을 만들고 publishQuestion()으로 게시한다.
그 종목 포지션이 없으면 NO_STOCK_POSITION → 보유 수량이 모자라면 INSUFFICIENT_QUANTITY → 주문 생성·저장 → 거래소에 제출 → 실패면 상태를 실패로 저장, 성공이면 활성 주문에 추가
지정가 매수
거래 가능 자금이 수량 × 지정가보다 적으면 INSUFFICIENT_FUNDS → 이후는 매도와 같다
거래소 콜백
callback_stock_exchange(order_id, order_parts, status): 체결 부분을 붙이고 상태를 바꿔 저장한다. FILLED나 CANCELLED면 활성 주문에서 뺀다
활동 다이어그램으로는 「종목 검색·선택(매도는 보유 종목과 팔 묶음 선택) → 주문 종류 선택 → 수량, 가격 한도, 유효 기간 입력 → 예치금(매도는 보유 주식)이 충분한가 → 자금(주식)을 차감하고 거래소로 전송 → 거래소 확인 수신 → 주문 접수 안내 → 주문 수정 여부」다.
텍스트·사진·동영상, 좋아요·공유 수. 메시지는 add_member()로 받는 사람을 늘린다
SearchIndex
회원 이름, 그룹 이름, 페이지 제목, 게시물 단어 맵
Notification
푸시 알림이나 이메일
enum
값
ConnectionInvitationStatus
PENDING, ACCEPTED, REJECTED, CANCELED
AccountStatus
ACTIVE, CLOSED, CANCELED, BLACKLISTED, DISABLED
새 글 흐름은 「새 글 화면 → 공개 범위 목록 지정 → 본문 입력 → 사진·동영상을 붙이면 업로드 → 게시 클릭 → 검증 → 빠진 정보가 있으면 알림 → 요청한 회원들에게 게시 → 이메일·푸시 알림」이다. 프로필에 경력을 더하는 흐름은 직책, 회사, 위치, 기간, 설명을 입력하고 검증한 뒤 저장한다.
친구의 친구 가운데 나와 공통 연결이 많은 사람이 좋은 추천 후보다. 나에서 시작해 깊이 2까지 너비 우선 탐색(BFS)을 하면서, 깊이 2에서 만난 사람마다 몇 번 만났는지(= 공통 친구 수)를 센다.
from collections import Counterdef connection_suggestions(member, top_n=10): friends = set(member.connections) counts = Counter() for friend in friends: # 깊이 1 for candidate in friend.connections: # 깊이 2 if candidate is not member and candidate not in friends: counts[candidate] += 1 # 공통 친구 한 명 추가 return [m for m, _ in counts.most_common(top_n)]
매칭(findNearestDriver): 모든 기사를 훑어 AVAILABLE이고 차량 등급이 요청과 같은 기사 가운데 출발지와의 거리가 가장 짧은 기사를 고른다. 실제 서비스는 전체를 훑지 않고 지오해시·쿼드트리 같은 공간 색인을 쓴다(위치 기반 서비스 설계).
요금(calculateFare): (기본 2.0 + 거리(km) × 1.5 + 시간(분) × 0.3) × 등급 배수를 소수 둘째 자리로 반올림한다. 시간은 출발·도착 시각이 있으면 그 차이, 없으면 평균 시속 30km로 추정한다. 10km를 UberX로 가면 추정 20분이라 2 + 15 + 6 = 23달러, UberXL이면 34.5달러다.
완료(completeRide): 요금 계산 → 결제 생성·처리 → 운행에 결제 연결 → 기사가 운행 완료. 취소는 상태를 CANCELLED로 바꾸고 배정된 기사를 AVAILABLE로 되돌린다.
동시성 문제
대응
여러 승객이 동시에 호출
스레드 안전한 컬렉션과 동기화
기사 위치가 쉴 새 없이 갱신
위치 갱신 큐로 경쟁 상태를 피한다
한 기사가 두 호출에 배정
매칭 구간에 락을 걸어 한 번에 한 운행만 배정한다
결제
원자적 결제 트랜잭션
확장 질문으로는 수요·공급에 따른 할증 요금, 여러 승객이 함께 타는 합승(UberPool), 기사 수익 집계와 분석, 실시간 운행 알림, 지도 서비스를 이용한 경로 최적화, 안전 기능(긴급 버튼, 지인과 운행 공유, 기사 신원 확인), 예약 호출, 프로모션 코드와 할인이 나온다.