-
Notifications
You must be signed in to change notification settings - Fork 34
[2주차] 설계 문서 제출 - 이민규 #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: leeminkyu-kr96
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,137 @@ | ||||||||||
| # **요구사항 명세서** | ||||||||||
|
|
||||||||||
| ## **1. 상품 목록 조회** | ||||||||||
|
|
||||||||||
| ### 1.1. 유저 시나리오 | ||||||||||
| > "사용자가 상품을 둘러보기 위해 사이트에 접속했다. 그는 어떤 제품이 인기가 많은지 보기 위해 상품 목록을 조회한다." | ||||||||||
|
|
||||||||||
| ### 1.2. 핵심 기능 정의 | ||||||||||
| - **F-1:** 상품 목록을 조회할 수 있다. | ||||||||||
| - **F-2:** 상품 목록을 '좋아요순'으로 정렬할 수 있다. | ||||||||||
| - **F-3:** 상품 목록을 '최신순', '가격순' 등 다른 기준으로도 정렬할 수 있다. | ||||||||||
| - **F-4:** 상품 목록을 페이지 단위로 나누어 볼 수 있다. | ||||||||||
|
|
||||||||||
| ### 1.3. 유스케이스 흐름 | ||||||||||
| * **Main Flow (기본 조회):** | ||||||||||
| 1. 사용자가 상품 목록 페이지에 진입한다. | ||||||||||
| 2. 최신순으로 첫 번째 페이지의 상품 목록을 반환한다. | ||||||||||
| 3. 화면에 상품 목록이 표시된다. | ||||||||||
| * **Alternate Flow (정렬 변경):** | ||||||||||
| 1. 사용자가 '인기순' 정렬 버튼을 클릭한다. | ||||||||||
| 2. 인기순으로 상품 목록을 다시 조회하여 반환한다. | ||||||||||
| 3. 화면에 인기순으로 정렬된 목록이 표시된다. | ||||||||||
| * **Alternate Flow (페이징):** | ||||||||||
| 1. 사용자가 다른 페이지를 클릭한다. | ||||||||||
| 2. 다른 페이지의 상품 목록을 조회하여 반환한다. | ||||||||||
| 3. 화면에 다음 상품 목록이 이어서 표시된다. | ||||||||||
| * **Exception Flow (결과 없음):** | ||||||||||
| 1. 사용자가 특정 필터를 적용했으나, 해당하는 상품이 하나도 없다. | ||||||||||
| 2. "조회된 상품이 없습니다."라는 메시지를 반환한다. | ||||||||||
|
|
||||||||||
| --- | ||||||||||
|
|
||||||||||
| ## **2. 상품 상세 조회** | ||||||||||
|
|
||||||||||
| ### 2.1. 유저 시나리오 | ||||||||||
| > "사용자가 마음에 드는 상품이 있어서 해당 상품을 클릭했다. 그는 해당 상품의 상세 정보를 확인하고 싶어 한다." | ||||||||||
|
|
||||||||||
| ### 2.2. 핵심 기능 정의 | ||||||||||
| - **F-1:** 상품 상세정보를 조회할 수 있다. | ||||||||||
| - **F-2:** 상품의 총 좋아요 수와 나의 좋아요 여부를 조회할 수 있다. | ||||||||||
| - **F-3:** 구매할 상품의 수량을 선택할 수 있다. | ||||||||||
|
|
||||||||||
| ### 2.3. 유스케이스 흐름 | ||||||||||
| * **Main Flow (상세 조회):** | ||||||||||
| 1. 사용자가 상품 목록에서 특정 상품을 클릭한다. | ||||||||||
| 2. 해당 상푸의 상세 정보(이름, 가격, 설명, 총 좋아요 수, 나의 좋아요 여부 등)를 조회하여 반환한다. | ||||||||||
| 3. 화면에 상품 상세 정보가 표시되고, 수량은 '1'로 기본 설정된다. | ||||||||||
| * **Alternate Flow (수량 변경):** | ||||||||||
| 1. 사용자가 '+' 버튼을 눌러 수량을 '3'으로 변경한다. | ||||||||||
| 2. 화면에 수량이 '3'으로 갱신된다. | ||||||||||
| * **Exception Flow (상품 없음):** | ||||||||||
| 1. 사용자가 존재하지 않는 상품 ID의 URL로 직접 접근한다. | ||||||||||
| 2. 상품을 찾을 수 없으므로, "상품을 찾을 수 없습니다."라는 오류를 반환한다. | ||||||||||
|
|
||||||||||
| --- | ||||||||||
|
|
||||||||||
| ## **3. 브랜드별 상품 조회** | ||||||||||
|
|
||||||||||
| ### 3.1. 유저 시나리오 | ||||||||||
| > "사용자가 마음에 드는 특정 브랜드를 찾고 있다. 그는 해당 브랜드에서 나오는 상품만 모아서 조회하고 싶어 한다." | ||||||||||
|
|
||||||||||
| ### 3.2. 핵심 기능 정의 | ||||||||||
| - **F-1:** 특정 브랜드에 속한 상품만 필터링하여 조회할 수 있다. | ||||||||||
| - **F-2:** 상품 목록을 '인기순'으로 정렬할 수 있다. | ||||||||||
| - **F-3:** 상품 목록을 '최신순', '가격순' 등 다른 기준으로도 정렬할 수 있다. | ||||||||||
| - **F-4:** 상품 목록을 페이지 단위로 나누어 볼 수 있다. | ||||||||||
|
|
||||||||||
| ### 3.3. 유스케이스 흐름 | ||||||||||
| * **Main Flow (브랜드별 조회):** | ||||||||||
| 1. 사용자가 'A 브랜드'를 조회회한다. | ||||||||||
| 2. 해당 브랜드드 상품 목록을 반환한다. | ||||||||||
|
Comment on lines
+70
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 타이포 수정: 문법 오류 2건. - 1. 사용자가 'A 브랜드'를 조회회한다.
- 2. 해당 브랜드드 상품 목록을 반환한다.
+ 1. 사용자가 'A 브랜드'를 조회한다.
+ 2. 해당 브랜드의 상품 목록을 반환한다.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| 3. 화면에 'A 브랜드'의 상품 목록만 표시된다. | ||||||||||
| * **Exception Flow (브랜드 없음):** | ||||||||||
| 1. 사용자가 존재하지 않는 브랜드 ID의 URL로 직접 접근한다. | ||||||||||
| 2. "브랜드를 찾을 수 없습니다."라는 오류(404 Not Found)를 반환한다. | ||||||||||
|
|
||||||||||
| --- | ||||||||||
|
|
||||||||||
| ## **4. 상품 좋아요 (등록/취소)** | ||||||||||
|
|
||||||||||
| ### 4.1. 유저 시나리오 | ||||||||||
| > (등록) "사용자가 마음에 드는 상품을 발견했다. 그는 나중에 마음에 드는 상품을 모아보기 위해 '좋아요'를 누른다." | ||||||||||
| > (취소) "사용자가 이전에 '좋아요' 했던 상품이 더 이상 마음에 들지 않아 '좋아요'를 취소한다." | ||||||||||
|
|
||||||||||
| ### 4.2. 핵심 기능 정의 | ||||||||||
| - **F-1:** 상품에 대해 '좋아요'를 등록할 수 있다. | ||||||||||
| - **F-2:** 이미 '좋아요'가 등록된 상품의 '좋아요'를 취소할 수 있다. | ||||||||||
|
|
||||||||||
| ### 4.3. 유스케이스 흐름 | ||||||||||
| * **Main Flow (좋아요 등록):** | ||||||||||
| 1. 사용자가 좋아요 아이콘을 클릭한다. | ||||||||||
| 2. 좋아요 여부를 판단한다. | ||||||||||
| 3. 해당 상품이 좋아요가 안되어있으면 좋아요 등록이 된다. | ||||||||||
| * **Alternate Flow (좋아요 취소):** | ||||||||||
| 1. 사용자가 좋아요 아이콘을 클릭한다. | ||||||||||
| 2. 좋아요 여부를 판단한다. | ||||||||||
| 3. 해당 상품이 좋아요가 되어있으면 좋아요가 취소된다. | ||||||||||
| * **Exception Flow (비회원):** | ||||||||||
| 1. 비로그인 사용자가 좋아요 아이콘을 클릭한다. | ||||||||||
| 2. "로그인이 필요한 기능입니다."라는 오류 메시지를 반환한다. | ||||||||||
|
|
||||||||||
| --- | ||||||||||
|
|
||||||||||
| ## **5. 주문 생성 (결제)** | ||||||||||
|
|
||||||||||
| ### 5.1. 유저 시나리오 | ||||||||||
| > "사용자가 특정 상품을 구매하고 싶어, 해당 상품을 결제한다." | ||||||||||
|
|
||||||||||
| ### 5.2. 핵심 기능 정의 | ||||||||||
| - **F-1:** 사용자가 선택한 상품을 구매할 수 있다. | ||||||||||
| - **F-2:** 사용자의 포인트가 충분할 경우 결제할 수 있으며, 결제 시 포인트가 차감된다. | ||||||||||
| - **F-3:** 상품의 재고가 충분할 경우 결제할 수 있으며, 결제 시 재고가 차감된다. | ||||||||||
| - **F-4:** 결제 성공 시 주문 정보가 외부 시스템으로 전송된다. | ||||||||||
|
|
||||||||||
| ### 5.3. 유스케이스 흐름 | ||||||||||
| * **Main Flow (주문 성공):** | ||||||||||
| 1. 로그인한 사용자가 상품과 수량을 선택하고 '결제하기'를 요청한다. | ||||||||||
| 2. 상품 재고가 1개 이상인지 확인한다. | ||||||||||
| 3. 사용자 포인트가 총 결제 금액 이상인지 확인한다. | ||||||||||
| 4. 상품 재고를 1 차감한다. | ||||||||||
| 5. 사용자 포인트를 차감한다. | ||||||||||
| 6. '주문' 및 '주문 항목'을 저장한다. | ||||||||||
| 7. 주문 정보를 외부 시스템으로 전송한다. | ||||||||||
| 8. 사용자에게 "주문 완료" 응답을 반환한다. | ||||||||||
| * **Alternate Flow (여러 수량 구매):** | ||||||||||
| 1. 사용자가 수량을 '3'으로 선택하고 '결제하기'를 요청한다. | ||||||||||
| 2. 재고 및 포인트를 수량 기준으로 검증, 차감, 저장한다. | ||||||||||
| 3. 주문에 성공한다. | ||||||||||
| * **Exception Flow (재고 부족):** | ||||||||||
| 1. 시스템이 재고를 확인했으나, 요청 수량보다 재고가 부족하다. | ||||||||||
| 2. "재고가 부족하여 주문할 수 없습니다."라는 오류 메시지를 반환한다. | ||||||||||
| * **Exception Flow (포인트 부족):** | ||||||||||
| 1. 시스템이 사용자의 포인트를 확인했으나, 총 결제 금액보다 포인트가 부족하다. | ||||||||||
| 2. "포인트가 부족합니다."라는 오류 메시지를 반환한다. | ||||||||||
| * **Exception Flow (비회원):** | ||||||||||
| 1. 비로그인 사용자가 '결제하기'를 요청한다. | ||||||||||
| 2. "로그인이 필요한 기능입니다."라는 오류 메시지를 반환한다. | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
|
|
||
| ### 1. 상품 목록/상세 조회 및 브랜드 조회 | ||
| ```mermaid | ||
| sequenceDiagram | ||
| participant User | ||
| participant ProductController | ||
| participant ProductReader | ||
|
|
||
| %% 상품 목록 조회 %% | ||
| User->>ProductController: GET /api/v1/products?sort=likes_desc | ||
| ProductController->>ProductReader: getProducts(sort) | ||
| ProductReader-->>ProductController: productList | ||
| ProductController-->>User: productList | ||
|
|
||
| %% 상품 상세 조회 %% | ||
| User->>ProductController: GET /api/v1/products/{productId} | ||
| ProductController->>ProductReader: getProduct(productId) | ||
| ProductReader-->>ProductController: product | ||
| ProductController-->>User: product | ||
|
|
||
| participant BrandController | ||
| participant BrandReader | ||
|
|
||
| %% 브랜드 조회 %% | ||
| User->>BrandController: GET /api/v1/brands/{brandId} | ||
| BrandController->>BrandReader: getBrand({brandId}) | ||
| BrandReader-->>BrandController: brand | ||
| BrandController-->>User: brand | ||
| ``` | ||
| ### 2. 주문 생성 | ||
|
|
||
| ```mermaid | ||
| sequenceDiagram | ||
| participant User | ||
| participant OrderController | ||
| participant OrderService | ||
| participant ProductReader | ||
| participant PointReader | ||
| participant ProductService | ||
| participant PointService | ||
| participant OrderRepository | ||
|
|
||
| User->>OrderController: POST /api/v1/orders (body: {productId, quantity}) | ||
| OrderController->>OrderService: setOrder(userId, {productId, quantity}) | ||
|
|
||
| %% 조회 및 검증 %% | ||
| OrderService->>ProductReader: getProduct({productId}) | ||
| ProductReader -->>OrderService: product(현재가격, 재고) | ||
|
|
||
| OrderService->>PointReader: getPoint(userId) | ||
| PointReader-->>OrderService: point (현재 잔여 포인트) | ||
|
|
||
| %% 재고 및 포인트 차감 %% | ||
| critical Transaction Block | ||
| OrderService ->>ProductService: decreaseStock(productId, quantity) | ||
| OrderService ->>PointService: deductPoint(productPrice * quantity) | ||
| OrderService->> OrderRepository: save(new Order(...)) | ||
| OrderRepository-->>OrderService: orderInfo | ||
| end | ||
|
|
||
| %% 응답 %% | ||
| OrderService -->> OrderController:orderInfo | ||
| OrderController-->> User:orderInfo | ||
| ``` |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||
| ## 1. 클래스 다이어그램램 | ||||||
|
|
||||||
| ```mermaid | ||||||
| classDiagram | ||||||
| class User { | ||||||
| Long id | ||||||
| String name | ||||||
| int point | ||||||
| } | ||||||
| class Product { | ||||||
| Long id | ||||||
| String name | ||||||
| int price | ||||||
| int quantity | ||||||
| } | ||||||
|
Comment on lines
+10
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain필드명 일관성 검토: ERD와 클래스 다이어그램 동기화 필요. Product 클래스의 필드명이 ERD와 다릅니다:
요구사항 및 시퀀스 다이어그램에서 사용할 정확한 필드명을 결정하고 전체 설계 문서에서 일관되게 사용하세요. Length of output: 124 🏁 Script executed: #!/bin/bash
# Search for ERD-related files
fd -e md -e mmd -e txt . .docs/design | grep -i erdLength of output: 22 🏁 Script executed: #!/bin/bash
# Examine the class diagram file to see Product class definition
cat ".docs/design/03-class-diagram.md"Length of output: 838 🏁 Script executed: #!/bin/bash
# Search for field name references (quantity, stock_quantity, stock) in all design docs
rg -n "(quantity|stock_quantity|stock)" .docs/design --type mdLength of output: 677 🏁 Script executed: #!/bin/bash
# List all files in .docs/design to understand document structure
ls -la .docs/design/Length of output: 380 Length of output: 918 🏁 Script executed: #!/bin/bash
# Examine requirements to see specified field names
cat ".docs/design/01-requirements.md"Length of output: 3680 🏁 Script executed: #!/bin/bash
# Examine sequence diagrams for context
cat ".docs/design/02-sequence-diagrams.md"Length of output: 1977 ERD와 클래스 다이어그램의 필드명 불일치 수정 필요 검증 결과, 설계 문서 간 필드명 불일치가 확인되었습니다:
🤖 Prompt for AI Agents |
||||||
| class Brand { | ||||||
| Long id | ||||||
| String name | ||||||
| } | ||||||
| class Like { | ||||||
| User user | ||||||
| Product product | ||||||
| } | ||||||
| class Order { | ||||||
| Long id | ||||||
| User user | ||||||
| int totalPrice | ||||||
| Timestamp orderDate | ||||||
| } | ||||||
|
Comment on lines
+24
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain필드명 일관성 검토: Order 클래스의 시간 필드. Order 클래스의 필드명이 ERD와 다릅니다:
데이터베이스 스키마와 도메인 모델의 네이밍을 통일하고, 시퀀스 다이어그램과도 일관성 있게 유지하세요. 🏁 Script executed: #!/bin/bash
# List all files in .docs/design directory to identify ERD and sequence diagram files
find .docs/design -type f -name "*.md" | sortLength of output: 124 🏁 Script executed: #!/bin/bash
# Search for ERD-related content showing database field names
fd -e md . .docs/design -x cat {}Length of output: 7413 🏁 Script executed: #!/bin/bash
# Search for "created_at" or "orderDate" references in design docs
rg -n -i "(created_at|orderDate)" .docs/design/Length of output: 118 🏁 Script executed: #!/bin/bash
# Look for Order class definitions in the codebase
rg -n -C5 "class Order" --type=java --type=ts --type=js --type=pyLength of output: 0 Order 클래스 시간 필드 네이밍 불일치 확인됨 - 수정 필요 검증 결과 설계 문서에서 다음과 같은 불일치가 확인되었습니다:
데이터베이스 스키마(snake_case)와 도메인 모델(camelCase) 간 명확한 네이밍 규칙을 수립하거나, 둘 중 하나로 통일하세요. 다른 엔티티(User, Product 등)의 시간 필드도 동일한 원칙으로 일관성 있게 정의되어야 합니다. 🤖 Prompt for AI Agents |
||||||
| class OrderItem { | ||||||
| Order order | ||||||
| Product product | ||||||
| int quantity | ||||||
| int orderPrice | ||||||
| } | ||||||
|
|
||||||
| %% --- 관계 정의 --- | ||||||
| Product --> Brand : (상품은 브랜드를 가짐) | ||||||
|
|
||||||
| Order --> User : (주문은 유저를 가짐) | ||||||
|
|
||||||
| OrderItem --> Order : (주문 항목은 주문에 속함) | ||||||
| OrderItem --> Product : (주문 항목은 상품을 가짐) | ||||||
|
|
||||||
| Like --> User : (좋아요는 유저를 가짐) | ||||||
| Like -- > Product : (좋아요는 상품을 가짐) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mermaid 문법 오류: 관계 정의 수정 필요. 라인 46에서 관계 정의에 오타가 있습니다. 스페이스가 불필요하게 포함되어 있습니다. - Like -- > Product : (좋아요는 상품을 가짐)
+ Like --> Product : (좋아요는 상품을 가짐)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| ## 1. ERD | ||
|
|
||
| ```mermaid | ||
| erDiagram | ||
| users { | ||
| bigint id PK | ||
| varchar name | ||
| int point | ||
| } | ||
| products { | ||
| bigint id PK | ||
| varchar name | ||
| int price | ||
| int stock_quantity | ||
| bigint brand_id FK | ||
| } | ||
| brands { | ||
| bigint id PK | ||
| varchar name | ||
| } | ||
| likes { | ||
| bigint user_id PK, FK | ||
| bigint product_id PK, FK | ||
| } | ||
| orders { | ||
| bigint id PK | ||
| bigint user_id FK | ||
| int total_price | ||
| Timestamp created_at | ||
| } | ||
| orderitems { | ||
| bigint id PK | ||
| bigint order_id FK | ||
| bigint product_id FK | ||
| int quantity | ||
| int order_price | ||
| } | ||
|
|
||
| %% --- 관계 정의 (1:N) --- | ||
| users ||--o{ likes : "likes" | ||
| users ||--o{ orders : "places" | ||
|
|
||
| products ||--o{ likes : "is_liked" | ||
| products ||--o{ orderitems : "is_in" | ||
|
|
||
| brands ||--o{ products : "has" | ||
|
|
||
| orders ||--o{ orderitems : "contains" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| package com.loopers.application.point; | ||
|
|
||
| import com.loopers.domain.point.PointModel; | ||
| import com.loopers.domain.point.PointService; | ||
| import com.loopers.domain.user.UserModel; | ||
| import com.loopers.domain.user.UserService; | ||
| import com.loopers.support.error.CoreException; | ||
| import com.loopers.support.error.ErrorType; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @RequiredArgsConstructor | ||
| @Component | ||
| public class PointFacade { | ||
| private final PointService pointService; | ||
| private final UserService userService; | ||
|
|
||
| public PointInfo getPoint(String userId) { | ||
| UserModel user = userService.getUser(userId); | ||
| if (user == null) { | ||
| throw new CoreException(ErrorType.NOT_FOUND, "존재하지 않는 요청입니다."); | ||
| } | ||
| PointModel pointModel = new PointModel(user, 0); | ||
| PointModel point = pointService.findPoint(pointModel); | ||
|
|
||
| if (point == null) { | ||
| throw new CoreException(ErrorType.NOT_FOUND, "포인트 정보가 없습니다."); | ||
| } | ||
|
|
||
| return PointInfo.from(point); | ||
| } | ||
|
|
||
| public PointInfo chargePoint(String userId, int amount) { | ||
| UserModel user = userService.getUser(userId); | ||
| if (user == null) { | ||
| throw new CoreException(ErrorType.NOT_FOUND, "존재하지 않는 요청입니다."); | ||
| } | ||
| PointModel pointModel = new PointModel(user, amount); | ||
| pointService.charge(pointModel); | ||
|
|
||
| PointModel charged = pointService.findPoint(new PointModel(user, 0)); | ||
| return PointInfo.from(charged); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.loopers.application.point; | ||
|
|
||
| import com.loopers.domain.point.PointModel; | ||
| import com.loopers.domain.user.UserModel; | ||
|
|
||
| public record PointInfo(Long id, UserModel user, int point) { | ||
| public static PointInfo from(PointModel model) { | ||
| return new PointInfo(model.getId(), model.getUser(), model.getPoint()); | ||
| } | ||
| public int getPoint() { | ||
| return point; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.loopers.application.user; | ||
|
|
||
| import com.loopers.domain.user.UserModel; | ||
| import com.loopers.domain.user.UserService; | ||
| import com.loopers.support.error.CoreException; | ||
| import com.loopers.support.error.ErrorType; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @RequiredArgsConstructor | ||
| @Component | ||
| public class UserFacade { | ||
| private final UserService userService; | ||
|
|
||
| public UserInfo signup(String userId, String email, String birthDate) { | ||
| UserModel userModel = new UserModel(userId, email, birthDate); | ||
| UserModel savedUser = userService.signUp(userModel); | ||
| return UserInfo.from(savedUser); | ||
| } | ||
|
|
||
| public UserInfo getUser(String userId) { | ||
| UserModel user = userService.getUser(userId); | ||
| if (user == null) { | ||
| throw new CoreException(ErrorType.NOT_FOUND, "존재하지 않는 요청입니다."); | ||
| } | ||
| return UserInfo.from(user); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
타이포 수정: "상푸" → "상품".
📝 Committable suggestion
🤖 Prompt for AI Agents