[회고] wecode 1차 프로젝트

Dongmin Lee·2023년 2월 21일
1

회고

목록 보기
4/4

💿 서문

약 2주 간 진행한 첫 프로젝트가 끝이 났다.
뿌듯함보단 후련함이, 후련함보단 아쉬움이 더 큰 프로젝트였다.

💿 모티브 사이트

프로젝트 주제는 배달의민족에서 운영하는 배민문방구 를 모티브로 한 클론 코딩이었다.

클론 코딩이지만 이미지 소스들을 그대로 사용하지는 못하기 때문에 배민문방구를 Product / End-user / Tech 관점에서 분석하여 차용할 부분은 차용하고, 새로 포지셔닝할 부분은 포지셔닝해서 진행하였다.

팀 미팅 결과, 배민문방구가 추구하고 싶은 가치는 친근하고 가벼운 BI(Brand Image) 제고 라고 판단하였고 이를 프로젝트 사이트에 녹이고자 하였다.

결과적으로 기존의 정체성을 각색해서 중고 거래 플랫폼을 운영하는 모기업의 온라인 기프트샵을 컨셉으로 잡았고, 판매하는 상품은 재미있고 특이한 선물을 취급하기로 하였다. 선물이라는 특별한 가치를 가지고 가면서도 상품 자체가 부담스럽지 않고 재치 있는 것들이니 중고 거래 플랫폼이 원하는 포지셔닝과 맞을 거라고 판단했다.

위와 같이 우리의 서비스에 맞게 PET 분석을 다시 진행한 후 본격적으로 프로젝트를 시작하였다.

💿 업무 분담 및 일정 관리

업무 분담 및 일정 관리는 트렐로와 매일 아침 DSM(Daily Stand Meeting)을 통해 진행하였다.

우선 필수로 구현해야하는 부분과 추가로 구현할 부분을 티켓 단위로 나누어서 Backlog 파트에 작성하고, 주 단위로 스프린트를 나누어 당기 스프린트에 진행해야하는 티켓들은 Backlog에서 To-do로 이동시켰다.
이후 내가 진행하는 티켓에 담당자 라벨을 붙이고 맞는 단계에 따라 수정시켜주면서 팀원끼리 이 사람이 무슨 작업을 하고 있는지 공유할 수 있게 했다.

업무 분담 및 일정 관리 부분에서

  1. DSM에 꾸준하게 참석하지 못함
  2. 작업 history를 Trello에 제때 반영하지 못함
  3. 미팅 당시 Back-end 파트와 효율적인 소통을 하지 않은 점

와 같은 부분이 아쉬웠고 특히 Back-end와 데이터 프로토콜에 대해 소통이 부족했던 점이 프로젝트 막바지에 뼈저리게 느껴졌다.

💿 기능 구현

회원가입 / 로그인 / 캐러셀 / 푸터 파트를 맡아서 구현하였다.

💾 회원가입

우리 쇼핑몰의 컨셉상 목표는 수익 창출 뿐만 아니라 모기업 브랜드 이미지 홍보도 있었기 때문에 컨셉을 최대한 살려가기 위해 BI 컬러인 보라색을 적극적으로 활용하려고 했다. 따라서 회원가입 페이지에서도 input 포커싱 또는 button 활성화 시 색상 변경을 통해 BI 컬러를 홍보하려고 하였다.

회원가입과 로그인은 이미 구현해봤던 기능이었기 때문에 금방 끝날 거라 생각했지만 움짤과 같이 포커스 여부에 따라 placeholder를 이동시키는 애니메이션은 label을 이용해야 하기 때문에 생각보다 많이 까다로웠다.

또한 기프트샵이라는 특성상 고객의 로열티가 낮기 때문에 회원가입 시 최대한 편의성을 신경써야 고객 이탈을 최소화할 수 있을 것이라 판단하고 회원정보 입력 시 비밀번호 일치/불일치 등의 피드백을 즉각적으로 줄 수 있도록 코드를 구성했다.

해당 파트에서 state의 비동기적 흐름에 대해 확실하게 배웠다.
비밀번호를 재확인하는 input의 이벤트 핸들러 내에서 input 입력 값을 받는 state를 확인해 비밀번호 일치 여부를 체크하려고 하였는데, 이 경우 state는 비동기적으로 동작하기 때문에 현재 입력 받은 값이 아니라 이전 값을 받아버렸다.
결국 비동기 문제임을 깨닫고 일치 여부를 이벤트 핸들러 밖에서 확인하도록 만들어 해당 이슈를 해결하였다.

상수 데이터를 map을 돌려 세팅하는 법도 이 파트를 구현하면서 숙달했다. 회원 가입 페이지 내에는 input 요소들이 여러 개 배치되는데, 요소마다 하드코딩으로 마크업하고 싶지 않아 상수 데이터에 인풋마다 들어가야되는 값을 적은 후 map을 돌려 알맞은 자리로 가도록 배치하였다.

상기 부분과 연계하여 input과 관련된 state가 여러 개 생기는 경우도 클린 코딩과는 거리가 먼 것 같아 state도 객체로 관리하여 각각의 인풋 값들이 객체의 키값으로 치환하여 하나의 state로 관리할 수 있게 코딩하였다.

💾 로그인

로그인 부분은 크게 어려운 부분이 없었다.
이미 회원가입을 진행하면서 input 스타일링 부분도 익숙해졌고, 나머지 부분 또한 구현해봤던 부분이라 blocker가 될만한 이슈가 없었다.

로그인 버튼을 누르면 input에 담긴 값을 서버쪽으로 post request하게 되고, db에 해당 데이터가 있을 경우 서버에서 JWT 토큰을 담아 response를 보낸다.

나는 이 토큰을 활용해 로그인 성공 여부를 판단하였다. fetch하면서 response로 받은 토큰을 바로 로컬 스토리지에 set하게 로직을 구성했는데, response에 토큰이 없다면 로컬 스토리지 값에 undefined가 찍히는 점을 이용해 로컬 스토리지의 토큰 값이 undefined면 실패로 판단해 alert창, 아니면 성공으로 판단해 main 페이지로 이동시켰다.

💾 캐러셀

이번 프로젝트를 진행하면서 구현에 가장 애먹었던 부분이었다.
우선 애니메이션 자체가 fade 방식이 아니라 실제 이미지가 옆으로 이동하는 것처럼 보여주어야 했는데, 마지막 인덱스에서 처음 인덱스로 이동할 경우 되돌아가는 가는 모션이 보여져서 이 부분을 개선해야 했다. 대부분은 라이브러리로 구현을 하였지만 해당 프로젝트의 경우 써드파티 사용이 금지되었기 때문에 바닐라 로직으로만 구현해야 했기 때문에 난이도가 급상승했다.

transform 및 translate 속성을 이용해 이미지 크기만큼 이미지 배열을 이동시키면서 해당 인덱스에 맞는 화면이 보여지게 만들었다.

무한 슬라이드의 경우 마지막 인덱스에서 다음 인덱스로 이동할 시 첫번째 인덱스로 이동하게(반대의 경우도 동일하다.) 로직을 구성해 구현하였다.

무한 슬라이드에서 마지막에서 처음 인덱스 또는 처음 인덱스에서 마지막 인덱스로 이동할 시 애니메이션 처리가 굉장히 어려웠는데

seEffect(() => {
    fetch('data/banner.json')
      .then(response => response.json())
      .then(data => {
        setDataFromServer(data);
        setSlideList(data);
        setSlideList(prev => [data[data.length - 1], ...prev, data[0]]);
      });
  }, []);

상기와 같이 도트를 위한 state, 실제 캐러셀을 위한 state 두 개를 set해주고 실제 캐러셀의 경우 양 끝에 애니메이션 구현을 위한 복제본을 만들어 주었다.

이렇게 되면 마지막 인덱스에서 다음 인덱스로 넘어갈 경우 되돌아가지 않고 복제된 첫 인덱스의 화면으로 자연스럽게 넘어간다.

 useEffect(() => {
    setTimeout(() => {
      setIsTransition(false);
    }, 1000);
    currentIndex === 0 &&
      setTimeout(() => {
        setAction(0);
        setCurrentIndex(slideList.length - 2);
        setTimeout(() => {
          setAction(1);
        }, 20);
      }, 1000);
    currentIndex === slideList.length - 1 &&
      setTimeout(() => {
        setAction(0);
        setCurrentIndex(1);
        setTimeout(() => {
          setAction(1);
        }, 20);
      }, 1000);
    return () => {};
  }, [currentIndex, slideList.length]);

그리고 인덱스가 변경될 경우 setTimeout을 걸어 눈속임을 하였다.

마지막 슬라이드에서 복제된 첫번째 슬라이드로 이동하면 인덱스가 변경되면서 useEffect가 호출되고, trasition second에 들어갈 값을 0으로 만들면서 애니메이션 없이 바로 진짜 첫번째 슬라이드로 이동시켜버린다.

그런데 이 경우 문제는 슬라이드 배열을 map을 돌리게 될 때 복제된 슬라이드로 인해 unique한 key value가 사라진다는 점인데, 이 부분은 아직 풀지 못했다.

지금처럼 처음부터 배열에 복제된 슬라이드를 넣지말고 조건에 따라 배열에 복제된 슬라이드를 넣거나 빼서 최대한 슬라이드 배열을 원본 상태로 유지시켜야 구현이 가능할 것 같다.

💾 푸터

기본적인 마크업 부분이라 패스!

💾 기타 등등

아무래도 내가 맡은 부분이 캐러셀을 제외하곤 기능적으로 어려운 부분이 없다보니 다른 팀원들보다 널널해서 서포트를 해주었다. 다른 팀원들 파트가 구현하기 훨씬 어려워보여서 내심 미안한 마음이 들었다.

💿 Self-Feedback

프로젝트를 수행함에 있어 스스로 아쉬운 부분이 너무 많았다.

💾 Non-agile process

가장 큰 문제는 애자일하지 못했다는 점.

일단 기능 먼저 구현하고 통신 붙여보고 간단하게 스타일링 하고 다음 기능 구현하고.. 이런 방식으로 진행을 했어야 하는데 일단 완벽하게 구현하고 나서 다음 기능을 진행하려고 하다 보니 막상 꼭 필요한 기능을 구현하지 못하거나 정상적으로 작동하지 않았다.

일단 모양새가 어떻든 다리는 걸을 수만 있으면 되고, 팔은 물건을 집을 수만 있으면 된다.

이 부분을 이번 프로젝트를 통해 뼈저리게 느꼈다.

💾 카운터 파트와 소통

두번째로는 백엔드와의 소통이었다. 나름 얘기도 많이하고 서로 진도 체크도 하면서 이 부분은 문제가 없을 줄 알았는데 우리는 가장 중요한 부분을 서로 '이 정도는 다 알겠지?' 라고 생각하면서 빼놓고 얘기하고 있었다. 프론트엔드는 가장 단순한 구조의 mock 데이터를 붙여서 구현하면서 문제가 없다고 판단하고 있었고, 백엔드는 실제 사이트의 구조를 뜯어보면서 그에 맞춰 스트럭쳐를 짜고 있었다.

발표 당일 아침까지 시간에 쪼들려 구현하다가 막상 통신 붙여서 데이터를 받았을 때 에러가 뜨길래 로그를 찍어보니 받아온 데이터에 뎁스가 하나 더 있었다. 그 당시의 아찔함은..

💾 Product Manager로써

컨셉 설정은 방향을 잘 잡고 갔다고 생각한다. 다만 컨셉상 비회원 주문 기능이 핵심적인 사항이라 꼭 구현하고 싶었는데 내 역량 부족으로 구현하지 못한 점이 너무 아쉬웠다. 다른 팀원들은 내 기대의 200%를 해주었는데 정작 내가 스스로의 기대만큼 해내지 못했다. 발표 또한 데모 데이 직전까지 통신 이슈를 해결하느라 스크립트 작성도 못하고 키노트만 겨우 작성해서 진행하게 되었다. 다행히 구상 자체는 프로젝트를 진행하면서 계속 생각해왔던터라 큰 실수는 없었지만 진행이 매끄럽진 않았던 것 같다.

💿 결문

팀 프로젝트를 하면서 결국에는 나만 잘하면 되는구나 라는 생각이 들었다. 내가 더 열심히, 더 효율적으로 했다면 결과물이 더 좋을 거라고 생각하니 더 그런 생각이 드는 것 같다.
일단 반성은 리팩토링하면서 마저 하고 아쉬웠던 부분을 반면교사 삼아 다음 프로젝트는 회고에 아쉬움이 묻어나오지 않았으면 한다.

profile
어제보다 성장하기

0개의 댓글