[JSCODE] controller, service, repository 구분하기

노을·2023년 3월 24일
0

JSCODE

목록 보기
3/7

공부 자료

✅ 요구사항을 만족하는 api 만들기

1. 상품 등록 api 만들기

  • RequestBody로 상품의 이름과 가격을 입력 받아서 ProductRepository에 상품을 저장하는 api
  • (심화) 이미 동일한 이름의 상품이 있다면 저장 실패
    - 저장을 실패했다는 안내를 어떻게 해주면 좋을지 고민해봅시다.

    다양한 방법이 있을겁니다. 문자열로 “상품 등록에 실패했습니다” 등의 안내 문구를 리턴할 수도 있고, 실패했다는 메세지를 담은 객체를 만들어서 json으로 전달할 수도 있습니다. 혹은 Exception을 만들어서 throw할 수도 있습니다. 자유롭게 구현해보세요!



처음에는 ExceptionCheckedException으로 만들었는데, 호석님이 에러를 던지다 보면 controller까지 에러 throw 코드가 넘어가게 되고, 이것은 메서드 모양을 변형시키는 것이라고 하셨다. 그리고 요즘은 CheckedException을 잘 안쓴다고 해서 내가 만든 Exception들이 RuntimeException을 상속받게 만들었다!

Controller

@PostMapping("/save")
public Long save(@RequestBody SaveProductRequest saveProductRequest) {
    return productService.save(saveProductRequest);
}

Service

// 저장 메서드
public Long save(SaveProductRequest saveProductRequest) {
    //상품명 중복 검사
    checkProductDuplicate(saveProductRequest.getName());
    return productRepository.save(saveProductRequest.getName(), saveProductRequest.getPrice());
}

// 중복 검사 메서드 (이미 존재하는 상품인지 확인하고, 있다면 에러를 throw한다)
private void checkProductDuplicate(String name) {
    if (isExistedProduct(name)) {
        throw new DuplicateNameException(); //UnCheckedException으로 구현함
    }
}

// 이미 존재하는지 확인하는 메서드
private boolean isExistedProduct(String name) {
    return productRepository.findOneByName(name).isPresent();
}


Repository

public Long save(String name, Long price) {
    Product saveProduct = Product.createProduct(sequence++, name, price);
    products.add(saveProduct);
    return saveProduct.getId();
}

시퀀스 값을 하나 증가시켜 products라는 ArrayList에 추가한다.



2. 상품 상세 조회 api를 아래의 요구사항을 만족하도록 변경하기

(controller는 service에게 위임하는 역할만 하도록 했고, 아래 코드는 모두 service 계층에서 구현된 메서드들이다.)

  • 상품 이름으로 상세 조회하는 api

  • (심화) 없는 상품명으로 조회했을 때 조회 실패

        public ProductResponse findOneByName(String name, String monetaryUnit) {
            // 없는 상품명으로 조회했는지 확인
            checkProductNotFound(name);
            Product findProduct = productRepository.findOneByName(name).get();
            ProductResponse productResponse = ProductResponse.from(findProduct);
            return getProductResponse(monetaryUnit, productResponse);
        }

        //존재하는 상품인지 확인하는 메서드 (없는 상품이면 에러를 throw한다)
        private void checkProductNotFound(String name) {
            if (!isExistedProduct(name)) {
                throw new ProductNotFoundException(); //UnCheckedException으로 구현함
        }

  • (심화) 가격을 원화와 달러를 구분해서 조회하는 api

    monetaryUnit을 쿼리 파라미터로 받아서 service 계층에 전달한다.
    service에서는 비즈니스 로직을 처리하고, controller에 반환할 때 ProductResponse dto로 반환하게 되는데, 이건 monetaryUnitdollar면 dollar로 바꿔서 반환하고, won이면 그대로 반환하게 만들었다.
    private ProductResponse getProductResponse(String monetaryUnit, ProductResponse productResponse) {
        if (monetaryUnit != null && monetaryUnit.equals("dollar")){
            productResponse.setMonetaryUnit(MonetaryUnit.DOLLAR);
            productResponse.setPrice(changeToDollar(productResponse.getPrice()));
            return productResponse;
        }
        productResponse.setMonetaryUnit(MonetaryUnit.WON);
        return productResponse;
    }
    여기서 원화를 달러로 바꾸는 changeToDollar()라는 메서드가 있는데, 나는 그냥
    won/1300 으로 개발자스럽지 않게 수동으로 바꾸도록 했다... (추후 수정이 필요할 것 같다. )



✅ (심화) 조회/등록 실패할 때 응답 interface 구현

상품을 등록할 때와 조회할 때 모두 ‘실패’가 발생 하는데요. 실패가 발생했을 때는 ‘실패사유’ 등을 공통적으로 전달해야 합니다. 실패에 대한 interface를 만들어서 등록과 조회에서의 각 실패를 구현해보세요.

이건 아직 공부를 덜 해서 공부를 더 하고 블로그 글 수정하겠습니다...⭐
@ExceptionHandler , @RestControllerAdvice 꼭 찾아보기!!!



✅ 블로그 글 쓰기

  • 배운 내용, 깨달은 점

    • spring을 조금은 안다고 생각했는데 전혀 그렇지 않았다..ㅎㅎㅎ
      이전에는 책으로만 접했는데 처음으로 Exception을 만드는 고민을 해본 것 같다.
  • 어려웠던 점, 반성하고 싶은 점 / 개선할 방법

    • 깃허브에 브랜치 나눠서 올리는 게 조금 어렵다,,, 기능 별로 나눠서 커밋하고 merge하는건 알겠는데
      day1에서는 텅텅 빈 자바 프로젝트였고, day4는 스프링 프로젝트여서 브랜치 별로 커밋하는 게 좀 헷갈린다. 커밋을 해두긴 했는데 잘 할 건지 모르겠다(?) 프로젝트 안에 프로젝트가 있는 느낌이랄까...
    • 나는 dto는 거의 setter를 열어둔다. 근데 호석님이 setter를 롬복으로 만들지 말고 직접 이름을 지정해서 만들라고 조언해주셨다. 어떤 값이 변경된다면 setA()보다 changeX()가 더 직관적인 이름이라고도 해주셔서 나의 무분별한 setter 사용을 반성했다.
    • cmd에선 push가 잘 되는데 인텔리제이에서는 push가 실패한다,,, 다음 스터디에서 팀원분들에게 물어봐야겠다..!
  • 궁금한 점

    • 제가 커밋을 잘 한 건지 궁금합니다...!ㅠㅠ day4 깃허브 코드 보러가기
    • 정답은 없겠지만, 원화와 달러를 구분해서 보여주는 정석의 코드(혹은 사용기술)이 궁금합니다!! :)


✅ 연습문제, 미션 내용 github에 push하기

day4 깃허브 코드 보러가기

profile
진짜를 알면 곁가지를 몰라도 된다

0개의 댓글

관련 채용 정보