패스트캠퍼스 X 야놀자 프론트엔드 개발 1기 부트캠프 - 미니 프로젝트 회고록

Jun_Gyu·2023년 12월 19일
6

회고록

목록 보기
3/3
post-thumbnail

여행을 떠나신다고요? Traveler를 통해서 숙소를 예약해보세요!

Traveler

Test ID : sun@test.com
Test PW : 123qwe

🤔이번 프로젝트는 어떤 프로젝트?

이번에 진행한 미니 프로젝트는 프론트엔드 팀원들 뿐만 아니라,
백엔드 팀원들과 함께 협업을 통해서 진행한 프로젝트가 되겠다.

프로젝트 주제는 야놀자와 같은
숙박 예약이 가능한 플랫폼을 만드는 프로젝트를 진행하게 됐는데,
야놀자의 현업 개발자분들께서 심사에 참여하시는 만큼 긴장 + 걱정이 앞서기도 했지만

처음으로 백엔드단과 협업을 해서 만드는
말 그대로 제대로된 '프로젝트'를 진행할 수 있음에 굉장히 가슴설레었다.



👨‍💻어떤 부분을 맡았나?

아직 부족한 실력이었지만,
길었던 교육기간으로 인해 슬럼프에 빠져있던 스스로를 채찍질함과 동시에
파이널 프로젝트 전까지의 정신무장(?)을 위해 이번 프로젝트간 팀장 직책을 수행하게 되었다.

프로젝트간 우리조는 CDD(컴포넌트 주도 개발)을 도입하여 목업서버가 완성되기 전 짧은 기간동안
우선적으로 회의를 통해 선별한 공동컴포넌트 및 레이아웃을
팀원들이 각자 한두가지씩 맡아 제작하였고,

이후에는 자신이 개발하고자하는 페이지를 선정하여
개발을 진행하는 방식으로 미니 프로젝트를 완성했다.

이번 프로젝트에서 나는 유저의 로그인, 회원가입 페이지와 헤더 레이아웃을 구현함과 동시에
다른 페이지들에서 유저의 로그인 유무에 따라 페이지의 접근을 차단할 수 있도록
Auth Guard 기능을 구현하였으며,

로그인 방식으로는 백엔드 팀원들과 회의를 통해
JWT방식을 채택하여 세션 스토리지에 토큰을 저장하는 방식으로 처리하였다.



🤔왜 JWT 방식을 선택하였는가?

물론 보안성과 더불어 안정성을 논한다면 세션 방식의 로그인이 좀 더 알맞을 순 있지만,

이번 개발 기간이 2주간의 짧은 기간동안 결과물을 완성해야하는 시간적인 제한이 있었다.

백엔드측과 논의를 거쳤을때도
프로젝트간 사용 할 서버를 기반으로도
세션방식에 비해 비교적 가벼운 리소스 + 비용 등의 여러 이유로
JWT 방식을 좀 더 선호하였기에

결과적으로 백, 프론트 팀 모두 기존에 좀 더 익숙했던 JWT 방식으로 통일하기로 협의하여
로그인을 구현하게 되었다.



👀개발도중 겪은 어려움은?

특히 초반에 JWT 토큰을 세션 스토리지에 저장했었는데,

이번 프로젝트간 Next를 이용해 SSR(서버사이드렌더링)을 사용했던 터라
Auth Guard를 구현하는 데 있어 이 부분에서 문제가 발생했다.

이때 처음으로 Next.js에서 SSR을 사용할 때, 세션 스토리지의 데이터를
클라이언트 컴포넌트에서 바로 서버 컴포넌트로 전송할 수 없다는 문제점에 대해서 몸소 알게되었다.

해당 문제로 인해서 기존에 세션 스토리지에 저장된 토큰의 유무를 통해
Auth Guard 기능을 구현하는데 있어 어려움이 발생했다..

사실 해결책으로는 쿠키에 토큰을 담아서 전달하게 되면 간단히 해결되는 문제였지만,
이미 다른 팀원들은 각 페이지에서 유저의 정보를
세션 스토리지에서 가져오는 코드를 완성해가고 있던 터라

얼마 남지않은 기간에 결정을 번복하면 불필요한 작업을 추가하게 되는 결과를 초래하게 되어
다른 방안을 모색하게 되었다.

그렇게 하여 Middelware를 추가로 도입하게 되었다.

import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

export async function middleware(request: NextRequest) {
  const token = request.cookies.get('refreshToken');
  if (!token) {
    return NextResponse.redirect(new URL('/sign-in', request.url));
  }
  return NextResponse.next();
}

export const config = { // Auth Guard를 사용 할 페이지들
  matcher: ['/cart', '/reservation', '/reservation-check', '/reservation-list'], 
};

로그인 후
기존의 유저 데이터를 받아오는 부분은 세션 스토리지에서 받아오는 방식을 그대로 유지하되,
쿠키에 토큰을 따로 저장하는 로직을 추가하여

쿠키에 저장되어 있는 값의 유무를 기준으로
Auth Guard 기능을 활성화하는 방식으로 문제를 해결했다.

또한, 유저가 로그아웃 할 때
쿠키에 저장된 데이터는 세션 스토리지와 함께 삭제되도록 설정했다.

const [isOnline, setIsOnline] = useState<boolean>(false);

  useEffect(() => {
    const Token = sessionStorage.getItem('refreshToken');
    if (refreshToken) {
      setIsOnline(true);
    } else {
      setIsOnline(false);
      deleteCookie('Token');
    }
  }, []);

찾아보니, 내가 사용했던 개념은 세션 쿠키라는 이름의 방식으로,
쿠키의 expire 시기를 별도로 지정해주지 않으면
브라우저가 종료될 때 쿠키도 함께 삭제되는 방식이었다.



🧩리팩토링을 통해 개선한 대표적 이슈들

1. 회원가입 UX 개선

이부분은 야놀자 현업 멘토님께서 지적해주신 사항이기도 하다.

기존의 회원가입 UX를 참고하자면,

이메일의 경우에는 중복확인 완료 후에도 추가 확인요청에 대한 제한이 없었으며,
모든 input값을 입력 한 후 가입하기 버튼을 눌러야 유효성 검사가 진행되는 구조였다.

하지만 해당 부분은 사용하는 유저 측면에서는
키보드를 입력하는 즉시 유효성 검사를 진행하는 타 사이트들에 비해
좋은 사용경험을 기대하기 어려울 수 있다는 멘토님의 피드백을 참고로 수정을 진행하게 되었다.

그리하여 아래의 GIF와 같이 개선을 진행하였다.

기존의 handler 함수만으로 사용했던 유효성 검사 부분의 로직을 분리하여
useEffectonClick함수를 활용,
값을 입력하는 동시에 유효성 검사가 이루어지도록 코드를 손보았다.

이메일 부분은 중복확인 후 다시 확인요청이 가지 않도록 버튼을 비활성화 했지만,
언제든지 input의 값은 변경 가능하도록 하여
이메일값의 오타가 발생했을 시 수정이 용이하도록 했다.

또한 가입하기 버튼이 활성화되었을 때 인위적으로 입력값을 변동하여 유효성검사에 위배되면 가입하기버튼을 비활성화하여

회원가입이 진행되지 않도록 코드를 구성하였다.



2. 반응형 추가에 따른 Header 햄버거 메뉴 구현

사실 이 부분에서는 초반에 조원들과 두가지 의견이 대립했었다.

헤더 부분에 존재하는 최대 버튼이 3개 이하이기에,(로그인 시 3)
굳이 헤더를 만들지 않아도
버튼의 크기를 조절하는 것으로 대체할 수 있지 않겠냐

와,

모바일 사용자의 입장에서는 사용경험이 좋지 못할 것 같다

라는 두가지 의견이 존재했었다.

처음에는 버튼크기를 조절하는 것도 나쁘지 않을 것 같다라는 예상을 했지만,
직접 모바일 화면에서 터치를 통해서 확인해보니,

사용자의 손 크기나 핸드폰 기종에 따라서는
버튼 영역이 손가락에 가려지는 등
일부 유저들의 접근이 불편할 수도 있음을 간과했다.

그리하여 반응형 구현과 동시에 햄버거 메뉴바 형식으로 해당 기능을 완성하였다.



📜배울 수 있었던 점

이번 프로젝트야말로
진짜 개발자로써 많은것들을 경험하고, 배울 수 있었던 기회라고 생각한다.

평소에는 그냥 '일단 기능이 동작한다면, 일단 패스!'
라는 느낌으로 완성하기에 바빴지만,

이번 프로젝트에서는 특히나 이번 우리 팀원들의 '코드리뷰'
그 어떤때보다 더욱 더 빛을 발한 것 같다.

이전 여러 프로젝트에서는
pr을 올리고 코드리뷰를 하는 동안
완성에만 포커싱을 두고 굉장히 수동적으로 코멘트를 작성했다.
(확인 완료했습니다, 고생하셨습니다~, ~~ 작업 완료했습니다 확인해주세요! 등등..)

하지만 이번 팀프로젝트에서

"준규님, 확인해보니까 ~~ 라고 사용하셨던데, 왜 이렇게 사용하셨는지 알 수 있을까요!?"

라는 리뷰를 보고
머리를 한대 얻어맞은 느낌이었다.

솔직히 처음에는
코드에 대해서 뭐라고 대답을 할만한 이유를 생각하지 않았다.

아니, 오히려 누군가가 질문을 한다면

아, 내 코드가 잘못됐다는 거구나.
저분은 나보다 더 잘하시는 분이니, 말씀주신대로 수정해야겠다.

라는 생각으로 일관했으며,
누군가가 리뷰를 해주게 되면
해당 리뷰에 대해서 의심없이 그대로 반영했었다.

그러다 보니
기능이 원래 의도하던 대로 작동하지 않는 경우도 가끔 발생하여
내가 작성했던 코드로 다시 되돌리는 경우도 빈번했었다.


그래서였을까?
그런 줏대없던 기존의 모습을 바꿔야 겠다는 스스로의 성찰을 계기로
내가 작성했던 코드에 조금씩 근거를 가지고
대답할 수 있는 코드를 짤 수 있게 된 것 같다.

자신감을 가지고 리뷰에 응하다 보니 내가 아닌 팀원의 이슈도 발견하기도 했다..!


그동안 신경쓰지 않았던 "왜?" 에 대한 근거를 채워나가기 시작했으며,
이윽고 내가 생각했던 부분과,
팀원들이 생각했던 부분의 차이점에서 새로운 레퍼런스를 알게 되기도 했다.

어떻게 보면 더 일찍이 깨달았어야 했지만,
내가 사용한 코드들에 대해서 설명이 가능하도록 검토함에 있어서
조금 더 깊게 고민할 수 있었던 좋은 기회가 된 것 같다.

profile
시작은 미약하지만, 그 끝은 창대하리라

2개의 댓글

comment-user-thumbnail
2023년 12월 22일

글 너무 잘쓰셔서 좋아요 남깁니다!

1개의 답글