내일배움캠프 TIL (230313): 로그인 상태에 따라 찜하기 여부 확인하기

Jiumn·2023년 3월 31일
0

찜 여부에 따라 다른 하트를 보여주기

워크샵 상세 페이지에 찜 하기 기능을 추가했다.
디폴트(찜을 하지 않았을 때)는 빈 하트(♡) 상태로 있다가 찜 하기를 한 유저가 접속하면 채운 하트(♥)를 보여주려고 했다.

이와 같이 동적으로 찜 아이콘을 보여주려면 다음과 같은 로직이 필요하다.
현재 우리는 wishlist라는 테이블에 user_id와 workshop_id를 저장하고 있다.
해당 유저가 특정 워크샵 상세 페이지에 접속했을 때 해당 워크샵의 id와 user_id를 받아 wishlist 테이블에 일치한 데이터가 있는지 확인하는 것이다.

문제는 로그인을 하지 않은 유저가 상세 페이지를 확인했을 때의 로직이었다. 그래서 경우의 수를 3가지로 정리했다.

  • 유저가 로그인 상태로 접속 시 → 해당 유저의 user_id와 workshop_id가 wishlist 테이블에 있는지 확인하여 빈 하트 or 채운 하트를 보여주기
  • 유저가 비로그인 상태로 접속 시 → user_id가 없는 상태(=비로그인)를 인식하여 찜하기 버튼을 빈 하트로 보여주기
  • 유저가 비로그인 상태로 접속한 후 찜하기 버튼을 눌렀을 때 → '로그인 후 이용 가능합니다' 경고창 노출

워크샵 상세 조회 API (controller)

  @ApiResponse({
    status: 200,
    description: '성공',
  })
  @ApiOperation({ summary: '워크샵 상세 조회 api' })
  @UseGuards(JwtUserPageGuard)
  @Get('/:workshop_id')
  async getWorkshopDetail(
    @Param('workshop_id') workshop_id: number,
    @CurrentUser() user: CurrentUserDto | boolean,
  ) {
    // 워크샵 상세 정보 가져오기
    const workshop = await this.workshopsService.getWorkshopDetail(workshop_id);

    if (typeof user === 'boolean' && user === false) {
      return { workshop, wish: false };
    }

    let isWish: boolean;

    if (typeof user === 'object') {
      isWish = await this.workshopsService.checkingWish(user.id, workshop_id);
    }

    if (isWish === false) {
      return { workshop, wish: false };
    }

    return { workshop, wish: true };
  }

user_id를 확인하기 위해 @UseGuards(JwtUserPageGuard) 데코레이터를 사용한다.

user가 false인 경우 비로그인 상태로 인식하고 wish 변수에 false를 할당한다. 만약 user가 객체 형태로 전달된다면 로그인한 유저라고 인식하고 찜하기 여부를 체크하는 함수로 전달한다.

JwtUserPageGuard 클래스

import { ExecutionContext, Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtUserPageGuard extends AuthGuard('refreshToken') {
  canActivate(context: ExecutionContext) {
    return super.canActivate(context);
  }

  // 만약 토큰이 불량 상태라면 user 는 false
  handleRequest(err: any, user: any, info: any) {
    if (!user) {
      return false;
    }
    return user;
  }
}

Service layer의 찜하기 여부를 판단하는 함수

// 워크샵 상세 정보를 가져올 때 로그인 한 유저가 있다면, 해당 유저가 워크샵을 찜 했는지 안했는지 여부를 확인
  async checkingWish(user_id: number, workshop_id: number) {
    const wishCheck = await this.wishRepository.findOne({
      where: { user_id, workshop_id },
    });
    if (!wishCheck) {
      return false;
    }
    return true;
  }
axios
    .get(`/api/workshops/${workshopId}`)
    .then((res) => {
      const workshop = res.data.data.workshop[0];
      const wishCheck = res.data.data.wish; // false or true

프론트 통신은 axios를 이용하여 wish 데이터를 클라이언트로 보내준다.

<button type="button" class="btn btn-outline-primary wish" onclick="addToWish()"></button>

하트 버튼을 클릭했을 때 해당 함수가 발동할 수 있도록 onclick 속성을 사용했다.

// 찜하기 유저에 있으면 하트 칠하기
if (wishCheck) {
	document.querySelector('.wish').textContent = '♥';
} else {
	document.querySelector('.wish').textContent = '♡';
}

wish 데이터가 true면 채운 하트, false면 빈 하트를 보여주도록 자바스크립트로 조작했다.

이커머스에서 워낙 기본적인 부분이라 간단하게 생각했는데, 은근히 고려해야 할 부분이 많았던 찜하기 기능이었다. user 로그인 여부와 찜하기 여부를 확인하기 위해 @UseGuards 데코레이터를 사용하는 부분이 조금 까다로웠던 것 같다.

profile
Back-End Wep Developer. 꾸준함이 능력이다. Node.js, React.js를 주로 다룹니다.

0개의 댓글