Skip to content

Commit 97a403c

Browse files
authored
Feature/software design (#6) (#51)
* [volume-1] 회원가입, 내 정보 조회, 포인트 조회, 포인트 충전 기능 구현 (#4) * Feature/user (#1) * test: User 단위테스트 추가 * feat: User 도메인 구현 * test: 회원 가입 통합테스트 추가 * feat: 회원가입 서비스 로직 구현 * test: 회원가입 E2E 테스트 추가 * feat: 회원가입 API 구현 * test: gender필드를 저장할 수 있도록 테스트 코드 수정 * refactor: User도메인에 성별 필드 추가 * test: 회원 정보 조회 통합 테스트 작성 * feat: 회원 정보 조회 서비스 로직 구현 * test: 회원 정보 조회 E2E 테스트 작성 * feat: 회원 정보 조회 API 추가 * Feature/point (#2) * test: 회원가입 관련 테스트 코드가 SignUpFacade를 참조하도록 수정 * refactor: 회원가입을 처리하는 SignUpFacade 구현 * test: 포인트 조회 통합테스트 추가 * feat: 포인트 조회 서비스 로직 구현 * test: 포인트 조회 E2E 테스트 코드 추가 * feat: 포인트 조회 API 로직 추가 * test: 포인트 충전 단위 테스트 추가 * feat: 포인트 충전 도메인 로직 추가 * test: 포인트 충전 테스트 코드 추가 * feat: 포인트 충전 서비스 로직 추가 * test: 포인트 충전 E2E 테스트 코드 추가 * feat: 포인트 충전 API 추가 * docs: 회원가입, 내 정보 조회, 포인트 조회, 포인트 충전 기능 관련 docstring 추가 (#3) * docs: 설계 문서 추가
1 parent ef70fe5 commit 97a403c

5 files changed

Lines changed: 559 additions & 0 deletions

File tree

.docs/design/01-requirements.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# 01-requirements.md
2+
> 루프팩 감성 이커머스 – 요구사항 및 유스케이스 명세서
3+
4+
---
5+
6+
## 📘 1. 개요
7+
루프팩 이커머스는 여러 브랜드의 상품을 한 번에 주문하고, 좋아요와 포인트 결제를 통해 감성적 쇼핑 경험을 제공하는 플랫폼이다. 본 문서는 사용자 중심 시나리오 기반으로 **기능 요구사항****유스케이스**를 정의하며, 이후 UML(시퀀스, 클래스, ERD)으로 확장된다.
8+
9+
---
10+
11+
## 👥 2. 주요 액터
12+
| 액터 | 설명 |
13+
|------|------|
14+
| **User (사용자)** | 상품 탐색, 좋아요, 주문 등 주요 행위를 수행하는 주체 |
15+
| **System (이커머스 시스템)** | 포인트 및 재고를 관리하고 주문 정보를 처리 |
16+
| **External Service (외부 연동 시스템)** | 주문 정보를 전달받는 외부 서비스(Mock 처리 가능) |
17+
18+
---
19+
20+
## 🧾 3. 유스케이스 목록
21+
| UC ID | 유스케이스명 | 주요 액터 | 설명 | 관계 |
22+
|------|---------------|----------|------|------|
23+
| UC-01 | 상품 목록 조회 | User | 브랜드/정렬 기준별 상품 목록을 조회한다 | - |
24+
| UC-02 | 상품 상세 조회 | User | 특정 상품의 상세 정보를 확인한다 | includes(UC-01) |
25+
| UC-03 | 상품 좋아요 등록/취소 | User | 상품에 좋아요를 누르거나 취소한다 | - |
26+
| UC-04 | 주문 생성 | User | 여러 상품을 선택해 포인트로 결제하고 주문을 생성한다 | include(UC-02) |
27+
| UC-04-1 | 포인트 결제 처리 | System | 주문 생성 중 포인트 차감을 수행한다 | include(UC-04) |
28+
| UC-04-2 | 재고 차감 처리 | System | 주문 생성 중 상품 재고를 차감한다 | include(UC-04) |
29+
| UC-04-3 | 외부 주문 전송 | System/External | 주문 생성 후 외부 시스템에 전송한다 | include(UC-04) |
30+
| UC-05 | 주문 내역 조회 | User | 사용자의 주문 이력을 확인한다 | - |
31+
| UC-06 | 단일 주문 상세 조회 | User | 특정 주문의 상세 정보를 확인한다 | include(UC-05) |
32+
33+
---
34+
35+
## 🎛️ 3-1. 유스케이스 다이어그램
36+
<img src="./use%20case%20diagram.png" alt="유스케이스 다이어그램" />
37+
38+
---
39+
40+
## 🧩 4. 유스케이스 명세
41+
42+
### 🛍 UC-01 상품 목록 조회
43+
| 구분 | 내용 |
44+
|------|------|
45+
| **액터** | User |
46+
| **기본 시나리오** | 1) 사용자가 상품 목록 페이지에 접근한다.<br> 2) 정렬(latest/price_asc/likes_desc)과 필터(brandId)를 선택한다.<br> 3) 시스템은 조건에 맞는 상품 목록을 반환한다.<br> 4) 각 상품의 좋아요 수를 함께 표시한다. |
47+
| **대안 시나리오** | 4a. 사용자가 로그인 된 경우 본인이 좋아요 했는지를 함께 표시한다.
48+
| **예외 시나리오** | • 등록된 상품이 없는 경우 빈 배열 반환한다.<br> • 정렬 기준이 유효하지 않으면 기본(latest)으로 조회한다 |
49+
| **후조건** | 상품 목록이 사용자 화면에 표시된다. |
50+
51+
---
52+
53+
### 📄 UC-02 상품 상세 조회
54+
| 구분 | 내용 |
55+
|------|------|
56+
| **액터** | User |
57+
| **사전조건** | • 요청 시 상품 ID가 파라미터로 전달된다.<br> • (선택) 사용자가 로그인된 상태이다.|
58+
| **기본 시나리오** | 1) 사용자는 상품 목록이나 링크를 통해 상세 페이지에 접근할 수 있다.<br> 2) 시스템은 상품명, 가격, 재고, 좋아요 수, 브랜드 정보를 반환한다. |
59+
| **예외 시나리오** | • 상품 ID가 존재하지 않거나 삭제된 상품 혹은 인 경우 404 반환한다. <br> • 상품이 비공개 상태일 경우 403 반환한다.<br> • 상품 ID 형식이 잘못된 경우 400 반환한다. |
60+
| **후조건** | 상품 상세 정보가 표시된다. |
61+
62+
---
63+
64+
### ❤️ UC-03 상품 좋아요 등록/취소
65+
| 구분 | 내용 |
66+
|------|------|
67+
| **액터** | User |
68+
| **사전조건** | • 사용자는 로그인 상태이다. |
69+
| **기본 시나리오** | 1) 사용자가 상세/목록 페이지에서 좋아요 버튼을 클릭한다.<br> 2) 시스템은 해당 사용자의 좋아요 등록/취소를 처리한다.<br> 4) 현재 상태(liked=true/false)와 총 좋아요 수를 반환한다. |
70+
| **예외 시나리오** | • 중복 요청 시 동일 결과 반환(멱등 보장)<br> • 데이터 충돌 시 요청 재시도 처리 |
71+
| **후조건** | 좋아요 상태가 변경되고, 상품 목록/상세 정보에 반영된다. |
72+
| **비고** | (user_id, product_id) UNIQUE 제약으로 중복 방지 |
73+
74+
---
75+
76+
### 🛒 UC-04 주문 생성
77+
| 구분 | 내용 |
78+
|------|------|
79+
| **액터** | User |
80+
| **사전조건** | 상품이 존재하고 재고 및 포인트가 충분해야 함 |
81+
| **기본 시나리오** | 1) 사용자가 여러 상품을 선택해 주문을 요청한다.<br> 2) OrderService는 ProductService에 재고 확인을 요청한다.<br> 3) OrderService는 PointService에 결제 금액만큼 포인트 차감을 요청한다.<br> 4) 모든 검증이 통과되면 주문 정보를 생성한다.<br> 5) 주문 정보를 외부 시스템으로 전송한다.<br> 6) 주문 생성 결과(주문번호, 결제금액, 잔여 포인트)를 반환한다. |
82+
| **예외 시나리오** | • 포인트 부족 → “결제 실패” 응답 및 충전 안내<br> • 재고 부족 → “주문 불가 상품” 메시지 반환<br> • 외부 전송 실패 → 주문은 저장되지만 상태를 “보류(PENDING)”로 표시 |
83+
| **후조건** | 포인트와 재고가 차감되고, 주문 내역이 생성된다. |
84+
| **비고** | UC-04-1~3을 포함하며, 트랜잭션으로 처리해야 함. |
85+
86+
#### UC-04-1 포인트 결제 처리
87+
| 항목 | 내용 |
88+
|------|------|
89+
| **액터** | System |
90+
| **기능 요약** | 사용자의 포인트 잔액을 검증 후 주문 금액만큼 차감한다. |
91+
| **예외 시나리오** | 잔액 부족 시 “Insufficient Points” 오류 반환 |
92+
| **후조건** | 사용자의 포인트 잔액이 감소한다. |
93+
94+
#### UC-04-2 재고 차감 처리
95+
| 항목 | 내용 |
96+
|------|------|
97+
| **액터** | System |
98+
| **기능 요약** | 주문한 각 상품의 재고를 차감한다. |
99+
| **예외 시나리오** | 재고 부족 시 해당 상품 주문 불가 처리 |
100+
| **후조건** | 재고 수량이 감소한다. |
101+
102+
#### UC-04-3 외부 주문 전송
103+
| 항목 | 내용 |
104+
|------|------|
105+
| **액터** | System / External Service |
106+
| **기능 요약** | 생성된 주문을 외부 시스템으로 전송한다. |
107+
| **예외 시나리오** | 외부 API 응답 지연 시 재시도 또는 비동기 큐에 저장 |
108+
| **후조건** | 주문 상태가 “전송 완료”로 변경된다. |
109+
110+
---
111+
112+
### 📦 UC-05 주문 내역 조회
113+
| 구분 | 내용 |
114+
|------|------|
115+
| **액터** | User |
116+
| **사전조건** | 주문 내역이 존재 |
117+
| **기본 시나리오** | 1) 사용자가 주문 내역 페이지를 연다.<br> 2) 시스템은 유저의 모든 주문 목록을 반환한다. |
118+
| **예외 시나리오** | • 주문 내역이 없을 경우 빈 배열 반환 |
119+
| **후조건** | 주문 목록이 화면에 표시된다. |
120+
121+
---
122+
123+
#### UC-06 단일 주문 상세 조회
124+
| 구분 | 내용 |
125+
|------|------|
126+
| **액터** | User |
127+
| **사전조건** | 주문이 존재하고 해당 사용자의 주문이어야 함 |
128+
| **기본 시나리오** | 1) 사용자는 목록이나 링크를 통해 상세 페이지에 접근할 수 있다.<br> 2) 시스템은 해당 주문의 상세 정보(주문번호, 상품 목록, 총액, 상태 등)를 반환한다. |
129+
| **예외 시나리오** | • 주문이 존재하지 않을 경우 404 반환<br> • 다른 사용자의 주문을 조회하려는 경우 403 반환<br> • 주문 ID 형식이 잘못된 경우 400 반환 |
130+
| **후조건** | 주문 상세 정보가 화면에 표시된다. |
131+
132+
---
133+
134+
## ⚙️ 5. 비기능 요구사항
135+
| 항목 | 내용 |
136+
|------|------|
137+
| **식별 방식** | 모든 API는 `X-USER-ID` 헤더로 사용자 식별 |
138+
| **동시성 제어** | 포인트 차감 및 재고 차감은 트랜잭션 단위로 동작 |
139+
| **멱등성 보장** | 좋아요, 주문 요청은 멱등하게 처리되어야 함 |
140+
| **성능 요구사항** | 상품 목록 조회는 페이지네이션(page/size) 적용 |
141+
| **확장성 고려** | 좋아요 데이터를 추천/랭킹 기능으로 확장 가능 |
142+
| **일관성 보장** | 외부 시스템 연동 실패 시 재시도 로직 또는 보류 상태 유지 |
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# 02-sequence-diagrams.md
2+
> 루프팩 감성 이커머스 – 시퀀스 다이어그램 명세서
3+
> (도메인별 행위와 책임 중심 설계)
4+
5+
---
6+
7+
## 🎯 개요
8+
이 문서는 **UC-03 (좋아요)****UC-04 (주문)** 의 핵심 시나리오를 시퀀스 다이어그램으로 시각화한다.
9+
핵심 비즈니스 로직 흐름만 표현하여 가독성을 높였다.
10+
11+
---
12+
13+
## ❤️ UC-03 상품 좋아요 등록/취소
14+
15+
> **멱등성 보장**: 이미 좋아요한 상태에서 다시 좋아요 요청 시, 추가 작업 없이 현재 상태(`liked: true`)를 반환하여 멱등성을 보장합니다.
16+
17+
### 1️⃣ 좋아요 등록
18+
19+
```mermaid
20+
sequenceDiagram
21+
autonumber
22+
actor User
23+
participant Controller
24+
participant Facade
25+
participant ProductDisplay
26+
27+
User->>Controller: POST /api/v1/like/products/{productId}
28+
Controller->>Facade: likeProduct(userId, productId)
29+
Facade->>ProductDisplay: findById(productId)
30+
ProductDisplay-->>Facade: ProductDisplay
31+
32+
alt 이미 좋아요 함
33+
ProductDisplay-->>Facade: likeCount
34+
Facade-->>Controller: {liked: true, likeCount}
35+
else 좋아요 없음
36+
Facade->>Facade: create Like(userId, productId)
37+
Facade->>ProductDisplay: like(Like)
38+
ProductDisplay->>ProductDisplay: likes.add(Like)
39+
ProductDisplay-->>Facade: likeCount
40+
Facade-->>Controller: {liked: true, likeCount}
41+
end
42+
Controller-->>User: 응답
43+
```
44+
45+
### 2️⃣ 좋아요 취소
46+
47+
> **멱등성 보장**: 좋아요하지 않은 상태에서 취소 요청 시, 추가 작업 없이 현재 상태(`liked: false`)를 반환하여 멱등성을 보장합니다.
48+
49+
```mermaid
50+
sequenceDiagram
51+
autonumber
52+
actor User
53+
participant Controller
54+
participant Facade
55+
participant ProductDisplay
56+
57+
User->>Controller: DELETE /api/v1/like/products/{productId}
58+
Controller->>Facade: unlikeProduct(userId, productId)
59+
Facade->>ProductDisplay: findById(productId)
60+
ProductDisplay-->>Facade: ProductDisplay
61+
62+
alt 좋아요 없음
63+
ProductDisplay-->>Facade: likeCount
64+
Facade-->>Controller: {liked: false, likeCount}
65+
else 이미 좋아요 함
66+
Facade->>Facade: find Like(userId, productId)
67+
Facade->>ProductDisplay: unlike(Like)
68+
ProductDisplay->>ProductDisplay: likes.remove(Like)
69+
ProductDisplay-->>Facade: likeCount
70+
Facade-->>Controller: {liked: false, likeCount}
71+
end
72+
Controller-->>User: 응답
73+
```
74+
75+
---
76+
77+
## 🛒 UC-04 주문 생성
78+
79+
### 1️⃣ 주문 생성 기본 흐름
80+
81+
```mermaid
82+
sequenceDiagram
83+
autonumber
84+
actor User
85+
participant Controller
86+
participant Facade
87+
participant ProductOrder
88+
participant Point
89+
participant Order
90+
91+
User->>Controller: POST /api/v1/orders
92+
Controller->>Facade: createOrder(userId, items, totalAmount)
93+
94+
Note over Facade: 트랜잭션 시작
95+
96+
Facade->>ProductOrder: checkStock(quantity)
97+
ProductOrder-->>Facade: stock available
98+
99+
Facade->>Point: checkBalance(totalAmount)
100+
Point-->>Facade: balance sufficient
101+
102+
Facade->>ProductOrder: decreaseStock(quantity)
103+
ProductOrder-->>Facade: success
104+
105+
Facade->>Point: deduct(totalAmount)
106+
Point-->>Facade: success
107+
108+
Facade->>Order: create(List~ProductOrder~, Point)
109+
Order-->>Facade: Order (status: PENDING)
110+
111+
Note over Facade: 트랜잭션 커밋
112+
Facade-->>Controller: Order
113+
Controller-->>User: 주문 접수 완료
114+
```
115+
116+
### 2️⃣ 외부 전송 성공
117+
118+
```mermaid
119+
sequenceDiagram
120+
autonumber
121+
participant Facade
122+
participant ExternalService
123+
participant Order
124+
125+
Note over Facade: 주문 생성 완료
126+
127+
Facade->>ExternalService: sendOrder(order)
128+
ExternalService-->>Facade: success
129+
130+
Facade->>Order: complete()
131+
Order->>Order: status = COMPLETED
132+
133+
Facade-->>User: 주문 완료
134+
```
135+
136+
### 3️⃣ 외부 전송 실패 (PENDING 상태 유지)
137+
138+
```mermaid
139+
sequenceDiagram
140+
autonumber
141+
participant Facade
142+
participant ExternalService
143+
participant Order
144+
145+
Note over Facade: 주문 생성 완료
146+
147+
Facade->>ExternalService: sendOrder(order)
148+
ExternalService-->>Facade: error
149+
150+
Note over Facade: 주문은 저장되지만 PENDING 상태 유지
151+
152+
Facade->>Order: 상태 유지
153+
Order->>Order: status = PENDING
154+
155+
Note over Facade: 재시도 로직 또는 비동기 큐에 저장
156+
157+
Facade-->>User: 주문 접수 완료 (외부 전송 보류)
158+
```
159+
160+
### 💬 예외 시나리오
161+
- **포인트 부족**: Point.deduct()에서 예외 발생 → 트랜잭션 롤백
162+
- **재고 부족**: ProductOrder.decreaseStock()에서 예외 발생 → 트랜잭션 롤백
163+
- **외부 전송 실패**: 주문은 저장되지만 상태를 PENDING으로 유지하여 재시도 가능

0 commit comments

Comments
 (0)