'포잉마켓' 프로젝트 회고

단단·2024년 7월 5일
3

프로젝트

목록 보기
10/10

프로젝트 소개

반려동물 용품 공동구매 플랫폼 '포잉마켓'🐾

FE 기술스택과 사용 이유

  • Next.js - page router
    => 커머스는 초기 렌더링 데이터가 많다. 서버 사이드 렌더링(SSR)을 활용해 초기 로딩 속도를 개선했다.
    => 페이지 라우팅 방식이 현업에서 많이 이용되기 때문에 이에 익숙해지기 위해 사용했다. 편하기도 하다.

  • TypeScript
    => 타입을 명시하면서 에러를 예측하고, 방지할 수 있다.

  • SCSS + CSS Module
    => 변수, 상속 등을 사용할 수 있어 유지보수, 재사용에 편리하다.

  • @tanstack-react-query
    => 화면(클라이언트) 단위의 캐싱 처리와 서버 상태를 실시간에 가깝게 동기화 하기 위해 사용했다.
    => NEXT.js SSR에서 새로고침을 하지 않으면 동기화가 되지 않는다.

  • react-hook-form + yup
    => 비제어 라이브러리를 사용한 이유
    - 입력 필드가 변경될 때만 렌더링되므로 성능을 최적화할 수 있다.
    - 사용하기 편리하고, form을 관리하기 쉽다.
    - 번들 크기가 작다. 빠른 렌더링을 할 수 있다.(React Hook Form 약 8.4KB / Formik 약 22.7KB / Redux Form 약 27.4KB)
    => yup을 함께 사용한 이유
    - 각 조건의 에러 메시지를 설정할 수 있다.
    - react-hook-form으로만 유효성 검사를 한 것보다 코드 가독성이 좋다.

내가 구현한 것

  • 인증&인가 / 카카오, 구글 OAuth
    - accessToken을 쿠키에 저장해 인증했다.

    • 로컬스토리지 대신 쿠키를 선택한 이유
      => 쿠키는 보안 설정을 따로 할 수 있고, XSS 공격에 대비할 수 있다.
      => 쿠키는 별도로 헤더에 담지 않아도 요청을 보낼때 자동으로 담아서 보내진다.
  • 마이 페이지 / 프로필 수정, 주문 내역

    • presignedUrl 방식으로 이미지 삽입
      => presignedUrl 방식: S3 접근 권한 인증을 마친 URL을 이용해 브라우저에서 AWS S3 버킷에 파일을 바로 업로드 하는 방식
      => 클라이언트가 서버를 거치지 않고 파일을 저장소에 직접 업로드할 수 있어, 서버 자원을 절약할 수 있다. / 성능 최적화
    • 제품 결제-배송 상태에 따라 text, 기능, 라우팅이 다른 주문 내역 컴포넌트 구현
      const firstButton = (purchaseId: number) => [
      {
        id: 1,
        name: '주문 취소',
        disabled: false,
        onClick: () => handleCancelPurchase(purchaseId),
      },
      { id: 2, name: '교환/환불', disabled: false, onClick: () => handleExchangeOrRefund(purchaseId) },
      { id: 3, name: '교환/환불', disabled: false, onClick: () => handleExchangeOrRefund(purchaseId) },
      { id: 4, name: '배송 조회', disabled: false, onClick: handleCheckDeliver },
      ];
      const secondButton = (purchaseId: number) => [
      { id: 1, name: '배송 조회', disabled: true, onClick: handleCheckDeliver },
      { id: 2, name: '배송 조회', disabled: false, onClick: handleCheckDeliver },
      { id: 3, name: '배송 조회', disabled: false, onClick: handleCheckDeliver },
      { id: 4, name: '교환/환불', disabled: true, onClick: () => handleExchangeOrRefund(purchaseId) },
      ];
      const thirdButton = (purchase: PurchaseData) => [
      {
        id: 1,
        name: '리뷰 쓰기',
        disabled: true,
        onClick: handleWriteReview(purchase),
      },
      { id: 2, name: '리뷰 쓰기', disabled: true, onClick: handleWriteReview(purchase) },
      {
        id: 3,
        name: notReviewableId?.length > 0 && notReviewableId.includes(purchase.id) ? '리뷰 작성 완료' : '리뷰 쓰기',
        disabled: notReviewableId?.length > 0 && notReviewableId.includes(purchase.id) ? true : false,
        onClick: handleWriteReview(purchase),
      },
      { id: 4, name: '리뷰 쓰기', disabled: true, onClick: handleWriteReview(purchase) },
      ];

트러블 슈팅

  1. OAuth flow 관련 BE와 소통하기
  • 문제: OAuth 로직을 짰고, 토큰과 BE가 추출한 데이터는 넘어왔지만 로그인 후 랜딩 페이지로 이동하지 않았다.
  • 원인: BE와 FE가 이해하는 OAuth flow가 달랐다. 그래서 리다이렉트 URI를 처리할 콜백 페이지 필요성에 대해 이견이 있었다.
  • 해결: 처음엔 FE가 로직을 잘못 짠 줄 알고 관련해서 수정하려고 했다. 그러다가 BE와 2시간 가량 소통하면서 OAuth flow에 대한 인식을 맞추면서 문제를 해결했다.
  • 배운 점: 역시 협업을 할 때 당사자와 직접 소통하는 게 필수적이다. OAuth flow를 이해해서 앞으로 작업할 때 좀 더 수월하게 할 수 있을 듯 하다.
  1. presignedUrl 방식으로 이미지 삽입하기
  • 문제: presignedUrl까진 받았으나 이를 S3에 업로드 하기 위해 put 요청까지 보냈으나 이미지를 업로드 하는 과정에서 CORS 에러가 발생했다.
  • 원인: 파일 Url 외 필요없는 Url까지 업로드 하는 Url에 포함했다.
  • 해결: split 메서드를 사용해 필요한 부분만 잘라 이미지를 업로드 했다.
  • 배운 점: presignedUrl 방식을 처음 사용해봤다. 응답값을 제대로 확인해야겠다.
  1. 사파리 브라우저에서 폼에 하이픈 입력 불가
  • 문제: QA 시 사파리 브라우저에서 회원가입 폼에 하이픈을 입력할 수 없다는 피드백이 있었다. 000-0000-0000 양식을 맞춰야 가입할 수 있는 유효성 검사를 넣어뒀다.
  • 원인: 크로스 브라우징 이슈
  • 해결: 숫자 11자리를 넣으면 자동으로 하이픈을 입력해주는 로직을 추가했다.
  • 배운 점: 크로스 브라우징 이슈를 신경쓰고, 테스트 배포 후 브라우저 별 테스트를 진행해야겠다.

KPT 회고

KEEP

  • 인증&인가 기능을 처음 구현했다. 처음해보는 것이기도 하고, 초반엔 어려운 것 같아 회피했다. 그래도 결국 하고 나니 못 구현할 정돈 아니구나 라는 생각이 들었다. 앞으로도 새로운 기술, 기능을 할 때 너무 겁먹지 말아야겠다.
  • BottomModal을 만들 때, 폼을 만들 때 어떤 식으로 구현할 지, 어떤 기술을 사용할 지 고민을 많이 했다. 전보다 기술과 라이브러리를 사용할 때 이유를 고민하는 습관이 생겼다.
  • 이번에 tanstack-query를 처음 적용했다. 써보니까 확실히 pre-fetching 기능이 편했다. 전보다 새 기술을 적용하는 데 덜 걸린다.
  • 배포 후 QA를 2회 진행했다. 팀원들과 함께 QA를 하며 사용성을 개선하고, 배포 전 이슈를 해결할 수 있었다. QA의 필요성을 깨달았다.

PROBLEM

  • BE와 소통할 때 '내가 잘 모르니까' 라는 생각에 질문을 잘 하지 못했다.
  • tanstack-query를 사용하면서 쿼리 키를 정리하지 못했다.

TRY

  • 협업에 있어선 명확한 언어로 소통해야 하는 게 중요하다. 이를 위해 관련 지식을 더 많이 공부해야겠다고 생각했다.
  • 쿼리 키를 정리해서 코드 가독성을 좋게 하고, 휴먼 에러를 줄일 수 있게 리팩토링 해야겠다.

소감

BE, Designer와 처음 협업하면서 걱정과 기대가 많이 됐다. 그러나 이는 기우였다. 협업하는 팀원 모두 책임감 넘치고, 소통을 잘해서 원활하게 협업할 수 있었다.

새벽까지 함께 작업하고, 서로 돕는 과정이 정말 따뜻했다. 또, 컴포넌트 하나를 만들더라도 깊게 고민하는 팀원들의 모습에 좋은 개발자의 태도를 배웠다. 팀장님이 처음에 얘기했던 것처럼 3팀 팀원이 다 모여야 팀을 완성할 수 있듯 한 명 한 명이 소중함을 느꼈다. 좋은 동료들을 만난 것 같아 행복하다!

그리고 발표 때 반응이 좋았다. 실제 운영하는 서비스 같다는 평가를 들어서 뿌듯했다. 포트폴리오로 쓸 수 있게 잘 리팩토링 해야겠다.

profile
반드시 해내는 프론트엔드 개발자

0개의 댓글