1차 프로젝트 회고록: Aesop 클론

김현수·2022년 5월 7일
1

Posea: Aesop 클론 프로젝트

본격적으로 팀을 이뤄 페이지를 나눠 작업하고 합치는 첫 프로젝트였다. 팀의 이름인 Pösea(푀세아)는 원본 사이트인 이솝의 영어 철자인 Aesop을 뒤집은 것으로, 별 의미 없이 내가 적어본 것이 그대로 받아들여졌다.

혹시 무슨 뜻이 있나 발표 때쯤 돼서 번역기를 돌려봤는데... 충격적인 번역 결과를 얻었다. 다음부터는 무난하게 짓든지, 무슨 뜻인지 한 번쯤은 찾아봐야 할 것 같다.

목표

첫 프로젝트이니만큼 많은 기능을 구현하는 것엔 큰 욕심이 없었고, 기본 필수 기능을 구현하는 것이 목표였는데, 팀원 분들 모두 해당 목표에 공감해주셨다.

팀 프로젝트를 시작하며 팀 단위로 상담을 받았는데, 그 중에서 들었던 말 중 가장 인상깊었던 말은 혼자 빠르게 완성한다고 프로젝트가 완성되는 것이 아니다 였다. 상담 이후 추가로 개인적인 목표로 잡은 것은, 빠르게 구현하고 다른 팀원들을 돕는 것이었다.

모든 팀 프로젝트가 다 그렇겠지만, 나는 특히나 다른 팀원들이 맡은 페이지와 연결고리가 되는 페이지를 맡았기 때문에, 다른 팀원들이 어려움을 겪는 부분을 돕고자 노력했다.

구현한 것

팀은 프론트엔드 넷, 백엔드 둘로 구성됐다. 프로젝트를 마치며 총 구현한 페이지와 기능은 다음과 같다.

  • nav, 상품 리스트
  • 메인페이지, 카트, 푸터
  • 제품 상세 페이지
  • 로그인 / 회원가입

나는 네 가지 중 nav, 상품 리스트를 맡았다. 첫 스프린트 때는 nav를, 두 번째 스프린트 때는 상품 리스트를 구현했고, 구현하는데 큰 어려움은 없었다.

어려웠던 부분

1. 스크롤 막기

// 메뉴 버튼 클릭 시 스크롤을 막는 CSS 클래스를 넣음

const onGnbButtonClick = e => {
  document.body.classList.add('stopScroll');

  // ...
};

// 닫기 버튼 클릭 시 스크롤을 푸는 CSS 클래스를 제거

const onGnbCloseButtonClick = e => {
  document.body.classList.remove('stopScroll');

  //...
 };

이솝 페이지는 내브 카테고리의 메뉴를 누르면 스크롤이 막힌다. 해당 기능을 구현하기 위해 스택 오버플로우 등을 찾아보았는데, 공통적으로 body 태그에 overflow: hidden; 스타일을 주는 것이 답이라고 작성되어 있었고, bodyclassList를 제어하는 방식으로 코드를 작성했다.

처음 작성하면서도 뭔가 리액트스럽지않다는 느낌을 받았다. 아니나다를까 멘토님이 해당 코드를 보고 document로 직접 접근하지 않고, 관리되는 state 값을 통해 동적으로 관리하면 어떨지 제안을 해주셨다.

처음에는 이 리뷰를 읽고 document.body를 사용하지 말라는 뜻으로 이해했고, state를 이용해 스크롤을 막아보려고 많은 노력을 했다. 그리고 모두 실패했다.

<nav> 태그는 다른 태그들과 형제 요소들로 놓여지게 되고, 따라서 다른 태그들과의 공통 조상 태그가 rootbody밖에 없었다. 원한다면 Router.js에서 만들 수야 있겠지만, 이 경우 해당 파일이 온전히 라우팅에만 집중하지 못한다는 점과, state를 Router.js에서 선언하는 것이 적절하지 못하다는 린터의 경고가 있었다.

다른 분들 역시 해결 방법이 가지각색이었다. <style> 태그를 만드는 분도 계셨고, state와 삼항연산자를 이용해 document.body.style.overflow를 제어하시는 분도 계셨다. 하지만 결국 body를 직접 제어한다는 점은 같아서 내가 작성한 코드와 크게 다르지 않다고 생각했다. 고민은 깊어졌는데, 금요일 밤이 지나가고 있어 멘토님께 여쭤볼 수도 있고, 주말 내내 해결책을 찾느라 고심했다.

월요일에 멘토님께 여쭤보니, "body를 건드려야 하는 것은 맞다. 단 해당 코드를 작성하기 전 충분히 고민하고 작성한 것인지를 확인하기 위해 물어봤던 것이다." 라는 답변을 들을 수 있었다. 결국 처음 작성한 코드에서 수정한 부분은 없지만, 스크롤 막기 라는 단순한 기능을 구현하기 위해 깊게 고민했던 시간들이었다.

2. 스크롤 다운 시 nav바를 사라지게 하기

const [scrollY, setScrollY] = useState(0);
const [isScrollingUp, SetIsScrollingUp] = useState(true);

useEffect(() => {
  const onScroll = () => {
    const currentScrollY = window.scrollY;

    if (scrollY >= 80) {
      scrollY - currentScrollY > 0
        ? SetIsScrollingUp(true)
      : SetIsScrollingUp(false);
    }

    setScrollY(currentScrollY);
  };

  window.addEventListener('scroll', onScroll);
  }, [scrollY]);

nav바가 80px이므로, 80px을 넘겨 스크롤 다운이 계속되면 isScrollingUp state를 변화시켜, 해당 state에 따라 nav의 클래스가 변하는 방식으로 작성했었다.

역시 어려운 기능이어서 스택 오버플로우를 참고하며 작성했는데, 이 코드대로라면 멘토님께서 scrollY가 변동될 때마다 이벤트리스너가 달리게 되니 구분해서 생각해보라고 리뷰해주셨다. 이후 수정한 코드는 다음과 같다.

const detectScrollDirection = e => {
  if (window.scrollY >= 80) {
    e.deltaY > 0 ? setIsScrollingUp(false) : setIsScrollingUp(true);
  }

  setScrollY(window.scrollY);
};

useEffect(() => {
  window.addEventListener('wheel', detectScrollDirection);
}, []);

가장 먼저 들었던 생각은 onScroll 함수를 useEffect 밖으로 빼고, useEffect 안에선 최초 마운팅 시점에 윈도우에 이벤트리스너를 부착하는 방식이었다. 단 이렇게하니 scrollY가 초기화됐다 변동했다를 반복해, 결론적으로 원하는 대로 동작하지 않았다.

구글링을 통해 wheel 이벤트의 event.deltaY라는 속성을 알 수 있었고, 해당 속성을 이용하는 방식으로 수정할 수 있었다.

아쉬운 점

소통, 소통, 소통!

위코드에 들어가기 전부터, 많은 선배 기수들이 '소통이 부족했다'라는 내용으로 회고록을 작성한 것을 보았다. 프로젝트를 직접 하기 전까진 솔직히 의문이었다. 충분히 상의하고, 그에 맞춰서 진행하면 되는 것 아닌가? 목 데이터로 작업하게 되면, 공유해가면서 이야기하면 되는 것 아닌가? 아니었다.

분명 본격적인 구현에 앞서 프론트와 백이 모여 상의했다. 어느 부분에서 어떤 데이터를 받기까지는 상의했는데, 해당 데이터의 어느 단계에 어떤 정보가 들어가는지 등 자료 구조까지 얘기하지 않았던 것이 문제였다.

목 데이터를 기반으로 작업하며 트렐로에 티켓을 만들어 공유했었다. 하지만 공유한다고 그대로 뚝딱 만들 수 있는 것은 아니었다. 백엔드도 백엔드 나름대로의 어려움이 있었을 것이다. 자세히 듣진 못했지만 테이블을 몇 차례 다시 짜야했다고 들었다.

더욱이, 백엔드 분들이 로그인, 회원가입을 먼저 작업하고 상품 데이터를 그 후에 작업하셨던 터라, 목데이터로 작업해야하나 초조했다. 결국 완벽하게 목데이터대로 들어오진 않았지만, 그래도 백엔드분들이 열심히 구현해주셔서 로직을 크게 수정할 일은 없었다.

뻔한 말이 뻔한 말이 된 것은 그만큼 많이 언급되었다는 것이고, 그만큼 많은 사람이 그 점을 느꼈다는 것이다. 위코드에서 공부할 때마다 매번 들었던 말이 '협업과 소통'이었던 이유, 많은 선배 기수들의 회고에서 소통이 계속 등장하는 이유, 다른 책과 글에서 소통을 강조하는 이유를 프로젝트를 겪고 나서야 알았다.

그래도 더 많은 기능을 구현했었다면

아무리 욕심 없이 임한 프로젝트였다지만, 욕심이 아주 안 났던 것은 아니었다. 시간과 중요도의 문제로 플래닝 미팅 때 계획했던 검색과 필터링 기능은 구현하지 못했다. 개인적으로는 백엔드와 통신을 많이 할 수 있는 기능이다보니 구현하지 못해서 참 아쉽다.

기능 구현을 하지 못 했던 것이 더욱 아쉬웠던 점은 작성한 코드의 절대적인 양이 적었던 것 같아서이다. 하루는 다른 분들을 돕다가 정작 나는 코드를 한 줄도 짜지 않았던 날도 있었다. 다른 분들도 '현수님은 2시간 앉아계시고 8시간은 돌아다니시면서 도와주시는 것 같아요'라는 말을 종종 하시곤 했다.

물론 다른 분을 도와 함께 에러를 해결하는 것은 보람찬 일이었고, 나 스스로의 성장에 도움이 되는 것이었다. 분명 그러한 경험을 통해서만 얻을 수 있었던 성장점이 있었다. 하지만 그것과는 별개로 아쉬움은 분명히 존재했고, 집에 돌아가며 이게 정말 맞는 건가 고민하곤 했다.

하지만 그럴 때마다 프로젝트를 시작하며 세웠던 목표를 향해 충분히 나아가고 있다고 생각했고, 추가 기능 구현은 2차 프로젝트 때 하면 된다고 생각했다. 결론적으로 유저 입장에서 필수적인 기능(메인 페이지 접속 - 회원가입 - 로그인 - 내브바를 통해 상품 리스트로 이동 - 상품 상세 페이지 - 장바구니 담기)을 모두 담은 프로젝트를 완성할 수 있었다.

편하게 구현하고자 UX를 고려하지 않았던 건 아니었나

구현을 거의 마치고 다른 분들께 혹시 버그가 있는지 한 번 사용해봐달라고 부탁을 드렸는데, 한 분께서 이런 말을 하셨다.

  1. 행간과 자간이 너무 좁습니다.
  2. 상품명과 가격은 다른 폰트 웨이트를 주는 것이 좋을 것 같습니다.
  3. 캐러셀 아이템은 다섯개인데, 세개가 꽉 차게 들어있어 넘겨볼 생각이 들지 않았습니다.

1번과 2번은 CSS에 몇 줄을 추가하는 것으로 해결할 수 있었다. 문제는 3번이었다. 생각지도 못한 부분이었고, 시간도 촉박해 결국 수정하지 못했다.

이솝은 캐러셀의 아이템을 일부러 반쯤 잘려있게 설정해놓아 사용자에게 다른 상품들이 캐러셀의 뒤에 남아있다는 것을 알리고 있었지만, 내가 구현한 캐러셀은 그런 것 없이 세개의 아이템이 꽉 차게 들어가 있어 눌러봐야만 존재하는지 알 수 있었다.

이솝 페이지는 거의 모든 요소들이 반응형으로 만들어져 있다. 캐러셀 역시 각 아이템이 vw 내지는 %로 계산되어 있어, 나도 전체 캐러셀을 75vw로, 각 아이템을 75vw / 3으로 가로 길이를 설정했던 것이 문제였다.

지적을 들었을 때 가장 먼저 생각났던 것은 위코드에서 공부를 시작하며 만들었던 자기소개 페이지의 머릿말이다. 모든 사람의 접근성을 생각하는 프론트엔드 개발자. "모든" 사람들이 내가 만든 웹 서비스를 이용할 때 불편함 없이 이용하는 사이트를 만드는 것이 목표였는데, 쉽게 구현하고자 접근성과는 멀어진 코드가 된 것 같아 아쉬웠다.

결론: 그래서 나는 성장했나?

프로젝트를 진행하며 들었던 두 가지의 말이 있다. 인상깊었던 말들이라 기억해둔 말인데, 1차 프로젝트 회고에 남겨두면 적절할 것 같다.

하나는 멘토님께 들었던 말이다. "현수님, 고민하신 흔적이 너무 많이 보이네요!", "혹시 오시기 전에 다른 데서 배우셨나요? 코드가 전반적으로 깔끔합니다."

다른 하나는 축구를 같이 보는 사람에게 들었던 말이다. "너가 학원에 다니면서 사람이 많이 밝아졌어. 나는 잘 모르는 분야지만 너가 그걸 즐기고 있는 것 같아 보여."

첫번째는 위코드에 온 뒤 멘토분께 처음으로 들었던 칭찬이었고, 두번째는 근 8년만에 듣는 '밝다'라는 평가였다. 그리고 이 두 가지의 말이, 내가 프로젝트를 통해 성장했음을 보여준다고 생각한다.

나는 좋은 코드를 짜고 싶고, 즐기며 코드를 짜고 싶다. 사람들이 나를 보았을 때 그러한 사람으로 봐주었으면 한다. 그러한 개발자가 되어갈 때 나는 성장하는 것이라 믿는다. 두 가지의 말은 내가 되고 싶은 이상향과 정확히 맞닿아 있고, 적어도 내가 옳은 방향으로 가고 있다는 안도감을 심어줬다.

팀원끼리 회고를 공유할 때도 비슷한 내용을 남겼다. "예쁜 프로젝트를 작업하는 것은 언제나 행복한 일이고, 특히 푀세아 팀과 함께 해서 즐거웠다." 이번 프로젝트가 나뿐만 아니라 팀원분들께도, 우리 팀원 뿐 아니라 다른 팀원분들께도 즐거웠던 기억, 성장하는 발판이 되었다면 참 좋겠다.

1개의 댓글

comment-user-thumbnail
2022년 5월 7일

훌륭합니다!

답글 달기