React | '프립' 모티브 프로젝트

연정·2021년 11월 27일
0

Personal Projects

목록 보기
5/6
post-thumbnail

Project Overview

클래스형 컴포넌트와 Sass를 사용했던 1차 프로젝트와 달리, 새롭게 함수형 컴포넌트와 Styled Component를 적용해봤던 2차 프로젝트가 끝났다. 새로운 배움이 언제나 그렇듯 이해하고 익히는 데까지 많은 시간을 필요로 했지만, 결과적으로 이번 프로젝트를 통해 각 방식의 장단점을 몸소 체험하고 상황에 맞는 방식을 선택할 수 있는 힘이 길러졌다고 생각한다.

특히 React-router-dom이 절묘한 타이밍에 버전 6으로 업그레이드 되면서 그 내용까지 습득해야만 했는데, 짧은 프로젝트 기간 내에 소화할 때는 힘들었지만 지금와서 생각해보면 빠르게 변화하는 기술들에 적응해야하는 개발자의 찐 모습을 경험한게 아닌가 싶다.

Project Description

2차 때는 각종 액티비티 및 취미활동에 대한 경험을 구매할 수 있는 '프립' 사이트를 모티브로 프로젝트를 진행하게 되었다. 이번엔 사이트에 대한 전체 컨셉은 유지하되 팀의 색깔을 녹여 사이트의 아이덴티티를 새롭게 기획했다.

액티비티 공유 & 구매 사이트 '프렙'

  • 프렙은 Preparation의 준말로, 내 미래를 위한 준비를 도와주는 사이트 입니다.
  • 다양한 기준에 따라 액티비티를 추천받을 수 있습니다.
  • 액티비티에 대한 후기를 보거나 남길 수 있습니다.
  • 로고 : 개인의 성장을 새싹을 통해 시각적으로 표현하였습니다.

작업기간

2021.11.15 (월) - 2021.11.26 (금) / 총 12일

기술스택

프론트엔트 / 3명

  • HTML / CSS
  • Javascipt (ES6+)
  • React (Function Component)
  • Styled Component

백엔드 / 2명

  • Python
  • Django
  • Bcrypt
  • JWT
  • Postman
  • MySQL

공통

  • Git & GitHub
  • Trello
  • Slack

주요 구현사항

이번에도 내가 직접 구현한 부분은 당근(🥕)으로 표시해두었다.

  • Nav & Header

    • 화면 사이즈에 따라 변화하는 반응형 Nav 구현
    • 카테고리 아이콘 클릭 시 카테고리 메뉴 모달창 활성화
    • Query Parameter를 활용하여 검색 기능 구현
    • token 여부에 따라 로그인 / 로그아웃으로 변화하는 아이콘 구현

  • 소셜 로그인

    • 카카오 API를 활용한 소셜 로그인 기능 구현

  • 메인 페이지

    • Slick slider 라이브러리 활용하여 이미지 슬라이더 구현
    • 특정 기준에 따라 콘텐츠 sort하여 노출
    • Query Parameter 활용하여 리스트 페이지로 연결

  • 리스트 페이지

    • 다양한 filter에 따라 해당하는 콘텐츠를 노출하는 기능 구현
    • 콘텐츠 수량에 따라 pagenation이 다르게 표현되도록 구현

  • 상세 페이지 🥕

    • Path Parameter(useParams)를 활용, 클릭된 상품에 대한 데이터 호출 🥕
    • Slick slider 라이브러리 활용, 상품 상세 이미지 슬라이더 구현 🥕
    • 평균 별점을 색칠된 5개의 별을 통해 시각적으로 표현하는 기능 구현 🥕
    • 사용자가 등록한 리뷰들이 함께 보여지는 슬라이더 구현 🥕
    • 리뷰들에 대한 좋아요 기능 구현 🥕
    • 리뷰 작성 (별점 & 텍스트 & 이미지) 기능 구현 🥕
    • 화면의 특정 시점부터 등장하는 Top 버튼 구현 🥕

  • 전체

    • Git merge가 아닌 Git rebase를 활용하여 깔끔하게 프로젝트 히스토리 관리 🥕
    • Styled Component로 컴포넌트 단위 스타일 관리 🥕

결과

프로젝트 내용 하나하나가 너무 소중해서 전체를 소개하고 싶지만 전체 구현 내용은 영상을 통해 보여주도록 하고, 개인이 작업한 내용을 중심으로 소개한다.

프렙 전체 시연영상 보러가기

[상세페이지 시연영상]

1. Path Parameter(useParams)를 활용, 클릭된 상품에 대한 데이터 호출 🥕

메인 혹은 리스트 페이지에서 상품 클릭 시, '그 상품'이라는 것을 전달하기 위해 해당 상품의 id를 URL에 저장한다. 클래스형 컴포넌트에서는 해당 정보에 this.props.match.params.id로 접근할 수 있었는데, 함수형 컴포넌트에서는 useParams를 통해 보다 간단하게 접근할 수 있다.

생각보다 간단한 개념이었음에도 함수형 컴포넌트에 익숙하지 않아 어떤 메소드를 활용해야하는지부터 많은 고민이 필요했다. react router의 공식 문서를 참고하여 상황에 맞는 적합한 메소드를 찾고 나니 수월하게 해결.

참고 : https://reactrouter.com/docs/en/v6/api#useparams


2. Slick-slider 라이브러리 활용, 상품 상세 이미지 슬라이더 구현 🥕

1차 프로젝트에 이어 또 다른 슬라이더를 구현하게 되었다.
지난 번엔 바닐라 자바스크립트로 복잡한 형태의 슬라이더를 구현해보았으니, 이번엔 라이브러리를 활용해보고 싶었다. 다양한 라이브러리 검색 후 Slick-slider라는 라이브러리를 사용하기로 결정하였는데, 생각보다 라이브러리를 적용하는 것 자체도 많은 공부가 필요했다. 실제로 코드가 보이지 않으니 개발자 도구로 하나하나 찍어보면서 파악하여 결국 원하는 바를 구현할 수 있었다.

바닐라 자바스크립트와 라이브러리, 두 가지의 방식을 통해 슬라이더 기능을 구현하고 나니 명확한 차이점이 느껴졌다. 일반적인 슬라이더를 구현해야 할 때는 라이브러리를 활용하는게 훨씬 빠르고 간편하나, 디자인이 독특하거나 구성이 복잡한 슬라이더를 구현할 때에는 오히려 직접 코드로 구현하는게 훨씬 수월할 것 같았다.


3. 평균 별점을 색칠된 5개의 별을 통해 시각적으로 표현하는 기능 구현 🥕

회색 별 5개 이미지 & 파란색 별 5개 이미지를 겹쳐 놓은 뒤, 평균 별점에 따라 파란색 별의 width값이 달라지며 디테일한 소수점까지 노출되는 별점 기능을 구현하였다. 이 부분은 1차 프로젝트 때 구현한 팀원이 있어 개념을 공유받고 생각보다 수월하게 구현할 수 있었다.


4. 사용자가 등록한 리뷰들이 함께 보여지는 슬라이더 & 좋아요 기능 구현 🥕

리뷰 이미지, 사용자 이미지와 id, 선택한 옵션, 리뷰 텍스트, 좋아요 버튼으로 이루어진 리뷰 슬라이더를 구현하였다. 아래 리뷰 등록 박스에서 사용자가 등록한 리뷰들이 실시간으로 추가되며, 제품에 대한 모든 리뷰를 슬라이더를 통해 한 번에 볼 수 있다.

이 섹션에서 가장 고민을 많이 했던 부분은 좋아요 버튼이었다. 하나의 기능이지만 고려해야하는 부분이 많았기 때문인데, 그 내용은 아래와 같다.

  • 특정 리뷰에 대한 좋아요 버튼을 클릭 시, 서버와의 통신을 통해 좋아요 숫자가 +1되어 저장
  • 동일한 사용자가 같은 리뷰 좋아요 버튼 클릭 시, -1 처리
  • 각각의 리뷰에 대한 좋아요 버튼을 따로 관리하여 누른 버튼만 다시 보여지도록 화면 처리

다행히도 백엔드 동료가 로직을 잘 처리해준 덕분에, token과 함께 클릭된 리뷰의 id값만 서버로 전달해주면 자동으로 이전에 눌렀는지 여부를 판단하여 + 혹은 - 처리가 되게 할 수 있었다. 하지만 문제는 마지막 고려 사항이었는데, 서버에 데이터는 무사히 저장되나 하나의 버튼 클릭 시 모든 버튼이 같은 숫자로 동기화 되는 문제가 발생했다.

이 기능을 구현하며 맞이한 문제와 해결 방식은 이 링크에서 확인할 수 있다.


5. 리뷰 작성 (별점 & 텍스트 & 이미지) 기능 구현 🥕

이번 프로젝트에서 구현한 내용 중 가장 많은 시간을 쏟았으며, 가장 많은 배움을 얻었던 부분은 리뷰 작성 기능 구현 부분이다. 이 섹션에서 구현한 내용은 다음과 같다.

  • input type='radio'map 메소드 활용하여 별점 리뷰 구현
  • textarea 태그를 활용하여 리뷰 텍스트 작성 구간 구현
    (maxLength를 부여하여 최대 리뷰 작성 숫자를 지정)
  • input type='file'label을 활용하여 이미지 업로드 기능 구현
  • 업로드 된 이미지를 미리보거나 삭제할 수 있는 기능 구현
  • 리뷰 submit 후 모든 input 내용 처음으로 되돌리기

그토록 기대했던 백엔드 서버와의 통신 중 끝판왕을 경험한 느낌이었는데, 이 부분 역시 디테일한 공유를 위해 이 링크에서 소개하도록 한다.


6. 화면의 특정 시점부터 등장하는 Top 버튼 구현 🥕

상세페이지 구현 영상을 자세히 보면 우측에 작은 Top 버튼을 구현해놓은 것을 볼 수 있다. 해당 버튼은 useRef를 활용하여 최상단에 ref를 걸고, 클릭 시 해당 섹션으로 이동하도록 구현하였으며 ref.current.scrollIntoView({behavior: smooth})를 활용하였다.

또한 스크롤이 이미 최상단에 위치하였을 때는 굳이 노출될 필요가 없으므로, 적정한 수준으로 스크롤 down이 일어났을 때에 등장하도록 구현하였다. 해당 기능은

  • scroll 값을 state로 관리
  • window.addEventListener으로 scrollY 값이 달라질 때마다 state가 업데이트 되도록
  • 업데이트된 state 값을 positon이라는 변수로 Styled Component의 props로 전달, 그 값이 특정 기준 이상일 때 opacity 값이 0에서 1로 변경되도록 구현

이렇게 구현하였다.


Project Review

2차 프로젝트를 시작하며 팀 전체의 목표와 함께 팀원들 각자의 개인적인 목표를 정했었다. 업무를 분담하면서도 최대한 각자의 목표를 이룰 수 있는 방향으로 나누려고 노력했고, 그 결과 누구 하나 빠짐없이 팀적으로도 개인적으로도 많은 배움이 있었다고 자부한다.

  • 팀 목표 : 최대한 다양한 기능을 경험해보고, 그 기능을 완벽하게 이해하고 구현하자
  • 개인 목표 : 1차 때 제대로 경험하지 못해서 아쉬웠던 백엔드와의 통신을 다양하게 경험하고, 그 process에 대해 이해하자

칭찬 포인트

👍🏻 유난히 이번 프로젝트에서는 서로 보완하는 힘이 엄청났다. 프론트엔드 개발자들끼리는 아는 내용을 서로 공유하여 구현에 필요한 시간을 줄이고, 백엔드 개발자와도 서로의 편의를 최대한으로 고려하여 개발 진행!

👍🏻 각자 세운 목표를 성실하게 달성하고, 팀으로 작업하면서도 개인적인 성장을 놓치지 않았다.

👍🏻 각자의 수준과 속도를 명확하게 파악하여 달성 가능한 목표를 세웠고, 기간 내에 팀원 모두 100% 구현 완료하였다.

👍🏻 실제 사이트처럼 사용자를 충분히 고려하고, 페이지 간 이동에 따라 필요한 내용을 적용하였다.

아쉬운 포인트

🙏🏻 개발 초기에는 스크럼 방법론에 따라 적극적으로 소통하였으나, 후반부로 갈 수록 개인의 일정에 몰두한 탓에 Daily-meeting에 소홀하였다. 지속적으로 팀원 각자와 따로 소통한 덕분에 일정이나 작업 내용에 문제가 생기지는 않았으나, 팀원 모두가 각자의 상황을 공유하는 미팅을 조금 더 꾸준히 챙겨 했어야 했다.

🙏🏻 빠듯한 일정에 추가적으로 구현하고자 했던 내용까지 소화하지 못했던 부분이 아쉽다. 이 부분은 추후에 보완하여 개발할 예정 :)

마무리 회고

이번 프로젝트를 시작하며 1차 프로젝트에서 아쉽다고 생각했던 점들을 보완하는 걸 목표로 삼았었는데, 그 부분을 성공적으로 이룬 프로젝트라 너무너무 만족한다.
그리고 새로운 사람들과 팀을 이루어 작업을 하는건 또 어떨지 기대 반 걱정 반이었는데, 모든 사람이 각자의 강점을 가지고 있기 때문에 팀적으로 그 부분을 잘 살린다면 누구와 진행하든 잘 흘러가는 프로젝트를 만들 수 있겠다는 자신감이 생겼다!

츤데레지만 부탁한 내용을 누구보다 빠르고 정확하게 (심지어는 더 편하게) 해결해주는 민석님,
꼼꼼한 소통과 공유로 문제 없이 흘러갈 수 있게 이끌어주는 용건님,
팀 내의 분위기 메이커이자 가장 빠르게 흡수하고 성장하는 성호님,
가장 열정적으로 공부하고 다른 사람의 문제를 함께 해결하려 노력해주는 보라님,

2주 동안 우리 사랑스런 팀원들과 함께 할 수 있어서 너무 행복한 시간이었다.

profile
성장형 프론트엔드 개발자

0개의 댓글