Conversation
개요이 PR은 OpenAPI/Swagger 지원을 추가하고 세 가지 핵심 기능을 구현합니다: 장바구니 CRUD 작업, 회원 배송 주소 관리, 그리고 가게 및 메뉴 조회 기능입니다. 각 기능은 도메인 엔티티, 데이터 전송 객체, 저장소, 서비스 및 REST 컨트롤러로 완벽하게 구성되어 있습니다. 변경 사항OpenAPI 설정 및 검증 예외 처리
장바구니 기능
주소 관리 기능
가게 및 메뉴 조회 기능
예상 코드 리뷰 노력🎯 3 (Moderate) | ⏱️ ~25 분 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/com/kuit/baemin/domain/cart/CartItem.java`:
- Around line 59-61: The updateQuantity method in CartItem currently assigns
quantity directly, allowing null/zero/negative values to corrupt cart
invariants; update CartItem.updateQuantity(Integer quantity) to validate and
enforce the invariant (e.g., reject null and require quantity > 0) and throw a
clear runtime exception (IllegalArgumentException or custom DomainException)
when validation fails; also ensure any other mutators/constructors in CartItem
that set quantity follow the same check so the invariant is enforced at the
entity level.
In `@src/main/java/com/kuit/baemin/domain/menu/Menu.java`:
- Around line 44-51: The Menu entity uses wrapper types for required fields
which risks NPEs and DB constraint violations; change the fields price and
popularity in class Menu from Integer and Boolean to primitive int and boolean
respectively, update the builder/constructors/setters/getters (e.g., any
Menu.Builder or Menu(...) constructor and
setPrice/setPopularity/getPrice/isPopularity methods) to accept/return
primitives and ensure callers set these required values (or provide sensible
defaults) so null cannot be assigned before persistence.
In `@src/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.java`:
- Around line 29-30: The field name 'type' in the Restaurant class is ambiguous;
rename it to a clear, domain-specific name (e.g., restaurantType, businessType,
or deliveryType) in the Restaurant entity and update its corresponding
accessor/mutator methods (getX/setX), any JPA annotations if you want to
preserve the DB column name (adjust `@Column` if necessary), and all usages across
the codebase (repositories, DTOs, services, tests) to the new identifier to keep
compile-time references consistent; ensure any JSON serialization names or
database migrations are handled after renaming.
- Around line 29-60: The nullable=false fields in Restaurant (fields: type,
minDeliveryPrice, deliveryTip, minDeliveryTime, maxDeliveryTime, rating,
reviewCount, dibsCount) currently use wrapper types (Integer/Double) which risks
nulls via the builder and NPEs; update these fields in the Restaurant entity to
use primitive types (int for Integer fields and double for rating) or
alternatively keep wrappers but remove nullable=false and handle nullability in
business logic—also adjust the builder/factory that constructs Restaurant
(ensure it supplies default primitive values or performs non-null validation) so
the chosen approach is consistent across the class.
In `@src/main/java/com/kuit/baemin/exception/handler/GlobalExceptionHandler.java`:
- Around line 44-53: Add a dedicated ErrorStatus entry for ConstraintViolation
(e.g., CONSTRAINT_VIOLATION or VALIDATION_CONSTRAINT_FAILED) and update the
GlobalExceptionHandler.handleConstraintViolation(ConstraintViolationException)
to return that new ErrorStatus's code instead of ErrorStatus.BAD_REQUEST;
specifically add the enum constant to ErrorStatus and change the
ApiResponse.onFailure(...) call in handleConstraintViolation to use
ErrorStatus.YOUR_NEW_CONST.getCode() (and keep the existing message and payload
behavior). Ensure the new enum follows the project's ErrorStatus
ordering/formatting conventions.
In `@src/main/java/com/kuit/baemin/repository/MenuRepository.java`:
- Line 14: The repository method findAllByRestaurantAndStatus in MenuRepository
causes N+1 when MenuRes.from(menu) accesses menu.getRestaurant().getId() because
restaurant is LAZY; update the repository to eagerly fetch restaurant either by
annotating findAllByRestaurantAndStatus with `@EntityGraph`(attributePaths =
"restaurant") or by replacing it with an explicit `@Query` that uses a fetch join
for restaurant so the Menu entities returned include their Restaurant and avoid
per-row selects.
In `@src/main/java/com/kuit/baemin/service/CartService.java`:
- Around line 37-43: The service currently trusts client-supplied member IDs and
looks up CartItem by ID only, causing ownership bypass; update the controller to
inject the authenticated user (use `@AuthenticationPrincipal` or read
SecurityContext) and change CartService methods createCartItem, updateCartItem,
and deleteCartItem to use the authenticated member's ID instead of
req.getMemberId(); additionally add/replace repository queries with a new
CartItemRepository method like findByIdAndMemberAndStatus(cartId, member,
CartItemStatus.ACTIVE) and use it in updateCartItem/deleteCartItem to verify
ownership before modifying or deleting items.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 977e1f65-e104-4101-bbb3-0cde44c17450
📒 Files selected for processing (34)
build.gradlesrc/main/java/com/kuit/baemin/config/OpenApiConfig.javasrc/main/java/com/kuit/baemin/controller/CartController.javasrc/main/java/com/kuit/baemin/controller/MemberController.javasrc/main/java/com/kuit/baemin/controller/StoreController.javasrc/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.javasrc/main/java/com/kuit/baemin/domain/address/Address.javasrc/main/java/com/kuit/baemin/domain/address/AddressStatus.javasrc/main/java/com/kuit/baemin/domain/cart/CartItem.javasrc/main/java/com/kuit/baemin/domain/cart/CartItemStatus.javasrc/main/java/com/kuit/baemin/domain/menu/Menu.javasrc/main/java/com/kuit/baemin/domain/menu/MenuStatus.javasrc/main/java/com/kuit/baemin/dto/request/AddressCreateReq.javasrc/main/java/com/kuit/baemin/dto/request/CartItemCreateReq.javasrc/main/java/com/kuit/baemin/dto/request/CartItemUpdateReq.javasrc/main/java/com/kuit/baemin/dto/response/AddressRes.javasrc/main/java/com/kuit/baemin/dto/response/CartItemRes.javasrc/main/java/com/kuit/baemin/dto/response/MenuListRes.javasrc/main/java/com/kuit/baemin/dto/response/MenuRes.javasrc/main/java/com/kuit/baemin/dto/response/StoreDetailRes.javasrc/main/java/com/kuit/baemin/dto/response/StoreListRes.javasrc/main/java/com/kuit/baemin/dto/response/StoreRes.javasrc/main/java/com/kuit/baemin/exception/CartException.javasrc/main/java/com/kuit/baemin/exception/StoreException.javasrc/main/java/com/kuit/baemin/exception/errorcode/ErrorStatus.javasrc/main/java/com/kuit/baemin/exception/handler/GlobalExceptionHandler.javasrc/main/java/com/kuit/baemin/repository/AddressRepository.javasrc/main/java/com/kuit/baemin/repository/CartItemRepository.javasrc/main/java/com/kuit/baemin/repository/MemberRepository.javasrc/main/java/com/kuit/baemin/repository/MenuRepository.javasrc/main/java/com/kuit/baemin/repository/RestaurantRepository.javasrc/main/java/com/kuit/baemin/service/CartService.javasrc/main/java/com/kuit/baemin/service/MemberService.javasrc/main/java/com/kuit/baemin/service/StoreService.java
| public void updateQuantity(Integer quantity) { | ||
| this.quantity = quantity; | ||
| } |
There was a problem hiding this comment.
수량 도메인 불변식을 엔티티에서 직접 보장해주세요.
Line 59~Line 60은 값을 그대로 대입해서 null, 0, 음수가 들어와도 저장 가능합니다. 요청 DTO 검증이 우회되면 장바구니 데이터 무결성이 깨집니다.
수정 예시
public void updateQuantity(Integer quantity) {
+ if (quantity == null || quantity <= 0) {
+ throw new IllegalArgumentException("수량은 1 이상이어야 합니다.");
+ }
this.quantity = quantity;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public void updateQuantity(Integer quantity) { | |
| this.quantity = quantity; | |
| } | |
| public void updateQuantity(Integer quantity) { | |
| if (quantity == null || quantity <= 0) { | |
| throw new IllegalArgumentException("수량은 1 이상이어야 합니다."); | |
| } | |
| this.quantity = quantity; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/domain/cart/CartItem.java` around lines 59 -
61, The updateQuantity method in CartItem currently assigns quantity directly,
allowing null/zero/negative values to corrupt cart invariants; update
CartItem.updateQuantity(Integer quantity) to validate and enforce the invariant
(e.g., reject null and require quantity > 0) and throw a clear runtime exception
(IllegalArgumentException or custom DomainException) when validation fails; also
ensure any other mutators/constructors in CartItem that set quantity follow the
same check so the invariant is enforced at the entity level.
| @Column(nullable = false) | ||
| private Integer price; | ||
|
|
||
| @Column(length = 500) | ||
| private String menuPictureUrl; | ||
|
|
||
| @Column(nullable = false) | ||
| private Boolean popularity; |
There was a problem hiding this comment.
nullable=false 제약조건에 래퍼 타입 사용으로 인한 NPE 위험
price와 popularity 필드가 nullable = false로 선언되었지만 래퍼 타입(Integer, Boolean)을 사용하고 있습니다.
이로 인해 발생 가능한 문제:
- 빌더 패턴 사용 시 필드 미설정으로 인한 null 할당
- DB 제약조건 위반 또는 런타임 NPE 발생
primitive 타입으로 변경하는 것을 권장합니다.
🔧 primitive 타입 사용 제안
- `@Column`(nullable = false)
- private Integer price;
+ `@Column`(nullable = false)
+ private int price;
- `@Column`(nullable = false)
- private Boolean popularity;
+ `@Column`(nullable = false)
+ private boolean popularity;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @Column(nullable = false) | |
| private Integer price; | |
| @Column(length = 500) | |
| private String menuPictureUrl; | |
| @Column(nullable = false) | |
| private Boolean popularity; | |
| `@Column`(nullable = false) | |
| private int price; | |
| `@Column`(length = 500) | |
| private String menuPictureUrl; | |
| `@Column`(nullable = false) | |
| private boolean popularity; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/domain/menu/Menu.java` around lines 44 - 51,
The Menu entity uses wrapper types for required fields which risks NPEs and DB
constraint violations; change the fields price and popularity in class Menu from
Integer and Boolean to primitive int and boolean respectively, update the
builder/constructors/setters/getters (e.g., any Menu.Builder or Menu(...)
constructor and setPrice/setPopularity/getPrice/isPopularity methods) to
accept/return primitives and ensure callers set these required values (or
provide sensible defaults) so null cannot be assigned before persistence.
| @Column(nullable = false) | ||
| private Integer type; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
필드명 'type'의 의미가 불명확합니다
type 필드가 무엇을 나타내는지 명확하지 않습니다. 레스토랑 분류인지, 배달 타입인지 등을 알 수 없습니다.
필드명을 더 명확하게 변경하는 것을 권장합니다 (예: restaurantType, businessType, deliveryType 등).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.java` around lines
29 - 30, The field name 'type' in the Restaurant class is ambiguous; rename it
to a clear, domain-specific name (e.g., restaurantType, businessType, or
deliveryType) in the Restaurant entity and update its corresponding
accessor/mutator methods (getX/setX), any JPA annotations if you want to
preserve the DB column name (adjust `@Column` if necessary), and all usages across
the codebase (repositories, DTOs, services, tests) to the new identifier to keep
compile-time references consistent; ensure any JSON serialization names or
database migrations are handled after renaming.
| @Column(nullable = false) | ||
| private Integer type; | ||
|
|
||
| @Column(length = 500) | ||
| private String storePictureUrl; | ||
|
|
||
| @Column(nullable = false, length = 20) | ||
| private String phone; | ||
|
|
||
| @Column(nullable = false, length = 500) | ||
| private String content; | ||
|
|
||
| @Column(nullable = false) | ||
| private Integer minDeliveryPrice; | ||
|
|
||
| @Column(nullable = false) | ||
| private Integer deliveryTip; | ||
|
|
||
| @Column(nullable = false) | ||
| private Integer minDeliveryTime; | ||
|
|
||
| @Column(nullable = false) | ||
| private Integer maxDeliveryTime; | ||
|
|
||
| @Column(nullable = false) | ||
| private Double rating; | ||
|
|
||
| @Column(nullable = false) | ||
| private Integer reviewCount; | ||
|
|
||
| @Column(nullable = false) | ||
| private Integer dibsCount; |
There was a problem hiding this comment.
nullable=false 제약조건에 래퍼 타입 사용으로 인한 NPE 위험
type, minDeliveryPrice, deliveryTip, minDeliveryTime, maxDeliveryTime, rating, reviewCount, dibsCount 필드들이 nullable = false로 선언되어 있지만 래퍼 타입(Integer, Double)을 사용하고 있습니다.
이는 다음 문제를 야기할 수 있습니다:
- 빌더 사용 시 필드를 설정하지 않으면 null이 할당되어 DB 삽입 시 제약조건 위반
- 엔티티 사용 중 예기치 않은 NPE 발생 가능
primitive 타입(int, double)으로 변경하거나, @Column 제약과 실제 타입 간 일관성을 유지하세요.
🔧 primitive 타입 사용 제안
- `@Column`(nullable = false)
- private Integer type;
+ `@Column`(nullable = false)
+ private int type;
- `@Column`(nullable = false)
- private Integer minDeliveryPrice;
+ `@Column`(nullable = false)
+ private int minDeliveryPrice;
- `@Column`(nullable = false)
- private Integer deliveryTip;
+ `@Column`(nullable = false)
+ private int deliveryTip;
- `@Column`(nullable = false)
- private Integer minDeliveryTime;
+ `@Column`(nullable = false)
+ private int minDeliveryTime;
- `@Column`(nullable = false)
- private Integer maxDeliveryTime;
+ `@Column`(nullable = false)
+ private int maxDeliveryTime;
- `@Column`(nullable = false)
- private Double rating;
+ `@Column`(nullable = false)
+ private double rating;
- `@Column`(nullable = false)
- private Integer reviewCount;
+ `@Column`(nullable = false)
+ private int reviewCount;
- `@Column`(nullable = false)
- private Integer dibsCount;
+ `@Column`(nullable = false)
+ private int dibsCount;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/domain/Restaurant/Restaurant.java` around lines
29 - 60, The nullable=false fields in Restaurant (fields: type,
minDeliveryPrice, deliveryTip, minDeliveryTime, maxDeliveryTime, rating,
reviewCount, dibsCount) currently use wrapper types (Integer/Double) which risks
nulls via the builder and NPEs; update these fields in the Restaurant entity to
use primitive types (int for Integer fields and double for rating) or
alternatively keep wrappers but remove nullable=false and handle nullability in
business logic—also adjust the builder/factory that constructs Restaurant
(ensure it supplies default primitive values or performs non-null validation) so
the chosen approach is consistent across the class.
| @ResponseStatus(BAD_REQUEST) | ||
| @ExceptionHandler(ConstraintViolationException.class) | ||
| public ApiResponse<?> handleConstraintViolation(ConstraintViolationException e) { | ||
| String message = e.getConstraintViolations() | ||
| .stream() | ||
| .map(violation -> violation.getMessage()) | ||
| .collect(Collectors.joining(", ")); | ||
| log.warn("[Validation error] {}", message); | ||
| return ApiResponse.onFailure(ErrorStatus.BAD_REQUEST.getCode(), message, null); | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
ConstraintViolationException에 전용 ErrorStatus 코드를 매핑해주세요.
현재 BAD_REQUEST 공통 코드를 재사용해서 @Valid 실패와 @Validated 실패를 코드 기준으로 구분할 수 없습니다. 전용 에러 코드를 ErrorStatus에 추가하고 이 핸들러에서 그 코드를 반환하는 방식으로 분리하는 게 좋습니다.
🔧 제안 패치
- return ApiResponse.onFailure(ErrorStatus.BAD_REQUEST.getCode(), message, null);
+ return ApiResponse.onFailure(ErrorStatus.CONSTRAINT_VIOLATION.getCode(), message, null);+ CONSTRAINT_VIOLATION(HttpStatus.BAD_REQUEST, "COMMON4001", "요청 파라미터 검증에 실패했습니다."),As per coding guidelines src/main/java/**/exception/**: 새 예외 코드를 ErrorStatus enum에 추가했는지 확인.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/exception/handler/GlobalExceptionHandler.java`
around lines 44 - 53, Add a dedicated ErrorStatus entry for ConstraintViolation
(e.g., CONSTRAINT_VIOLATION or VALIDATION_CONSTRAINT_FAILED) and update the
GlobalExceptionHandler.handleConstraintViolation(ConstraintViolationException)
to return that new ErrorStatus's code instead of ErrorStatus.BAD_REQUEST;
specifically add the enum constant to ErrorStatus and change the
ApiResponse.onFailure(...) call in handleConstraintViolation to use
ErrorStatus.YOUR_NEW_CONST.getCode() (and keep the existing message and payload
behavior). Ensure the new enum follows the project's ErrorStatus
ordering/formatting conventions.
|
|
||
| public interface MenuRepository extends JpaRepository<Menu, Long> { | ||
|
|
||
| Page<Menu> findAllByRestaurantAndStatus(Restaurant restaurant, MenuStatus status, Pageable pageable); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Menu 엔티티의 Restaurant 관계 매핑 확인
rg -n -A 5 -B 2 '@ManyToOne|@OneToOne' --glob 'Menu.java'
# MenuRes DTO에서 Restaurant 필드 접근 여부 확인
rg -n -A 10 'class MenuRes|from.*Menu' --glob 'MenuRes.java'Repository: Konkuk-KUIT/KUIT7_REST-API
Length of output: 2633
🏁 Script executed:
cat -n src/main/java/com/kuit/baemin/repository/MenuRepository.javaRepository: Konkuk-KUIT/KUIT7_REST-API
Length of output: 832
@EntityGraph를 통한 N+1 문제 해결 필요
findAllByRestaurantAndStatus는 현재 최적화 전략이 없어 N+1 문제가 발생합니다. MenuRes.from(menu) 메서드가 menu.getRestaurant().getId()를 호출할 때, restaurant 필드가 LAZY-loaded이므로 페이지의 각 Menu 엔티티마다 추가 쿼리가 발생합니다.
다음과 같이 수정하세요:
`@EntityGraph`(attributePaths = "restaurant")
Page<Menu> findAllByRestaurantAndStatus(Restaurant restaurant, MenuStatus status, Pageable pageable);
또는 @Query와 fetch join을 사용하면 더 명시적입니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/repository/MenuRepository.java` at line 14, The
repository method findAllByRestaurantAndStatus in MenuRepository causes N+1 when
MenuRes.from(menu) accesses menu.getRestaurant().getId() because restaurant is
LAZY; update the repository to eagerly fetch restaurant either by annotating
findAllByRestaurantAndStatus with `@EntityGraph`(attributePaths = "restaurant") or
by replacing it with an explicit `@Query` that uses a fetch join for restaurant so
the Menu entities returned include their Restaurant and avoid per-row selects.
| public CartItemRes createCartItem(CartItemCreateReq req) { | ||
| Member member = memberRepository.findByIdAndStatus(req.getMemberId(), MemberStatus.ACTIVE) | ||
| .orElseThrow(() -> new MemberException(ErrorStatus.MEMBER_NOT_FOUND)); | ||
| Restaurant restaurant = restaurantRepository.findByIdAndStatus(req.getStoreId(), RestaurantStatus.ACTIVE) | ||
| .orElseThrow(() -> new StoreException(ErrorStatus.STORE_NOT_FOUND)); | ||
| Menu menu = menuRepository.findByIdAndRestaurantAndStatus(req.getMenuId(), restaurant, MenuStatus.ACTIVE) | ||
| .orElseThrow(() -> new CartException(ErrorStatus.MENU_NOT_IN_STORE)); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== CartController 엔드포인트 시그니처 확인 =="
fd -i 'CartController.java$' src/main/java | while read -r f; do
echo "---- $f ----"
sed -n '1,260p' "$f"
done
echo
echo "== 인증 주체 사용 흔적 확인 (`@AuthenticationPrincipal` / Principal / SecurityContext) =="
rg -n -C2 --type=java '@AuthenticationPrincipal|Principal|SecurityContextHolder|getAuthentication\(' src/main/java
echo
echo "== CartService 호출부 및 메서드 시그니처 확인 =="
rg -n -C3 --type=java 'createCartItem\s*\(|updateCartItem\s*\(|deleteCartItem\s*\(' src/main/java
echo
echo "== Security 설정 파일 확인 =="
fd -i 'Security*.java$' src/main/java | while read -r f; do
echo "---- $f ----"
sed -n '1,260p' "$f"
doneRepository: Konkuk-KUIT/KUIT7_REST-API
Length of output: 2241
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== CartService 전체 구현 확인 =="
fd -i 'CartService.java$' src/main/java | xargs cat -n
echo
echo "== 컨트롤러의 권한 검증 어노테이션 확인 =="
rg -n --type=java '@PreAuthorize|@Secured|@RolesAllowed' src/main/java/com/kuit/baemin/controller/CartController.java || echo "No `@PreAuthorize/`@Secured found"
echo
echo "== Security/WebSecurityConfig 파일 확인 =="
fd -i 'Security.*Config.java$' src/main/java | xargs cat -n
echo
echo "== 인증 관련 설정 확인 (모든 Security 관련 파일) =="
find src/main/java -name '*Security*.java' -o -name '*Config.java' | head -10 | xargs ls -la 2>/dev/null || echo "No security files"Repository: Konkuk-KUIT/KUIT7_REST-API
Length of output: 3985
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== WebSecurityConfig 파일 전체 저장소 검색 =="
find . -name '*SecurityConfig*.java' -o -name '*WebConfig*.java' 2>/dev/null | head -20
echo
echo "== application.yml/properties에서 security 설정 확인 =="
find . -name 'application*.yml' -o -name 'application*.properties' 2>/dev/null | xargs cat -n || echo "No application config found"
echo
echo "== CartItem 엔티티 확인 (memberId 필드 있는지, CartItemRepository 쿼리 확인) =="
fd -i 'CartItem.java$' src/main/java | xargs cat -n
echo
echo "== CartItemRepository 인터페이스 확인 =="
fd -i 'CartItemRepository.java$' src/main/java | xargs cat -n
echo
echo "== SecurityContextHolder 사용 여부 (서비스 내부에서 인증 객체 접근) =="
rg -n 'SecurityContextHolder|Authentication' src/main/java/com/kuit/baemin/service/ || echo "No SecurityContextHolder usage"Repository: Konkuk-KUIT/KUIT7_REST-API
Length of output: 3823
장바구니 항목 수정/삭제 시 소유자 검증이 없어 권한 우회가 발생합니다.
updateCartItem()과 deleteCartItem()은 cartId만으로 조회하고 member 소유권을 검증하지 않습니다. Line 58, 67의 findByIdAndStatus(cartId, CartItemStatus.ACTIVE) 쿼리가 member 조건을 포함하지 않으므로, 인증된 모든 사용자가 다른 사용자의 장바구니 항목을 수정하거나 삭제할 수 있습니다.
또한 createCartItem()은 Line 38에서 클라이언트 요청의 req.getMemberId()를 직접 사용하고 있어, 인증 주체와의 일치 여부를 확인하지 않습니다. 컨트롤러에 @AuthenticationPrincipal 주입도 없습니다.
필수 수정:
- CartController에서 인증 주체를
@AuthenticationPrincipal또는 SecurityContext를 통해 주입 - CartService 메서드들이 클라이언트 전달값 대신 인증 주체의 ID를 사용하도록 변경
- CartItemRepository의 쿼리를
findByIdAndMemberAndStatus()형태로 확장하여 멤버 소유권 검증 포함
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/main/java/com/kuit/baemin/service/CartService.java` around lines 37 - 43,
The service currently trusts client-supplied member IDs and looks up CartItem by
ID only, causing ownership bypass; update the controller to inject the
authenticated user (use `@AuthenticationPrincipal` or read SecurityContext) and
change CartService methods createCartItem, updateCartItem, and deleteCartItem to
use the authenticated member's ID instead of req.getMemberId(); additionally
add/replace repository queries with a new CartItemRepository method like
findByIdAndMemberAndStatus(cartId, member, CartItemStatus.ACTIVE) and use it in
updateCartItem/deleteCartItem to verify ownership before modifying or deleting
items.
구현한 API 목록
/members/{memberId}/stores/stores/{storeId}/stores/{storeId}/menus?page=0&size=10/members/{memberId}/addresses/cart-items/cart-items/{cartId}/cart-items/{cartId}기타 특이사항
ErrorStatus를 정의할 떄 얼마나 자세하게 많이 해야하는지 감이 잘 안 잡혔습니다.
swagger: https://share-subzero-ecologist.ngrok-free.dev/swagger-ui/index.html

Summary by CodeRabbit
릴리스 노트