- 주문 생성 API
- 주문 상품 개별 취소 API
- 주문 상품 조회 API
- 요구사항 분석
- 도메인 모델, DB 설계
- 애플리케이션 환경 설정
- 프로젝트 패키지 구조 설계,
- 서비스 로직 개발 및 예외 처리
- API 문서화 및 테스트 코드 작성
| 항목 | 선택 기술 | 이유 |
|---|---|---|
| Framework | Spring Boot | - 개발 생산성 증가 - 환경 설정 간편화 - DI(의존성 주입) 지원 - 싱글톤 패턴 지원 - 트랜잭션 관리 용이 - 공통 예외 처리 기능 제공 |
| DB | H2 (In-memory) | - 테스트 용이 - 외부 DB 없이 빠르게 테스트 가능 |
| ORM | 순수 JPA + Spring Data JPA | - 객체지향적 설계 가능 - 반복되는 쿼리 감소 (쿼리 메소드) - 개발 생산성 증가 |
| API Docs | Swagger | - REST API 명세 자동 생성 - 문서화 및 테스트 용이 |
| 테스트 | JUnit5 | - Java 진영 단위 테스트 표준 - 다양한 테스트 기능 지원 - Spring과의 통합 용이 |
💡 주요 고려사항
- 비즈니스 로직 대부분이 엔티티에 구현, 서비스는 이를 호출하는 도메인 모델 패턴 적용
- 주문 생성 및 주문 상품 개별 취소 시, 재고 및 금액 처리는 하나의 트랜잭션으로 묶어 데이터 정합성 보장
- 상품 재고는 인기 상품의 경우, 동시성 이슈 발생 고려하여 주문 생성 시에 재고 감소는 비관적 락(Pessimistic Lock), 주문 취소 시에 재고 복구는 낙관적 락(Optimistic Lock) 적용
- 정적 팩토리 메서드를 사용하여 객체 생성 로직 캡슐화 및 명확한 메서드명을 통한 의도 전달
- 주문 엔티티를 중심으로 연관관계 매핑과 객체 그래프 탐색을 활용하여, 주문 상품 및 상품 정보를 객체지향적으로 설계하고 구현
- 전역 예외 처리 클래스를 통해 전역적으로 컨트롤러에 전달 및 발생하는 예외(에러)를 일관되게 처리하여 클라이언트에 응답, 이로써, 비즈니스 로직 내의 try catch문 등의 코드 중복을 줄이고 예외 처리 책임을 분리하도록 구현
- 각 컨트롤러마다 Swagger 문서화를 위한 별도의 ControllerDoc 인터페이스를 정의
- 상세 예외 내용은 서버에 로깅하도록 하여 예외(에러) 발생 시, 개발자가 로그를 보고 에러를 조치하도록 구현
- 자주 발생할 수 있는 도메인 예외 상황들(존재하지 않는 상품 조회, 재고 부족, 중복 취소 등)에 대해, 커스텀 예외 클래스를 별도로 정의하여 상황별로 명확하게 예외를 구분하고 처리할 수 있도록 구현
- 예외 발생 시 사용자에게 명확한 메시지 반환
- 입력받은 상품 ID + 수량 리스트에서 상품 ID를 미리 List에 담아두고, 상품 조회 시, IN 쿼리로 조회함으로써 쿼리 횟수 감소를 통한 성능 최적화
- 상품 주문 수량 만큼 재고 감소
- 상품별 할인금액 적용 후 상품의 개당 실구매금액 반환
- 개당 실구매금액 * 수량을 해당 주문 상품의 실구매금액으로 order_items 테이블에 저장
- 모든 주문상품의 실구매금액의 합인 전체 주문 금액을 order 테이블에 저장
- 사용자가 장바구니에 주문 상품을 담아두고, 주문을 하듯이, 주문 상품에 대한 엔티티를 먼저 생성 후, 해당 주문 상품을 생성할 주문에 넣어 구현
- 조회할 상품의 Id를 미리 List에 담아두고, 상품 조회 시, IN 쿼리로 조회함으로써 쿼리 횟수 감소를 통한 성능 최적화
- 주문, 주문상품, 재고 차감은 모두 하나의 트랜잭션 안에서 처리
- 주문번호, 상품ID로 주문상품 조회
- 주문 상품 개별 취소 시, 해당 주문 상품에 대한 주문 상태를 CANCELED로 변경 (타입 안정성 열거형 패턴 Enum 클래스 적용)
- 존재하지 않는 주문번호 또는 상품 ID 로 요청 시 에러 처리
- 이미 취소된 상품에 대한 재취소는 예외 처리
- 취소 처리 시 재고 복구 및 전체 주문 금액 재계산
- 주문번호로 전체 주문 상품 목록 및 전체 주문 금액 조회
- Lazy Loading(지연 로딩) + batch size 전역 설정을 통한 컬렉션(orderitems) 조회 최적화
- Read-Only 트랜잭션 적용으로 성능 최적화
ItemEntity: 상품 정보OrderEntity: 주문 정보OrderItemEntity: 주문 내 개별 상품
-
하나의 주문(
Order)은 여러 개의 주문상품(OrderItem)을 포함 -
하나의 상품(
Item)은 여러 주문에 포함 -
Order와 Item은 N:M(다대다) 관계에 해당하며, 이 관계를 명시적으로 표현하기 위해 OrderItem 엔티티를 연결 테이블(연결 엔티티)로 설정 OrderItem은 각각 Order와 Item에 대해 다대일(N:1) 관계를 맺고 있어, 결과적으로 두 개의 다대일 관계를 통해 다대다 관계를 구현한 구조
-
OrderItem은 단순한 중간 테이블로서의 역할 뿐만 아니라-
주문 수량
-
실구매금액
-
취소 여부
등의 필드들을 개별적으로 관리
-
-
연결 엔티티 방식(Many-to-One 양방향 관계) 으로 매핑
-
성능 최적화를 위해
OrderItem에@ManyToOne(fetch = LAZY)전략을 사용하여 지연 로딩을 적용
🗂️ com.ssg.ssg.domain
도메인(order)에 대한 핵심 비즈니스 로직을 담당
| 계층 | 설명 | 책임 |
|---|---|---|
| Controller | 클라이언트 요청의 진입점 | HTTP 요청 처리, 응답 반환 |
| Service | 비즈니스 로직 처리 계층 | 핵심 도메인 로직 호출, 트랜잭션 처리 |
| Repository | 데이터 접근 계층 | 데이터베이스와의 연결, 쿼리 실행 |
| Entity | DB 테이블과 매핑되는 객체 | 테이블 구조 매핑, 비즈니스 로직 정의 |
| DTO | 요청/응답 데이터 전달 객체 | API 요청 및 응답용 데이터 구조 정의 |
🗂️ com.ssg.ssg.global
전역적이고 재사용 가능한 설정과 예외 처리 등을 담당
- exception: 공통 예외 처리
- code: 전역 에러 코드 관리 클래스 (ErrorCode)
- config: Swagger 설정 등 전역 설정 클래스
- Swagger UI 경로:
/swagger-ui/index.html
- 테스트 화면 경로: /test
- 통합 테스트: 서비스 주요 기능 수행 후, 실제 DB와 DTO 값이 예상대로 동작하는지 검증하는 테스트
- 기능별 단위 테스트: 각 기능의 동작을 개별적으로 확인하는 테스트
- ConCurrencyTest : 재고 차감/복구 동시성 테스트
- ItemEntityTest : Item 기능 테스트
- OrderEntitytest : OrderEntity 기능 테스트
- OrderItemEntityTest : OrderItemEntity 기능 테스트
- OrderServiceTest : 트랜잭션 적용, 필수 API 테스트
