너무 늦은 4주차 프리코스 회고
4주차 미션은 프리코스 동안 가장 어려운 도전이었습니다. 회고를 적기엔 늦었지만, 당시의 고민과 배운 점을 기록하며 앞으로의 방향을 정리하고자 합니다.
4주차 목표와 구현 목록
4주차에는 모든 의존성을 관리하는 Config 클래스를 설계하고, 1~3주차 동안 순수 Java로 구현한 기능들을 조합하여 4주차 미션을 완성하는 것이 목표였습니다.
4주차 구현 목록
구매자의 할인 혜택과 재고 상황을 고려하여 최종 결제 금액을 계산하고 안내하는 결제 시스템을 구현한다.
- 사용자가 입력한 상품의 가격과 수량을 기반으로 최종 결제 금액을 계산한다.
- 총구매액은 상품별 가격과 수량을 곱하여 계산하며, 프로모션 및 멤버십 할인 정책을 반영하여 최종 결제 금액을 산출한다.
- 구매 내역과 산출한 금액 정보를 영수증으로 출력한다.
- 영수증 출력 후 추가 구매를 진행할지 또는 종료할지를 선택할 수 있다.
- 사용자가 잘못된 값을 입력할 경우 IllegalArgumentException를 발생시키고, "[ERROR]"로 시작하는 에러 메시지를 출력 후 그 부분부터 입력을 다시 받는다.
- Exception이 아닌 IllegalArgumentException, IllegalStateException 등과 같은 명확한 유형을 처리한다.
재고 관리
- 각 상품의 재고 수량을 고려하여 결제 가능 여부를 확인한다.
- 고객이 상품을 구매할 때마다, 결제된 수량만큼 해당 상품의 재고에서 차감하여 수량을 관리한다.
- 재고를 차감함으로써 시스템은 최신 재고 상태를 유지하며, 다음 고객이 구매할 때 정확한 재고 정보를 제공한다.
프로모션 할인
- 오늘 날짜가 프로모션 기간 내에 포함된 경우에만 할인을 적용한다.
- 프로모션은 N개 구매 시 1개 무료 증정(Buy N Get 1 Free)의 형태로 진행된다.
- 1+1 또는 2+1 프로모션이 각각 지정된 상품에 적용되며, 동일 상품에 여러 프로모션이 적용되지 않는다.
- 프로모션 혜택은 프로모션 재고 내에서만 적용할 수 있다.
- 프로모션 기간 중이라면 프로모션 재고를 우선적으로 차감하며, 프로모션 재고가 부족할 경우에는 일반 재고를 사용한다.
- 프로모션 적용이 가능한 상품에 대해 고객이 해당 수량보다 적게 가져온 경우, 필요한 수량을 추가로 가져오면 혜택을 받을 수 있음을 안내한다.
- 프로모션 재고가 부족하여 일부 수량을 프로모션 혜택 없이 결제해야 하는 경우, 일부 수량에 대해 정가로 결제하게 됨을 안내한다.
멤버십 할인
- 멤버십 회원은 프로모션 미적용 금액의 30%를 할인받는다.
- 프로모션 적용 후 남은 금액에 대해 멤버십 할인을 적용한다.
- 멤버십 할인의 최대 한도는 8,000원이다.
영수증 출력
- 영수증은 고객의 구매 내역과 할인을 요약하여 출력한다.
- 영수증 항목은 아래와 같다.
- 구매 상품 내역: 구매한 상품명, 수량, 가격
- 증정 상품 내역: 프로모션에 따라 무료로 제공된 증정 상품의 목록
- 금액 정보
- 총구매액: 구매한 상품의 총 수량과 총 금액
- 행사할인: 프로모션에 의해 할인된 금액
- 멤버십할인: 멤버십에 의해 추가로 할인된 금액
- 내실돈: 최종 결제 금액
- 영수증의 구성 요소를 보기 좋게 정렬하여 고객이 쉽게 금액과 수량을 확인할 수 있게 한다.
미션 구현 중 큰 실수...
이번에 미션 구현하면서 가장 큰 실수는 이 요구사항이였습니다.
입력
- 구현에 필요한 상품 목록과 행사 목록을 파일 입출력을 통해 불러온다.
- src/main/resources/products.md과 src/main/resources/promotions.md 파일을 이용한다.
- 두 파일 모두 내용의 형식을 유지한다면 값은 수정할 수 있다.
이 요구사항을 제출하기 하루전에 확인하는 큰 실수를 해버렸던 기억이 강하게 남아있습니다...
진짜 제출하기 24시간동안 손에 땀을 흘리면서 코드 구현을 했습니다. 다행히도 대부분의 요구사항을 만족하는 코드를 작성하였지만, 기존의 테스트 코드는 쓸데가 없어져 버려 의미가 사라져버렸습니다.
이번 미션을 하면서 다시 한번 깨달은 점은 요구사항을 정확하게 인지하여 정리하자... 입니다.
어찌되었든 어떻게든 기능 구현에 성공했지만 그렇기에 코드가 개판이 되어버렸습니다.
하지만 이번에 이렇게 코드를 급하게 구현하면서 알게된 점은 요구사항을 정확히 인지하고, 코드 설계 전 철저히 검토해야 한다는 점입니다.
Config란?
4주차 미션에서 새롭게 도입된 설계는 Config 클래스였습니다.
Config 클래스는 각 객체의 의존 관계를 주입하는 책임을 가집니다.
Config를 사용하는 이유
- 코드 유연성 확보: 의존 관계가 외부에서 주입되므로 수정이 쉬움.
- 코드 가독성 향상: 의존성 관리와 로직 실행을 분리.
Config 코드 예시
public class Config {
private final FileLeader leader;
private final UserRequest userRequest;
public Config() {
this.leader = new FileLeader();
this.userRequest = createUserRequest();
}
public UserRequest getUserRequest() {
return userRequest;
}
private UserRequest createUserRequest() {
return new UserRequest(new CallBackTemplate(), createController(), createViewHandler());
}
private ConvenienceController createController() {
Promotions promotions = new Promotions(leader.loadPromotionsFromFile("./src/main/resources/promotions.md"));
Products products = new Products(leader.loadProducts("./src/main/resources/products.md", promotions));
return new ConvenienceController(products, promotions);
}
private ViewHandler createViewHandler() {
return new ViewHandler(new CallBackTemplate(), new ApiHandler(new Validator()), new Input(), new Output());
}
}
이렇게 Config 클래스는 의존성을 정의하고 필요한 객체를 생성하여, 로직 코드에서 의존성 관리 부담을 줄여줍니다.
4주차 회고
이번 미션은 시간에 쫓기며 코드를 작성해야 했던 어려운 경험이었습니다.
하지만 동작하지 않는 아름다운 코드보다는 동작하는 덜 아름다운 코드가 낫다는 사실을 다시금 느꼈습니다.
앞으로는 요구사항을 꼼꼼히 분석하고, 나만의 방식으로 체계적으로 정리하는 습관을 들이고자 합니다.
또한, 시간에 쫓겨도 테스트 코드와 요구사항 검토를 놓치지 않는 개발자가 되기를 목표로 합니다.
'우아한 프리코스' 카테고리의 다른 글
[3주차] 우아한 프리코스 회고록 (3) | 2024.11.13 |
---|---|
[2주차] 우아한 프리코스 회고록 (2) | 2024.11.04 |
[1주차] 우아한 프리코스 회고록 (2) | 2024.10.22 |