리뷰 작성에 대한 예외처리

권태형·2023년 5월 31일
0

bnb Back-Server Project

목록 보기
13/31

이번엔 리뷰 작성에 대한 예외처리에 대해서 고민이 생겨서 이렇게 정리하게 되었다.

기본적인 리뷰작성에 대한 프로세스는 다음과 같다.

나는 숙소 상세페이지에서 리뷰페이지로 넘어갈 수 있도록 구상하였고,

기본적으로 숙소에 리뷰를 남기기 위해서는 다음과 같은 조건들을 만족해야만 한다.

  1. 로그인이 되어있는 우리 서비스의 회원인가?

  2. 로그인 된 유저가 해당숙소(상세조회한 숙소)에 대해서 예약을 한 데이터가 있는가?

  3. 예약한 데이터는 리뷰를 작성하는 날짜를 기준으로 체크아웃이 완료 되었는가?(숙소 사용을 마친 후 인가?)

처음 프로세스를 구상할 때는 이 정도의 조건만을 걸어두었다. 그리고 해당 조건을 만족할 수 있도록 코드 로직을 작성했다.

//review.controller.ts
@Post('/:id')
  @UseGuards(AccessTokenGuard) // 1. 로그인 유무를 확인
  createReview(
    @Param('id') id: number,
    @Body() createReviewDto: CreateReviewDto,
    @GetUser() user: User,
  ) {
    const houseId = id;
    const userId = user.id;
    return this.reviewService.createReview(userId, houseId, createReviewDto);
  }


//review.service.ts
async createReview(
    userId: number,
    houseId: number,
    createReviewDto: CreateReviewDto,
  ) {
    await this.housesService.findHouse(houseId);
    const existReservation = await this.reservationsService.findByFields({
      where: { userId, houseId },
    });
	
    //2. 예약정보를 확인
    //해당 숙소에 예약했던 정보가 없다면 에러
    if (!existReservation) throw new BadRequestException('예약 정보 없음');

    //3. 체크아웃 날짜와 리뷰생성 날짜를 비교
    //예약날짜의 체크아웃 시간이 리뷰작성 날짜보다 앞선다면 에러
    const today = new Date().toISOString().split('T')[0];
    if (existReservation.check_out >= today)
      throw new BadRequestException('리뷰는 숙소 체크아웃 이후 작성 가능');

    const reviewInfo = await this.reviewRepository.create({
      userId,
      houseId,
      ...createReviewDto,
    });

    await this.reviewRepository.save(reviewInfo);

    return { msg: '리뷰 작성 성공' };
  }

여기서 추가적인 예외처리가 있다면 await this.housesService.findHouse(houseId) 에서 파람즈로 들어오는 houseId의 숙소가 존재하는가?에 대해서 추가를 해 주었다.

생각해보면 로그인된 유저에게 그 숙소가 있고, 예약이 존재하고, 체크아웃 시간보다 늦게 작성한다면 얼마든지 리뷰를 작성할 수 있게 되어버린다. 이로 인해 문제점이 파생된다.

  • ⛔문제점. 과거에 한번 다녀왔는데 리뷰를 100개 1000개 쓸 수 있으면 안되지 않나?

한번 다녀왔으면 한번만 리뷰를 쓸 수 있게 제한을 둘 필요가 있으며, 어떤 예약에 대한 리뷰인지 확인할 수 있는 방법이 필요했다.


역시 이렇게 글로 정리하고 있다보면 해결책이 생각난다. 필자의 처음 Review테이블의 관계설정 ERD는 아래와 같다.

Review테이블은 Reservation(예약)테이블과 관계가 없게 설계했었다. 아직 개발과정이기 때문에 해당 테이블들을 One-To-One으로 관계를 지어주고 하나의 예약은 하나의 리뷰만 작성할 수 있도록 변경해보자.


해당 관계를 변경하여도 문제가 발생한다. 본인의 코드로직에서 Review테이블에 reservationId를 추가하고 관계를 설정해 주었지만, 컨트롤러에서 받는 정보에는 어떤예약에 대해서인지 알지 못하고, userId와 houseId로 예약정보를 찾아서 해당정보의 id를 reservationId로 저장한다. 그럼으로 또 다시 새로운 문제점을 야기한다.

  • ⛔문제점. 한 유저가 해당 숙소를 1년중 4번 다녀왔는데 리뷰를 미루다가 한번에 해당숙소에 대한 리뷰를 작성하려고 한다면, 결국 컨트롤러로 들어오는 userId와 houseId는 동일하기 때문에 reservation테이블에서 뽑아오는 정보 또한 4번 모두 동일한 정보를 뽑아오게 되어 1번 리뷰를 작성하면 나머지 3번은 작성이 불가능해 진다.

그렇다면 프론트에서 어떻게 내게 reservationId를 넘겨주게 할 수 있을까?
해당 방법은 일반적은 쇼핑몰이나, 배민등의 서비스에서 유추해 보았을 때 쇼핑몰은 구매확정된 상품에 대해서 리뷰를 작성할 수 있고, 배민은 주문이 완료되고 배달이 완료된 주문에 대해서 리뷰를 작성할 수 있다. 각 상품에 대해서는 시간제한을 두는 곳도 있고, 아닌 곳도 있다.

여러서비스들의 리뷰에 대한 공통점은 무엇일까? 내 프로세스처럼 숙소 상세조회 페이지에서 리뷰작성으로 넘어가는 것이 아니라, 이미 구매된 상품 또는 주문에 대한 목록에서 리뷰를 작성하러 넘어간다. 따라서 해당 상품 또는 주문에 대해서 1:1 또는 1:N으로 리뷰를 작성할 수 있도록 설계되어 있는 것인다.

내 서비스의 숙소 상세정보에서 예약정보(결국 check-out시간이 오늘을 넘어가면 사용완료정보)에 대한 고유id를 받는 방법은 찾아보기 힘들것 같다.

숙소 리뷰작성하기 API의 경우 만약 내가 프론트와 작업을 하게 된다면, 예약정보리스트 조회해서, 해당 예약정보의 check-out이 오늘을 기준으로 앞선다면 해당 API를 불러올 수 있는 요청방법(ex:리뷰작성하기 버튼)을 활성화 하는 방법을 추천하고, 필자의 백서버는 예약정보리스트의 중 해당 예약에 대한 리뷰를 작성할 수 있도록 id를 받는 방법으로 대체해야 겠다.

profile
22년 12월 개발을 시작한 신입 개발자 ‘권태형’입니다. 포스팅 하나하나 내가 다시보기 위해 쓰는 것이지만, 다른 분들에게도 도움이 되었으면 좋겠습니다. 💯컬러폰트가 잘 안보이실 경우 🌙다크모드를 이용해주세요.😀 지적과 참견은 언제나 환영합니다. 많은 댓글 부탁드립니다.

0개의 댓글