러쉬 (Lush) 코리아 클론 프로젝트 후기

김지현·2021년 7월 25일
16

프로젝트

목록 보기
1/1
post-thumbnail

👩‍👩‍👧‍👦🏞🕊 사람, 환경, 동물이 조화로운 세상을 함께 만들어요! Lush
러쉬 페이지를 클론 프로젝트를 진행해보았습니다.

Preview

2주간 모든 것을 쏟아부었던 1차 프로젝트가 끝이 났다. 이 시점에서 다시 생각을 돌이켜보니, 팀 프로젝트라는 단어가 주는 막연한 부담감과 막막함이 상당했던 것 같다. 그래서 프로젝트 시작 전날까지 심장이 쿵쿵 거려서 잠도 잘 못 이뤘다. 하지만 일단 해보는 거지! 내가 이 정도도 못할 쏘냐..! 하는 마음 가짐으로 뛰어들었다.

프로젝트 시작 전 주에 각자 하고 싶은 사이트에 대해 의견을 내고, 간단히 발표하는 시간이 있었다. 그리고 동기분들 모두 각자 하고 싶은 사이트 몇 가지를 선정하는 투표를 거쳐 사이트가 선발되었는데, 감사히도 내가 의견을 낸 러쉬 사이트가 선정되어 원하던 사이트를 클론할 수 있게 되었다.


Project Goal

이번 1차 프로젝트의 가장 큰 목표라 함은, 지금껏 배운 리액트 및 노드 개념을 다시금 정리하고, 또 새롭게 배우는 개념들에 대해 공부하는 것이다. 그 목적에 걸맞게 최대한 코드들을 내 것으로 만들기 위해 노력했고, 하나를 하더라도 최선을 다해 좋은 코드로 만들어 보자는 생각을 가지고 최선을 다했다.

그 외에도,

  1. 백엔드와 프론트엔드의 fetch 함수 를 통한 통신
  2. 팀원들과 공통의 폴더 를 공유하며 코드 함께 관리
  3. Trello, github 등의 협업 tool 로 하여금 협업 경험 기르기
  4. 매일 정해진 시간에 StandUp Meeting 을 가지면서 진행 상황 공유

위 네 가지가 이번 프로젝트의 진짜 목적이라고 할 수 있다. 비단 코딩 실력을 업그레이드 시키는 것뿐만 아니라, 정말 협업 이라는 단어에 집중하여 하나의 공동 목표를 위해 모두가 최선을 다하는 경험을 해보았다는 것이 더 값진 결과로 다가왔다.

위는 우리가 작업한 WESH 페이지, 아래는 진짜 LUSH 페이지이다.

소망하다, 간절히 바라다 는 뜻의 WISH 와, 우리 모두가 함께 했다 는 의미의 WE, 그리고 러쉬의 뒷 두 글자 SH를 따서 WESH 라는 이름을 가진 사이트가 탄생했다.
메인 슬라이드에 보이는 WASH, FRESH, WESH! 또한 고심해서 탄생한 문구이다. 최대한 러쉬의 깔끔하면서도 감각적인 디자인을 살리자는 의견 하에 프로젝트가 착착 진행되었고, 결론적으로는 아주 멋지고 깔끔한 디자인을 가진 페이지가 탄생했다.

러쉬 클론 프로젝트 구현 영상 보러가기 🎥


작업 기간

2021/07/05 ~ 2021/07/16

기술 스택

FRONTEND

  • HTML, CSS
  • Javascript (ES6+)
  • React
  • SASS

BACKEND

  • Node.js
  • Mysql
  • Prisma
  • Express
  • JWT
  • Bcrypt

팀원 소개

협업 툴

  • Github, Trello, Google Meet, Zoom, Slack

필수 & 주요 구현 사항

(내가 참여한 기능은 굵은 글씨로 표시되어 있다!)

  • 로그인, 회원 가입 레이아웃 (validation 및 로그인 성공 시 페이지 이동, 회원 비회원 탭 간 이동)
  • 로그인, 회원 가입 api (bcrypt를 이용한 비밀번호 암호화, 로그인 성공 시 access token 발행)
  • 네비게이션 바 레이아웃 (마우스 호버 시 카테고리 및 유저 툴팁 창 띄우기)
  • 푸터 레이아웃 (구독하기 란의 이메일 입력 기능 및 alert창 띄우기)
  • 카테고리 api 제작
  • fetch 받아 화면단에 프론트 엔드 단의 네비게이션 바에 띄우기
  • 네비게이션 바 modal 창 띄우기
  • 메인 페이지 레이아웃 (Slide 버튼 클릭 시 Carousel 동작, ScrollTop 위치값을 이용한 페이지 디자인)
  • 리스트 페이지 레이아웃
  • 상품 리스트 api 제작
  • 상품 리스트 api로부터 데이터 fetch를 통해 리스트 페이지에 띄우기
  • 디테일 페이지 레이아웃 (상품 상세 및 리뷰 작성 페이지)
  • 리스트 & 디테일 간의 동적 라우팅
  • 디테일 페이지에서 상품 개수 카운팅 및 3만원 이상이 될 시, 배송비 무료

프로젝트 구현 결과

✨ 메인 페이지

WESH의 정체성인 메인 페이지!

민기님의 정성과 노력이 그대로 엿보이는 결과물이다. 러쉬의 아이덴티티를 최대한 살리면서, 우리만의 느낌도 잘 녹여내고 싶었는데 그런 우리의 바람이 아주 잘 녹아든 멋드러진 화면이 탄생했다.

✨ 하단 푸터

기존의 러쉬 페이지는 이메일 입력 후 구독하기 버튼을 누르면 마케팅 활용 동의 모달창이 뜨지만, 우리는 alert 창이 뜨도록 구현해보았다.

✨ 상단 모달

네비게이션 바 아이콘 중 검색 아이콘 클릭 시 모달창이 뜨도록 구현해보았다.

✨ 회원가입 기능

유효한 정보 (이전에 가입되어 있지 않은 유저 정보) 입력 시, 회원가입을 축하드립니다 라는 문구가 뜬다.

✨ 로그인 기능

회원가입 시 입력한 정보와 일치하는 정보를 입력하면, 로그인에 성공하셨습니다 라는 문구가 뜬다.

✨ 네비게이션 바

러쉬 페이지처럼 제품러쉬 소개 카테고리에 대한 세부 카테고리들을 띄워서 보여준다.

✨ 리스트 페이지

제품 카테고리 중에서도 카테고리 선택 시 솝에 대한 리스트 페이지로 이동한다.

✨ 디테일 페이지

허니 제스트라는 제품 클릭 시, 해당 디테일 페이지로 이동한다. 수량이 늘어남에 따라 가격이 다르게 책정되고, 3만원 이상 시 무료 배송 금액이 적용된다.


Personal Review

🥲 프로젝트를 진행하며 내가 가장 애를 먹었던 부분은 바로 카테고리를 출력해주는 api를 프론트엔드 코드와 합치는 부분이었다. 프론트엔드, 백엔드 두 가지를 합치는 것이 이렇게 힘든 작업인 줄 몰랐는데 이번 프로젝트를 진행하면서 뼈져리게 느꼈다.

이래서 초반 설계와 회의가 정말 중요하구나! 하는 부분도 다시금 느꼈다.

멘토님들께서도 코드를 짜는 것보다, 코드가 완성된 후에 서로 통신할 때가 가장 힘들고 어렵다고 하셨다. 그 말씀에 백번 공감하는 순간이었다.

위 gif 파일에서 볼 수 있듯, 러쉬 페이지는 카테고리가 크게

  1. 제품, 러쉬 소개, 매장 안내, 스파, 이벤트 -> 5개의 메뉴
  2. 제품 탭 아래의 11개의 카테고리 및 러쉬 소개 탭 아래의 5개의 카테고리
  3. 각 카테고리 아래의 서브 카테고리 (주간 베스트, 별 다섯 개 후기, 배쓰 밤 등)

이러한 구조로 구성되어 있다.

따라서 카테고리에 대한 모델링 당시, 이러한 구조로 연계된 구조로 모델을 짰다.
그에 따라 api 코드 또한 categories 라는 큰 배열 안에 categoryName, categoryId 그리고 각각의 categoryName에 해당하는 subCategories 배열이 담겨서 출력되도록 코드를 짜보았다.

✔ 그런데 이렇게 구조를 짜고 출력되도록 api를 제작하다보니,
프론트 단에서 제품러쉬 소개 카테고리에 마우스 호버 시 각각 다른 서브 카테고리들을 보여줘야 하는데, 분리되지 않고 모든 서브 카테고리가 두 카테고리 모두에 출력되는 현상이 발생했다. 즉, 러쉬 소개 카테고리에 가야할 부분까지 제품 카테고리에 함께 보여지고, 제품 카테고리에만 보여져야할 부분이 러쉬 소개 카테고리에도 함께 출력되고 있었다. 백엔드 단에서 카테고리를 분류해주고 있지 않고, 모든 카테고리를 출력해서 넘겨주니 이런 상황이 발생한 것이다.

많은 api를 만들어보지 않은 상황이라 api에 아직 익숙하지 않은 상태였고, 프론트 코드와 통신을 해본 경험도 많지 않았어서 굉장히 멘붕이 왔었다. 어떻게 개선해야 하지..? 🤔 수도 없이 고민하고 또 고민했다.

멘토님들께도 여러 번 조언을 구하면서 코드를 이리 고쳐보고, 저리 고쳐보고 엄청난 고난이 있었다. 결론적으로는, menu_id를 키워드로 두 카테고리를 분류하기로 결정을 내렸다. 즉 백엔드로부터 데이터를 모두 받아오되, 그 데이터를 예쁘게 가공하여 프론트 단에 분리해서 보여주는 것이다.


📚 우선 백엔드 코드부터 수정했다.


// controller 
const findAllCategoriesAndSubCategories = async (req, res) => {
  try {
    const { menu_id } = req.body;
    const categories = await categoryService.matchCategoriesAndSubCategories(menu_id);
    res.status(200).json({ categories });
  } catch (err) {
    res.status(500).json({ message: err.message });
  }
};
export default { findAllCategoriesAndSubCategories };

// service
const matchCategoriesAndSubCategories = async () => {
  const categories = await categoryDao.findCategories();
  const data = await Promise.all(
    categories.map(async (category) => {
      const subCategories = await categoryDao.findSubCategories(category.id);
      return {
        menuId: category.menu_id,
        categoryId: category.id,
        catagoryName: category.name,
        subCategories: subCategories,
      };
    })
  );
  return data;
};
export default { matchCategoriesAndSubCategories };

// model
const findCategories = async () => {
  return await prisma.$queryRaw(`
    SELECT
      categories.id, categories.name, categories.menu_id
    FROM
      categories
  `);
};
const findSubCategories = async (categoryId) => {
  return await prisma.$queryRaw(`
    SELECT
      sub_categories.id, sub_categories.name
    FROM
      sub_categories
    WHERE
      category_id = '${categoryId}'
  `);
};

export default { findCategories, findSubCategories };

database에 저장된 데이터들을 불러올 때, 각각의 카테고리가 가진 menu_id 를 필수적으로 출력할 수 있도록 코드를 수정했다. 멘토님들께서 적극 도와주시고, 함께 해주셔서 위 코드를 멋지게 완성 할 수 있었다. 🥲

위 코드를 짜는 과정에서 service 단의 코드 중, 비동기 지옥 에 걸려 한참을 헤맸었다. 자바스크립트에서는 비동기 실행이 필수적인데, 이 중요한 비동기 프로세스 를 간과했다가 큰 코 다칠 뻔 했다.

내가 필요한 데이터를 담은 data 변수가 병렬적으로 출력되기 위해서 Promise.all 코드가 필수적이었다. 이전까지는 자꾸만 data 변수에 아무것도 담기지 않고 빈 객체만 자꾸 return 되었다. 도대체 왜 그럴까, 왜 그럴까 답답했는데 해답은 비동기에 있었다. 객체 내에 데이터들을 담기도 전에 return이 실행되니 당연히 빈 객체가 출력될 수 밖에 없었다.

Promise.all 을 붙여주고, 원하는 데로 객체 내에 데이터가 잘 담겨 출력 되었을 때 그 희열을 잊을 수가 없다. 소헌님과 함께 소리를 질렀던 기억이 있다. 덕분에 비동기의 중요성, 자바스크립트에서의 비동기 구조에 대해 다시 한 번 느끼고 공부하는 계기가 되었다. 기억하자. 자바스크립트 - 비동기 = 0...

✨ 코드 수정 결과 아래와 같이 출력되었다!


📚 이제 백엔드 코드를 수정했으니, 프론트 단에서 데이터를 받아오고, 받아온 데이터를 예쁘게 가공하여 화면에 뿌려주는 일만 남았다.

이 과정도 결코 만만치 않았으며, 오랫동안 붙잡고 있었다. 여러 번 조언도 구하고.. 수 없이 많은 자료들을 찾고 콘솔도 대략 500번 쯤 찍어가며 겨우 겨우 완성시켰다. 예쁘게 화면에 잘 출력되었던 그 순간의 희열을 잊을 수가 없다.

1. 제품 카테고리 코드

2. 러쉬 소개 카테고리 코드

✨✨ fetch 받아오는 포트 번호 및 api 주소는 모두 변수화 하여 config.js 파일에 따로 보관해두었다. ✨✨

✔️ 코드에 대한 설명을 덧붙여보자면, 우선 subNav라는 이름으로 데이터 전체를 먼저 받아온다. 이 데이터는 가공되지 않은, 즉 분류되지 않은 데이터이다.

  • 이제 이 데이터들을 제품 에 들어가야 할 것들은 제품으로, 러쉬 소개 에 들어가야 할 것들은 러쉬 소개 쪽으로 보여지게 하기 위해 컴포넌트 명부터 LushProducts, LushIntro 라고 붙였다.

  • 가공되지 않은 데이터를 모두 받아온 뒤, menuId 에 따라 분류했다.
    menuId 가 1인 것들은 제품 탭 아래의 카테고리 및 서브 카테고리들이고, menuId 가 2인 것들은 러쉬 소개 탭 아래의 카테고리 및 서브 카테고리들이다.

  • menuId 로 분류된 각각의 데이터들을 미리 만들어둔 constructor 함수 내의 빈 배열에 담고, 해당 배열을 다시 변수에 담아 그 변수를 setState 에 다시 저장해주었다. 즉, setState를 두 번 사용해준 것이다.

이 과정에서 함수를 분리해주었다. 각각의 코드가 어떤 역할을 하는 지 확실히 알 수 있도록 getCategoryDatamanufactureCategory 라는 이름을 붙여주었다.

✔️ 이렇게 해서 가공되지 않은 데이터 -> 아이디 값에 따라 가공된 데이터 로 변환시킨 뒤 화면에도 깔끔하게 분류된 카테고리들을 보여줄 수 있게 된 것이다.


이 일련의 과정을 완성하는 데 정말 많은 시간을 쏟았다. 눈물이 찔끔 날 뻔도 했다. 어렵지 않게 생각했던 카테고리 api, 그리고 네비게이션 바가 내 예상보다 훨씬 어려워서 멘붕의 연속이었다. 하지만 끝까지 포기하지 않았다. 수 많은 리뷰를 받으면서 코드를 고치고 고치고 또 고치면서 많이 발전하고, 또 내 생각에도 큰 변화가 있었던 것 같다.

코드 리팩토링 과정이 생각 리팩토링 과정과도 같았다.

가독성 낮고, 다소 지저분하던 코드에서 점점 깔끔한 코드로 변모해가는 과정에서 희열감은 물론이고, 클린 코드의 중요성에 대해서도 뼈저리게 느낄 수 있었다. 내 코드가 어떤 역할을 하는 코드인지 전혀 모르는 사람이라고 할 지라도, 코드를 보았을 때 그 짜임새와 역할에 대해 파악할 수 있도록 하는 것. 이 부분을 항상 유념해야 할 것 같다.

실제로 나 또한 리팩토링 전과 후 코드를 비교하면, 전의 코드는 하나 하나 뜯어보고 곱씹어야 겨우 맥락을 이해할 수 있었다면 이후의 코드는 훨씬 가독성이 좋아지고, 함수명과 변수명으로 하여금 조금이나마 명확성이 생긴 것 같았다.


🧐 방심은 금물!

물론 그렇다고 해서 현재의 코드에 만족하느냐?
그것은 절대 아니다. 아직도 부족함이 많이 보이고, 더 개선해나가야 할 점이 많다고 생각한다.

1. setState를 두 번 사용한 점
2. 결국 같은 역할을 하는 코드가 각 컴포넌트에서 반복되고 있는 점
3. 백엔드 단에서 분리를 먼저 해주었다면 프론트 단 코드가 좀 더 간결해질 수 있지 않을까?

이 세 가지 찜찜함을 가지고 있다. 이 찜찜함이 나쁘다고 생각하지 않는다. 오히려 긍정적으로 작용할 것 같다. 조금씩 찜찜함을 쾌감으로 바꾸면서 보완해나가면 되니까!


스스로 칭찬하기

이번 프로젝트를 진행하며 스스로 칭찬해주고 싶은 부분도 분명히 있다.

우선 팀원들과 좋은 분위기로 프로젝트가 진행될 수 있도록 지속적으로 팀원들을 독려했다. 팀 분위기가 좋아야 팀 프로젝트도 원활히 진행될 수 있다는 생각이 컸기 때문에 모두들 지쳐서 다소 쳐져 있을 때나, 혹은 컨디션 환기가 필요할 때 팀원들과 함께 다시 활기를 되찾을 수 있도록 적극 노력했다.

더불어, 팀원들과 최대한 많이 소통하려고 노력했다. 시시때때로 팀 채널에서 팀원들과 많은 대화를 나누고 문제 상황 혹은 업데이트 상황에 대해 바로 바로 팀원들에게 알려서 소통의 부재로 인한 문제가 생기지 최대한 생기지 않도록 노력했다. 그래서 우리 팀은 정말 많은 미팅 시간을 가졌던 것 같다! 💪


Project Review

1차 프로젝트를 마치면서 가장 크게 든 생각은, 뿌듯하지만 아쉽다 였다.
초반의 기대에 부풀었던 기획과는 다르게 조금씩 줄여나간 기능들이 있었고, 시간에 쫓겨 결국 구현하지 못한 기능들도 있었기 때문이다. 특히나 커머스 사이트의 cycle 중 하나인 장바구니 기능 을 구현하지 못한 부분에 대한 아쉬움이 아직도 크다.

하지만 어떤 작업을 진행 할 때 가장 중요하게 여겨야 할 부분은 바로 데드라인이다. 따라서 팀원들과 그 데드라인 을 생각하면서 현재의 상황에 충실하자! 라는 생각으로 다 같이 으쌰으쌰 열심히 했던 것 같다. 비록 구현을 못한 부분에 대한 아쉬움도, 부족함도 남아있지만 그 부분들은 2차 프로젝트 때 더 열심히 공부해서 보완하면 된다.

개인적으로 1차 프로젝트를 회고해보면서, 한 가지 얻어가는 부분은 확실히 있다고 느낀다. 협업 이라는 것은 생각보다 쉽지 않았다. 각자의 진행 속도, 생각, 성격 모두가 다르기 때문에 협조적인 태도로 모두의 말에 귀 기울이는 것이 중요하다는 것을 다시금 느낄 수 있었다.

4명이라는 적은 인원이지만, 모두 다른 배경과 다른 환경 속에 자라 온 4명이다.
즉, 어떻게 보면 부딪히는 것은 당연하다. 매일 매일 얼굴을 마주하는 가족도 싸우는데, 어떻게 팀원들끼리 매번 화목하기만 할까? (그렇다고 우리 팀이 싸웠다는 것은 아니다)

물론, 우리 팀은 단 한 번도 싸우지 않았다. 서로를 존중하고 독려했다. 매일 정해진 시간에 진행하는 스탠드 업 미팅 이외에도 시간이 날 때마다 회의를 진행하며 혹시라도 한 팀원이 막힌 부분이 있으면 그 부분을 해결하기 위해 팀원 모두가 노력했다. 낮, 밤을 가리지 않고 본인의 상황을 공유했다. 이따금씩 지칠 때면 농담도 던지면서 나름 화기애애하게 팀 프로젝트가 진행 되었던 것 같다. 이런 면에서 다른 건 몰라도, project goal 중 3번 4번은 정말 잘 지켰다고 자부할 수 있다.

개인적으로 나 자신을 돌아볼 때, 난 성격이 매우 조급한 편이다. 어떤 큰 일을 앞두고 있을 때 그 조급한 성격이 더 심해진다. 마음의 평정심을 찾는 게 나에겐 가장 큰 숙제이다. 수시 면접 보던 날, 수능 치던 날, 대학교 첫 발표 날, 논문 발표 날, 취준 시절 첫 면접을 보러가던 날 등등.. 괴로워했던 그 모든 기억이 스쳐지나간다. 타고난 성격이 그런 건지.. 멘탈 관리가 나에겐 가장 힘든 부분 중 하나다. 그래서 평정심을 가지고 스스로를 잘 다스리는 사람을 보면 너무 부럽다.

이번 프로젝트를 진행하면서 나의 조급한 마음이 또 나왔던 것 같다. 이러한 부분이 혹여 팀원들께 안 좋은 영향을 끼쳤으면 어떡하나 싶기도 했다.

우리 팀원분들은 항상 나에게 좋은 말만 해주셨다. 😁 그 덕에 마음의 안정을 조금이라도 찾은 것 같기도...


마음가짐

1차 프로젝트 발표가 끝나고 다 같이 회식하던 때가 엊그제 같은데, 현재 2차 프로젝트를 앞두고 있다. 솔직히 말하면 두려운 마음은 가시지가 않는다. 내 몫을 멋지게, 아니 그 이상을 해내고 싶은데 그렇게 될 수 있을 지에 대한 의문점, 그리고 두려움이 엄청나게 몰려오는 밤이다. 하지만, 팀원들과 서로 격려하며 헤쳐나가면 될 것이라 굳게 믿는다!

나 뿐만 아니라 모두가 2차 프로젝트를 맞이하며 부담감이 클텐데, 멋드러지게 해내버릴고 또 다 같이 맛있는 거 먹으면서 회식하는 날이 올거다 !!! 다가올 행복한 미래를 그리며 회고록은 이만 마치려 한다.

최강 Rush & Lush 팀! 💪 감사했습니다

profile
나만의 세상을 개척하고 싶은 사람

5개의 댓글

comment-user-thumbnail
2021년 7월 26일

지현님 회고록 넘 멋집니다. 짧다면 짧았고, 길다면 길었을 1차 프로젝트 진행하시는라 진짜 넘 수고 많으셨어요. 배포까지 단 한순간도 쉽지 않았지만, 단 한순간도 멋있지 않았던 순간이 없던 지현님의 프로젝트를 응원합니다 정말 !!

1개의 답글
comment-user-thumbnail
2021년 7월 26일

엄청난 회고록이군요. 2달만에 이렇게 성장할수있다니 신기합니다! 2차도 같이 힘내서 잘해봐요!

1개의 답글
comment-user-thumbnail
2021년 7월 28일

👍👍👍

답글 달기