[1차 프로젝트 회고] 폭풍 같던 2주를 돌아보며

YJ·2023년 3월 21일
0

프로젝트가 시작되기 전 매일같이 느꼈던 걱정들이 여전히 생생하다.
내가 아는 지식은 협소한데 해야하는 일들의 난이도는 그걸 훨씬 뛰어넘는 것들이어서 '과연?' 이라는 생각을 떨칠 수 없었다.
그러나 시작의 순간은 어느새 코앞으로 다가왔고.. 그래, 가 보자!

우리 팀이 클론 코딩할 웹사이트는 'Aesop(이솝)'으로 정해졌다.
처음에는 완전히 동일한 웹을 구현하려 했는데, 팀원들과 회의 중 좋은 의견들이 쏟아졌고, 무드는 가져가되 제품과 디테일은 우리가 원하는 방향으로 수정하기로 했다.
그래서 나온 결과물이 'SipScent'!!
처음 이름을 들은 사람들은 모두 욕인줄 알고 놀랐으나ㅎㅎ 향(scent)을 홀짝인다(sip)는 생각보다 건전하고 서정적인 이름에 팀원 모두 만장일치로 결정되었다.

1. 방향성

회원가입, 로그인, 장바구니가 모두 모달창으로 되어있고, 클릭시 페이지가 바뀐다는 느낌보다는 전체적인 플로우가 유려하게 흘러 시각적으로 안정감이 있었다.
반면에 애니메이션이 많아 로딩 시간이 오래 걸리고 불필요하게 요구되는 단계들이 한국인에게는 불편하게 느껴질 수 있겠다고 생각했다.

그래서 우리는 모달창으로 구현된 부분은 따라가되, 우리나라 사람들에게 좀 더 알맞은 속도와 형태(예를 들어 이름을 적는 란에 성과 이름을 나누지 않을 것)로 가져가자고 입을 모았다.

2. 무엇을 했는가

우리 조는 모든 역할을 삼등분해 시작하지 않고, 우선 각자 맡을 부분을 하나씩 정한 뒤 먼저 완성하는 사람이 그 다음 파트를 가져가는 방식으로 진행했다.
첫 주에는 레이아웃을 잡고, 두번째 주에 기능을 구현하는 것을 목표로 했다.

  • Nav & Footer (원래 Footer는 추가 구현으로 뒀던 녀석인데 막상 없으니 너무 허전한 느낌이 들어 기능 까지는 아니더라도 레이아웃은 잡자 싶어 빠르게 해결했다.)

  • 로그아웃

  • 제품 리스트

  • 필터

  • 정렬

  • 상품 상세 페이지 & 장바구니

3. 어떻게 했는가 (레이아웃을 제외한 기능 구현에 초점)

  • Nav : token 유무에 따라 로그인 / 로그아웃 변화 (이 부분은 프로젝트 기간이 끝난 다음날 추가로 구현해 보았다.)
const handleToggle = () => {
    setToggle(prev => !prev);
    localStorage.removeItem('TOKEN');
    alert('로그아웃 되었습니다.');
  };


// 처음에는 localStorage.length === 0 ? 로 작성했었다!
{Object.keys(localStorage).includes('TOKEN') ? (
  <button className="loginButton" onClick={handleToggle}>로그아웃</button>
            ) : (
  <button className="loginButton" onClick={showLoginModal}>로그인</button>
            )}

씻다가 문득, 지금은 로컬 스토리지에 토큰밖에 없으니 length 를 사용해도 잘 작동하지만 로컬 스토리지에는 토큰만 저장하는 것이 아닐테니 직접적으로 token에 접근할 방법이 있어야 한다고 생각해 찾은 방법이다.

  • 제품 리스트

    • 리스트에 들어갈 상품을 컴포넌트로 분리해 각각이 개별적으로 동작할 수 있게 하였다.
    • 동적 라우팅을 활용해 데이터에 따라 다른 카테고리의 상품 리스트가 그려지도록 하였다.
    • 마우스를 hover 했을 때 보여지는 장바구니 버튼으로도 장바구니에 담기도록 하였다.
  • 정렬, 필터

    • 쿼리 스트링을 활용해 원하는 필터에 해당하는 상품이 나열되도록 하였다.(중복 선택도 가능!)
    • 쿼리 스트링으로 가나다순, 높은 가격순, 낮은 가격순의 정렬이 가능하도록 하였다.
  • 제품 상세 페이지

    • 동적 라우팅으로 들어오는 데이터에 따라 그려지는 UI가 달라지도록 하였다.
  • 장바구니

    • 장바구니 리스트를 컴포넌트로 분리해 수량 변경 또는 삭제가 개별적으로 이루어지게 하였다.
    • 삭제 버튼은 마우스 hover 시 나타나게 하고, 수량은 + / - 버튼으로 변경 가능하게 하였다.

4. 마주쳤던 장애물들

우리들 사이에서 거의 밈과 같이 사용되던 말이 '태산같은 벽을 마주했다' 였다. 나중에는 '태산'만 들어도 깔깔대며 웃었는데 그만큼 우리를 울고 웃게 만들었던 오류들을 다시 꺼내보자면🧐

  • 필터

필터를 구현하는데 백엔드에서 받은 query string 이 tasting_notes="화사한" 과 같은 형태로 되어있어 따옴표를 어떻게 삽입해야 하나 고민이 많았다. 그래서 "${value}" 형태로 작성했더니 추가는 잘 되는데 삭제하면 따옴표만 남는 대참사 발생...
온갖 방법을 적용해봤지만 제자리 걸음이라 결국 멘토님께 조언을 구해 얻은 결과는 생각보다 간단했다. 바로 searchParams.append 에 따옴표를 뺀 value 그 자체로만 넣을 것!

  • 장바구니

누군가 그랬다. 장바구니는 카오스의 집합체라고.
그리고 그 말은 사실이었다.

<부모 컴포넌트>

<자식 컴포넌트>

컴포넌트로 분리한 장바구니 리스트의 state를 부모로 넘겨주어야 했다. 그러나 내가 아는 선에서 자식 컴포넌트의 정보를 부모로 넘겨줄 방법이 없었다.
그렇다면 애초에 부모 컴포넌트에서 state를 관리해야 하는데, 그렇게 되면 자식 컴포넌트가 개별적으로 동작하지 않는(하나의 상품을 수량 변경하면 모두 동시에 변경되는) 일이 발생한다.
이 모든 경우를 만족하는 코드를 생각해내는게 최고이자 최악의 난이도였다.

결과적으로 수량 변경 등의 상태 관리를 useState 를 사용하지 않고 함수로 해결했고, 함수의 인자를 props 로 넘겨주어 장바구니 리스트의 독립성을 확보했다.

한가지 더!

통신 테스트를 할 때는 토큰을 없애고 했기 때문에 순조롭게 되다가 발표 전날 최종 통신에서 토큰을 넣었는데도 장바구니가 열리지 않아 새벽 한시쯤 멘붕에 빠졌다. 허무하게도 문제는 fetch로 GET할 때 headers에 토큰을 넣었어야 하는데 그걸 빠트리는 바람에 발생한 것이었다. POST 나 DELETE 에는 잘 적어놓고 이게 무슨 바보같은 짓이었는지.

원하는 결과가 나오지 않거나 에러가 뜨는 순간 순간 망연자실 했지만 돌이켜보면 그 과정들로 하여금 확실히 성장하지 않았나 하는 생각이 든다. 멘토님이 지금은 빨간 글씨를 많이 봐야 좋은거라고 하셨었는데 그 얘기가 이제서야 조금 이해가 된다.

5. 아쉬움으로 남은 것들

이솝 홈페이지의 첫 인상이 '슬로우' 였다는 것에 모두가 동의했고, 그 부분에서 불편함을 느꼈다는 것도 공통된 생각이었다.

그러나 계속해서 사이트를 보다보니 우리가 느끼는 '이솝'의 이미지는 현재 구현된 웹페이지와 다를바 없었다.
이솝의 제품을 구매하는 사람들은 제품의 우수성(이솝은 오프라인 매장 서비스가 정말 좋은데 그만큼 제품에 대한 자신이 있기 때문이 아닐까) 뿐만 아니라 그들의 감성까지도 구매하고 있는게 아닌가 싶어 애니메이션을 최대한 줄이자는 처음의 판단이 그들의 의도와는 다르게 흘러갔을지도 모른다는 생각이 들었다.

다음 프로젝트 때는 기획을 좀 더 탄탄히 해서 판매자의 의도와 소비자의 니즈까지도 더 디테일하게 구성하고 싶다는 욕심이 든다.

기능적으로는 페이지네이션이나 무한 스크롤을 사용해보지 못한 것과, 검색 기능을 추가하지 못한 부분이 아쉬움으로 남는다.
메인 페이지에 사진이 아닌 동영상이나 적어도 gif 파일을 넣으려고 했는데 마지막까지 기능 구현에 매달리느라 신경쓰지 못한 것도 마음에 걸린다.

도약을 위한 워밍업이라 생각하며! 2차 프로젝트에서 더 잘 해봐야지.

끝을 맺으며

우리는 팀원들간 소통에 있어서는 정말 자부한다.
"유정님, 데이터 수정이 있을 것 같아요..." 라는 미안함과 걱정 섞인 목소리가 오히려 반갑게 느껴졌다. 수정이나 체크 사항들을 미루지 않아 나중에 생길 충돌을 방지할 수 있어 얼마나 다행이었는지 모른다.

그리고 모르면 일단 달려갔다. 서로 모르면 다같이 앉아서 몇시간이고 얘기하면서 해답을 찾았다. 말을 하면서 스스로 깨달아 가는 부분과 의견을 주고 받는 과정에서 생기는 사고의 확장이 정말 큰 공부가 된다는 것을 느꼈다.
몇 시간에 걸친 방황 끝에 맞이하는 단비같은 해결책은 말로 표현할 수 없을 정도로 시원하고 통쾌했다. (실제로 팀원들과 하이파이브를 하도 해서 손바닥이 성할 날이 없었다🤣)

백엔드에서 구현하는 기능들은 프론트에서 완성시키지 못하면 화면에 그려지지 못하기 때문에 그 노력이 헛되지 않도록 마지막까지 완성시키고자 했다. 우리는 생각지도 못했던 에러 핸들링을 끊임없이 파악하고 마지막까지 완벽한 웹을 만들어내기 위해 노력해준 백엔드 팀원들한테 다시 한번 감사의 마음를 보낸다. (나중에 다른 팀에게서 들은 이야긴데 특히 필터 구현한걸 보고는 백엔드의 역량에 많이 놀랐다고. 괜히 내가 다 뿌듯했네👍🏼)

각자의 자리에서 끊임없이 노력하고 애써준 우리 팀원들, 그리고 PM님들 고생 많았습니다!

Github https://github.com/wecode-bootcamp-korea/43-1st-Sipscent-frontend

배포 완료! http://sipscent.s3-website.ap-northeast-2.amazonaws.com/

profile
Hello

0개의 댓글