Skip to content

feat: 품목 수정 기능 구현#33

Merged
JoonKyoLee merged 13 commits intomainfrom
feat/update-product
Nov 20, 2025
Merged

feat: 품목 수정 기능 구현#33
JoonKyoLee merged 13 commits intomainfrom
feat/update-product

Conversation

@JoonKyoLee
Copy link
Contributor

@JoonKyoLee JoonKyoLee commented Nov 20, 2025

✨ 작업 내용

  • 품목 수정 기능 구현

📝 적용 범위

  • /product

📌 참고 사항

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 상품 부분 수정 기능 추가 (PATCH 엔드포인트로 선택적 필드 업데이트)
    • 상품 응답에 상품 ID 포함
  • 버그 수정 / 개선

    • 존재하지 않는 상품에 대한 명확한 오류 응답 추가
    • 상점/발주처 접근 권한 오류 처리 강화(권한 상태 코드 조정)
    • 필드별 유효성 검증 및 널 안전 업데이트로 변경 안정성 향상
  • 테스트

    • 상품 수정 관련 단위 및 통합 테스트 대폭 추가/보강

✏️ Tip: You can customize this high-level summary in your review settings.

@JoonKyoLee JoonKyoLee self-assigned this Nov 20, 2025
@JoonKyoLee JoonKyoLee added the enhancement New feature or request label Nov 20, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 20, 2025

Walkthrough

상품 수정(PATCH) 기능이 추가되고, Product 엔티티에 부분 업데이트용 가드 메서드들이 도입되었습니다. DTO는 CreateProductResponse가 ProductResponse로 통합되고 UpdateProductRequest가 추가되었으며, 컨트롤러·서비스에 업데이트 흐름과 관련 성공/오류 상수들이 추가·수정되었습니다.

Changes

코호트 / 파일(s) 변경 요약
글로벌 상수
src/main/java/com/almang/inventory/global/api/SuccessMessage.java, src/main/java/com/almang/inventory/global/exception/ErrorCode.java
SuccessMessageUPDATE_PRODUCT_SUCCESS("품목 수정 성공") 추가. ErrorCodePRODUCT_NOT_FOUND(HttpStatus.NOT_FOUND, "품목을 찾을 수 없습니다."), STORE_ACCESS_DENIED(HttpStatus.FORBIDDEN, "상점에 접근할 수 없습니다.") 추가 및 VENDOR_ACCESS_DENIED의 HTTP 상태를 BAD_REQUESTFORBIDDEN으로 변경.
컨트롤러
src/main/java/com/almang/inventory/product/controller/ProductController.java
생성 응답 타입을 ProductResponse로 변경하고 @PatchMapping("/{productId}") 기반의 updateProduct(...) 엔드포인트 추가(요청 바인딩, 로깅, SuccessMessage 사용).
서비스
src/main/java/com/almang/inventory/product/service/ProductService.java
createProduct 반환 타입을 ProductResponse로 변경. 신규 updateProduct(Long, UpdateProductRequest, Long) 추가. findVendorByIdAndValidateAccess(...), findProductById(...) 헬퍼 추가 및 접근 검증 로직 삽입.
도메인(엔티티)
src/main/java/com/almang/inventory/product/domain/Product.java
선택적/부분 업데이트용 가드 메서드 5개 추가: updateVendor, updateBasicInfo, updateWeights, updatePrices, updateActivation.
DTOs
src/main/java/com/almang/inventory/product/dto/request/UpdateProductRequest.java, src/main/java/com/almang/inventory/product/dto/response/ProductResponse.java
신규 UpdateProductRequest 레코드(검증 애노테이션 포함) 추가. CreateProductResponseProductResponse로 통합하고 productId 필드 추가 및 from(Product) 팩토리 업데이트.
테스트
src/test/java/com/almang/inventory/product/controller/ProductControllerTest.java, src/test/java/com/almang/inventory/product/service/ProductServiceTest.java
테스트 전반에서 CreateProductResponseProductResponse로 교체. 상품 수정 성공/실패(상품 없음, 벤더 없음, 접근 거부 등) 케이스 추가 및 검증 로직 확장.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller as ProductController
    participant Service as ProductService
    participant Repo as Repository
    participant Entity as Product

    Client->>Controller: PATCH /api/v1/product/{productId} (UpdateProductRequest)
    activate Controller
    Controller->>Service: updateProduct(productId, request, userId)
    activate Service

    Service->>Repo: findUserById(userId) / validate
    Service->>Repo: findProductById(productId)
    alt product not found
        Service-->>Controller: throw PRODUCT_NOT_FOUND
    else
        Service->>Repo: findVendorByIdAndValidateAccess(vendorId, user)
        alt vendor not found
            Service-->>Controller: throw VENDOR_NOT_FOUND
        else vendor access denied
            Service-->>Controller: throw VENDOR_ACCESS_DENIED / STORE_ACCESS_DENIED
        else
            rect rgba(100,180,120,0.12)
                Service->>Entity: updateVendor(...)
                Service->>Entity: updateBasicInfo(...)
                Service->>Entity: updateWeights(...)
                Service->>Entity: updatePrices(...)
                Service->>Entity: updateActivation(...)
            end
            Service->>Repo: save(product)
            Service-->>Controller: ProductResponse.from(product)
        end
    end

    Controller-->>Client: 200 OK + ApiResponse<ProductResponse> (SuccessMessage.UPDATE_PRODUCT_SUCCESS)
    deactivate Controller
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

주의할 파일/영역:

  • src/main/java/com/almang/inventory/product/domain/Product.java — 널/동일성 검사 로직의 일관성 및 엔티티 상태 불변성 검토(동시성/트랜잭션 영향).
  • src/main/java/com/almang/inventory/product/service/ProductService.java — 권한/스토어 접근 검증(findVendorByIdAndValidateAccess)과 예외 매핑(새 ErrorCode들) 정확성 확인.
  • DTO 유효성(Validation) — UpdateProductRequest의 @NotNull/@Positive/@min 제약이 의도한 비즈니스 요구와 일치하는지 확인.
  • 테스트 — 기존 생성 흐름을 ProductResponse로 바꾼 부분이 모든 테스트 케이스와 직렬화/매핑 규칙에 맞는지 검증.

Possibly related PRs

  • #32 — 동일 파일군(ProductController, ProductService, Product 엔티티/DTO) 변경으로 기능 확장/조정 관련 연관성 높음.
  • #5 — ErrorCode 열거형을 변경한 다른 PR로, 에러 상수 충돌·일관성 점검에 관련됨.
  • #22 — SuccessMessage에 업데이트 유형 상수를 추가한 PR로 메시지 일관성 관점에서 연관됨.

Poem

🛠️ 품목 한 줄 바뀌니 시스템이 웃네,
널은 피해 값만 바꾸는 조심스런 손길,
벤더는 검증하고 저장은 깔끔히,
응답은 하나로 돌아오니 일사천리,
작지만 단단한 변경, 짧은 박수! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 일부 추가적인 변경사항들이 이슈 범위를 넘어갑니다. ProductResponse 도입, ErrorCode 업데이트, HTTP 상태 코드 변경 등이 본 PR의 주요 범위에 포함되지 않아야 합니다. ErrorCode 수정(VENDOR_ACCESS_DENIED 상태 코드 변경, 새 에러 코드)과 CreateProductResponse → ProductResponse 리팩토링은 별도 PR로 분리하세요. 이슈 #29는 '품목 수정 기능'만 범위로 명시했습니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항을 명확하게 반영합니다. '품목 수정 기능 구현'은 핵심 기능인 제품 업데이트 API 구현을 간결하고 직관적으로 설명합니다.
Description check ✅ Passed PR 설명이 필수 템플릿 섹션을 모두 포함하고 있습니다. 작업 내용, 적용 범위, 참고 사항이 적절하게 기술되었습니다.
Linked Issues check ✅ Passed 모든 코드 변경이 이슈 #29의 요구사항 '품목 정보 수정 기능'을 충족합니다. UpdateProductRequest DTO, updateProduct 메서드, PATCH 엔드포인트가 구현되었습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/update-product

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4d6de3 and 139e542.

📒 Files selected for processing (2)
  • src/main/java/com/almang/inventory/global/exception/ErrorCode.java (2 hunks)
  • src/test/java/com/almang/inventory/product/controller/ProductControllerTest.java (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-20T10:43:47.489Z
Learnt from: JoonKyoLee
Repo: almang2/inventory-server PR: 33
File: src/main/java/com/almang/inventory/product/domain/Product.java:62-66
Timestamp: 2025-11-20T10:43:47.489Z
Learning: In the almang2/inventory-server repository, Product entity update methods (e.g., updateVendor in src/main/java/com/almang/inventory/product/domain/Product.java) do not require null checks on vendor parameters because ProductService validates vendor existence via findVendorByIdAndValidateAccess before calling update methods, and the vendor field has nullable=false constraint ensuring this.vendor is never null for persisted entities.

Applied to files:

  • src/test/java/com/almang/inventory/product/controller/ProductControllerTest.java
🔇 Additional comments (10)
src/test/java/com/almang/inventory/product/controller/ProductControllerTest.java (7)

9-9: 임포트 변경 잘 적용되었습니다.

PATCH 메서드와 업데이트 관련 DTO 임포트가 적절하게 추가되었고, CreateProductResponseProductResponse로 통합한 것은 좋은 리팩토링입니다.

Also applies to: 18-19


70-84: 응답 DTO 통합이 깔끔하게 처리되었습니다.

CreateProductResponse에서 ProductResponse로의 전환이 기존 테스트 로직을 그대로 유지하면서 잘 적용되었습니다.


195-248: 업데이트 성공 시나리오가 완벽하게 구현되었습니다.

모든 필드를 포괄하는 테스트 데이터와 검증 로직이 체계적으로 작성되었습니다. 특히 isActivate 상태 변경(true→false)까지 테스트하여 완전한 수정 시나리오를 커버하고 있습니다.


250-283: 품목 미존재 예외 처리가 정확합니다.

존재하지 않는 품목 ID에 대한 업데이트 시도를 적절히 검증하고 있으며, 404 상태 코드와 에러 메시지 확인이 완벽합니다.


285-318: 발주처 미존재 시나리오가 올바르게 검증되었습니다.

유효하지 않은 발주처 ID로 업데이트 시도 시 예외 처리를 정확히 테스트하고 있습니다.


320-353: 접근 권한 검증이 보안 관점에서 매우 중요합니다! 🔒

다른 상점의 발주처로 품목을 수정하려는 시도를 차단하는 테스트가 완벽하게 구현되었습니다. 403 FORBIDDEN 상태 코드 사용도 HTTP 표준 시맨틱에 정확히 부합합니다.

참고: 멀티 테넌트 환경에서 이런 권한 검증 테스트는 데이터 무결성과 보안을 위해 필수적입니다.


355-383: 요청값 검증 테스트가 체계적으로 작성되었습니다.

다양한 유형의 유효하지 않은 값(null, 빈 문자열, 음수)을 조합하여 검증 로직을 테스트하고 있으며, 400 상태 코드 확인도 적절합니다.

src/main/java/com/almang/inventory/global/exception/ErrorCode.java (3)

17-17: 상점 접근 거부 에러 코드가 올바르게 추가되었습니다.

403 FORBIDDEN 상태 코드 사용이 접근 제어 시맨틱에 정확히 부합합니다. 다른 ACCESS_DENIED 에러들과도 일관성을 유지하고 있습니다.


31-31: 이전 리뷰 피드백이 완벽하게 반영되었습니다! 👍

HttpStatus.BAD_REQUEST에서 HttpStatus.FORBIDDEN으로 변경되어 이제 HTTP 표준 시맨틱에 정확히 부합합니다.

배경 설명:

  • 400 BAD_REQUEST: 잘못된 요청 형식(예: JSON 파싱 오류, 유효성 검증 실패)
  • 403 FORBIDDEN: 인증은 되었으나 권한이 없는 경우

이 변경으로 API 사용자가 에러의 원인을 명확히 파악할 수 있게 되었습니다.

참고 자료: RFC 7231 - HTTP Status Codes


33-34: 품목 미존재 에러 코드가 일관성 있게 추가되었습니다.

404 NOT_FOUND 상태 코드 사용이 적절하며, 기존 STORE_NOT_FOUND, VENDOR_NOT_FOUND와 동일한 패턴을 따라 코드베이스의 일관성을 유지하고 있습니다. 품목 수정 기능 구현에 필수적인 에러 처리입니다.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/main/java/com/almang/inventory/product/dto/request/UpdateProductRequest.java (1)

11-12: 필드 검증이 누락되었습니다.

namecode 필드에 유효성 검증이 없습니다. 빈 문자열이나 공백만 있는 값이 허용될 수 있습니다.

생성 시에는 어떤 검증을 사용하는지 확인하고 동일한 수준의 검증을 적용하는 것이 좋습니다.

CreateProductRequest의 검증 수준과 일관성을 맞추기 위해 다음 검증을 추가하세요:

 public record UpdateProductRequest(
         @NotNull Long vendorId,
+        @NotBlank String name,
+        @NotBlank String code,
-        String name,
-        String code,
         ProductUnit unit,
src/main/java/com/almang/inventory/product/domain/Product.java (2)

92-102: 타입 일관성을 개선하면 더 명확한 코드가 됩니다.

메서드 파라미터는 Integer (wrapper)인데 엔티티 필드는 int (primitive)로 선언되어 있습니다 (lines 54, 57, 60). 현재는 null 체크로 문제가 없지만, 타입을 일치시키면 코드 의도가 더 명확해집니다.

옵션 1: 엔티티 필드를 wrapper 타입으로 변경 (nullable 가격을 허용하려는 경우)

-private int costPrice;
-private int retailPrice;
-private int wholesalePrice;
+private Integer costPrice;
+private Integer retailPrice;
+private Integer wholesalePrice;

옵션 2: primitive를 유지하려면, null인 경우 업데이트를 건너뛰는 현재 로직이 적절합니다. 이 경우 추가 조치는 불필요하지만, 차후 리팩토링 시 고려해보세요.

📚 참고: JPA Best Practices - Wrapper vs Primitive Types


104-108: 타입 일관성 개선을 고려해보세요.

파라미터는 Boolean (wrapper)이지만 엔티티 필드는 boolean (primitive, line 51)입니다. 필드가 @Column(nullable = false)로 선언되어 있으므로, 파라미터도 primitive boolean으로 통일하는 것이 더 명확할 수 있습니다.

-public void updateActivation(Boolean isActivate) {
-    if (isActivate != null) {
-        this.isActivate = isActivate;
-    }
+public void updateActivation(boolean isActivate) {
+    this.isActivate = isActivate;
 }

단, 이렇게 변경하면 호출하는 쪽에서 항상 값을 전달해야 하므로, 부분 업데이트 시나리오에 따라 현재 구현이 더 적합할 수도 있습니다. 비즈니스 요구사항에 맞게 선택하세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e664bac and ad24525.

📒 Files selected for processing (9)
  • src/main/java/com/almang/inventory/global/api/SuccessMessage.java (1 hunks)
  • src/main/java/com/almang/inventory/global/exception/ErrorCode.java (1 hunks)
  • src/main/java/com/almang/inventory/product/controller/ProductController.java (3 hunks)
  • src/main/java/com/almang/inventory/product/domain/Product.java (1 hunks)
  • src/main/java/com/almang/inventory/product/dto/request/UpdateProductRequest.java (1 hunks)
  • src/main/java/com/almang/inventory/product/dto/response/ProductResponse.java (2 hunks)
  • src/main/java/com/almang/inventory/product/service/ProductService.java (3 hunks)
  • src/test/java/com/almang/inventory/product/controller/ProductControllerTest.java (4 hunks)
  • src/test/java/com/almang/inventory/product/service/ProductServiceTest.java (3 hunks)
🔇 Additional comments (8)
src/main/java/com/almang/inventory/global/exception/ErrorCode.java (1)

31-33: LGTM!

에러 코드가 기존 패턴과 일관성 있게 추가되었습니다. 👍

src/main/java/com/almang/inventory/global/api/SuccessMessage.java (1)

26-26: LGTM!

성공 메시지가 적절하게 추가되었습니다.

src/test/java/com/almang/inventory/product/controller/ProductControllerTest.java (1)

195-383: LGTM!

품목 수정 기능에 대한 테스트 커버리지가 훌륭합니다. 성공 케이스뿐만 아니라 다양한 예외 상황(품목 없음, 발주처 없음, 권한 없음, 검증 실패)을 모두 검증하고 있습니다. 🎯

src/main/java/com/almang/inventory/product/dto/response/ProductResponse.java (1)

7-38: LGTM!

ProductResponse로 이름을 변경하고 productId를 포함하도록 개선되었습니다. 생성과 수정 API가 동일한 응답 타입을 사용하게 되어 일관성이 높아졌습니다.

src/main/java/com/almang/inventory/product/service/ProductService.java (1)

82-91: 발주처 접근 권한 검증 로직이 잘 추출되었습니다.

중복 코드를 제거하고 재사용 가능한 메서드로 분리한 점이 좋습니다. 생성과 수정에서 동일한 검증 로직을 사용할 수 있게 되었네요. 👍

src/main/java/com/almang/inventory/product/controller/ProductController.java (1)

48-62: LGTM!

PATCH 엔드포인트가 적절하게 구현되었습니다. 검증, 로깅, 에러 처리가 모두 포함되어 있고, 기존 생성 API와 일관된 구조를 유지하고 있습니다.

src/main/java/com/almang/inventory/product/domain/Product.java (2)

68-78: 깔끔한 null-safe 구현입니다! 👍

각 파라미터에 대한 null 체크가 적절하게 적용되어 있어 부분 업데이트를 안전하게 수행할 수 있습니다.


80-90: 구조가 일관성 있게 잘 구현되었습니다.

null 체크를 통한 부분 업데이트 패턴이 명확하게 적용되어 있습니다.

import java.math.BigDecimal;

public record UpdateProductRequest(
@NotNull Long vendorId,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

PATCH 엔드포인트의 부분 업데이트 시맨틱과 일치하지 않습니다.

vendorId@NotNull 제약이 있어서 발주처를 변경하지 않는 부분 업데이트 시에도 항상 vendorId를 제공해야 합니다. PATCH 방식은 변경하려는 필드만 전달하는 것이 일반적입니다.

현재 구조는 PUT(전체 교체)에 가깝습니다. 다음 중 하나를 선택하세요:

  1. PATCH 시맨틱을 유지하려면 vendorId를 nullable로 변경하고, null인 경우 업데이트하지 않도록 서비스 로직 수정
  2. 전체 교체 방식(PUT)으로 변경하고 모든 필수 필드에 validation 추가

참고: RFC 5789(PATCH Method for HTTP) 및 REST API 설계 모범 사례를 확인하세요.

🤖 Prompt for AI Agents
In
src/main/java/com/almang/inventory/product/dto/request/UpdateProductRequest.java
around line 10, the @NotNull on vendorId forces clients to always supply
vendorId which breaks PATCH semantics; remove the @NotNull so vendorId is
nullable and update the service layer to only apply vendorId changes when
request.getVendorId() != null (i.e., check for null before setting or calling
repository update), adjust any controller validation groups to allow partial
updates, and add/modify tests to cover partial updates where vendorId is
omitted.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/java/com/almang/inventory/global/exception/ErrorCode.java (1)

34-34: 코드 포맷팅 일관성을 개선하세요.

생성자 호출 시 쉼표 뒤에 공백이 누락되었습니다. 파일 내 다른 상수 선언들(10, 14, 16번 라인 등)과 일관성을 유지하기 위해 공백을 추가해주세요.

적용 예시:

-    PRODUCT_NOT_FOUND(HttpStatus.NOT_FOUND,"품목을 찾을 수 없습니다."),
+    PRODUCT_NOT_FOUND(HttpStatus.NOT_FOUND, "품목을 찾을 수 없습니다."),

참고로 HttpStatus.NOT_FOUND 사용은 완벽합니다! 👍 품목을 찾을 수 없을 때 404를 반환하는 것이 정확한 HTTP 시맨틱입니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad24525 and a4d6de3.

📒 Files selected for processing (3)
  • src/main/java/com/almang/inventory/global/exception/ErrorCode.java (2 hunks)
  • src/main/java/com/almang/inventory/product/service/ProductService.java (3 hunks)
  • src/test/java/com/almang/inventory/product/service/ProductServiceTest.java (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-20T10:43:47.489Z
Learnt from: JoonKyoLee
Repo: almang2/inventory-server PR: 33
File: src/main/java/com/almang/inventory/product/domain/Product.java:62-66
Timestamp: 2025-11-20T10:43:47.489Z
Learning: In the almang2/inventory-server repository, Product entity update methods (e.g., updateVendor in src/main/java/com/almang/inventory/product/domain/Product.java) do not require null checks on vendor parameters because ProductService validates vendor existence via findVendorByIdAndValidateAccess before calling update methods, and the vendor field has nullable=false constraint ensuring this.vendor is never null for persisted entities.

Applied to files:

  • src/test/java/com/almang/inventory/product/service/ProductServiceTest.java
  • src/main/java/com/almang/inventory/product/service/ProductService.java
🔇 Additional comments (11)
src/test/java/com/almang/inventory/product/service/ProductServiceTest.java (6)

10-11: 임포트 및 반환 타입 변경 잘 반영되었습니다!

ProductResponse로의 통합이 깔끔하게 이루어졌네요.

Also applies to: 95-95


200-252: 완벽한 업데이트 성공 케이스 테스트입니다!

발주처 변경을 포함한 모든 필드 업데이트를 검증하고 있어, 업데이트 기능의 정확성을 확실하게 보장합니다.


254-281: 존재하지 않는 품목 예외 처리 테스트 적절합니다!


283-326: 존재하지 않는 발주처 예외 처리 테스트 적절합니다!


328-372: 다른 상점의 발주처로 수정 시도 테스트가 잘 구현되었습니다!

접근 권한 검증이 제대로 동작하는지 확인하는 중요한 보안 테스트입니다.


374-430: 이전 리뷰에서 요청한 테스트 케이스가 완벽하게 추가되었습니다!

다른 상점의 품목을 수정하려는 시도를 차단하는 중요한 보안 검증 테스트입니다. 두 개의 독립적인 상점 환경을 구성하고, 교차 접근을 시도한 뒤 적절한 예외(STORE_ACCESS_DENIED)가 발생하는지 확인하고 있어 완벽합니다.

src/main/java/com/almang/inventory/product/service/ProductService.java (5)

7-8: 응답 DTO 통합이 깔끔하게 적용되었습니다!

ProductResponse로의 일관된 변경이 잘 이루어졌네요.

Also applies to: 29-29, 37-37


40-61: 이전 리뷰의 크리티컬 보안 이슈가 완벽하게 수정되었습니다!

Lines 45-47의 상점 소유권 검증이 추가되어, 다른 상점의 품목을 수정할 수 없도록 보호하고 있습니다. 검증 순서도 훌륭합니다:

  1. 품목 소유권 확인 (fail-fast)
  2. 발주처 접근 권한 확인
  3. 업데이트 수행

이는 OWASP의 Broken Access Control (A01:2021) 취약점을 제대로 방어하는 구현입니다. 👍

참고: OWASP Top 10:2021 - A01 Broken Access Control


63-64: 헬퍼 메서드 재사용으로 코드 중복이 제거되었습니다!

DRY 원칙을 잘 따르고 있네요.


87-96: 발주처 검증 헬퍼 메서드가 잘 구현되었습니다!

존재 여부와 접근 권한을 한 곳에서 검증하여 코드 재사용성이 높아졌습니다.


98-101: 품목 조회 헬퍼 메서드가 적절하게 구현되었습니다!

일관된 예외 처리 패턴을 따르고 있네요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 품목 수정 기능 구현

1 participant