[React, TypeScript, Firebase] 장소 리뷰 웹사이트 만들기

소고기는레어·2022년 4월 8일
2

Project 🗂

목록 보기
9/15
post-thumbnail

Place Review

Place Review
Place Review Github Repository

React, Redux, TypeScript, Firebase 그리고 Kakao map 을 사용하여 장소에 대한 리뷰를 남길 수 있는 웹사이트를 만들어 보았다.

이름은 Place Review로 지었는데, 개인 프로젝트를 진행하는데 있어서 사이트 이름 짓는데 큰 시간을 할애하지는 않기 때문에 그냥 직관적으로 작명하였다.






프로젝트 목적

프로젝트 시작 계기는 내가 지금까지 공부한 내용들을 최대한 활용해보기 위함이다. 간단한 프로젝트들을 진행하며 하나 하나 쌓아온 라이브러리나 api에 대한 경험들을 최대한 한군데 모아보고 싶었다.






구현한 기능

1. 툴바

위치 검색 기능

  • 장소 및 주소에 대한 검색 기능이다.
  • 원하는 검색 결과를 클릭하면 지도와 마커가 해당 위치로 이동한다.
  • 현위치 정보가 있을 경우 현위치 주변으로 우선 검색한다.
  • 검색 결과가 15건을 초과할 경우 다음 페이지로 출력된다.

현위치 이동

  • geolocation 을 통해 현위치로 지도를 이동시키고 해당 위치에 대한 검색을 자동 실시한다.

리뷰 검색

  • 다른 사용자들이 작성한 리뷰를 확인할 수 있다.
  • 두 가지의 필터(전체 리뷰 / 해당 위치 리뷰)를 통해 리뷰를 확인할 수 있다.
  • 주소나 제목, 내용 등을 통해 리뷰를 검색할 수 있다.
  • 리뷰를 클릭하면 지도가 리뷰 위치로 이동한다.

리뷰 작성

  • 리뷰의 제목은 선택한 장소 검색 결과의 가게 이름으로 자동 변경된다. 필요에 따라서 직접 입력할 수도 있다.
  • 1점 단위 최대 5점의 별점을 입력할 수 있다.
  • 사진의 업로드가 가능하다. (최대 1장)
  • 120자 내의 간단한 내용을 작성할 수 있다.
  • 제목과 내용의 글자 수는 자동으로 카운트되어 사용자가 실시간으로 확인할 수 있다.

리뷰 삭제

  • 작성자가 본인일 경우 리뷰에 삭제 버튼이 추가된다.
  • 리뷰를 삭제할 경우 데이터베이스에서 해당 리뷰의 데이터를 삭제한다.
  • 첨부사진이 존재할 경우 스토리지에서 사진을 찾아서 삭제한다.

리뷰 수정

  • 작성자가 본인일 경우 리뷰에 수정 버튼이 추가된다.
  • 리뷰가 수정되면 데이터베이스에 수정 내용을 반영한다.
  • 첨부 사진이 변경되거나 삭제되면 기존의 사진을 스토리지에서 삭제한다.

2. 지도

현재 주소

  • 현위치 기능을 사용할 경우 현재 내가 있는 위치의 주소가 지도 상단에 출력된다.

중앙 크로스헤어

  • 지도의 드래그가 시작되면 지도 중앙에 십자 표시가 출력되어 마커가 찍힐 위치를 알려준다. 십자 표시는 HTML과 CSS로 구현하였다.

자동 검색

  • 지도의 드래그가 종료되면 자동으로 해당 위치에 대한 검색을 실시한다.

마커 인포윈도우

  • 마커에 마우스를 올리면 해당 마커의 주소가 인포윈도우로 출력된다.

3.프로필

닉네임

  • 초기 닉네임은 "익명" 이며 사용자가 임의로 변경이 가능하다.

비밀번호 재설정

  • 입력한 메일이 로그인에 사용하는 메일과 동일할 경우 메일이 발송된다.
  • 메일로 발송된 링크를 통해 비밀번호를 재설정한다.

내 작성 글

  • 프로필 페이지에서 내가 작성한 리뷰들을 확인할 수 있도록 했다.





스타일 및 레이아웃

1. 사용 색상

사용한 색상은 다음과 같다.


2. 로고 & 기타 이미지

로고는 일러스트레이터로 직접 제작하였다.
"Place" 부분의 텍스트 색상이 밝은 배경에서는 잘 보이지 않아서 어두운 배경 버전과 배경 없는 버전 두 가지를 만들어 상황에 맞게 사용하였다.

어두운 배경 버전 로고


투명 배경 버전 로고


마커

지도에 사용된 마커도 직접 제작하여 사용하였다.


파비콘

위 마커를 ico로 변환 후 파비콘으로 사용했다.


3. 로그인 페이지

로그인 페이지는 로고와 로그인 폼, 버튼 그룹, 푸터로 구성되어 있다.

로그인 페이지는 구성 요소가 많지 않아서 심플한 레이아웃을 유지하고자 노력했다.


4. 메인 페이지

넓은 width

사용자가 지도를 보는데서 답답함을 느끼지 않도록 레이아웃에서 가장 큰 부분을 지도에 할당하고 지도를 기준으로 좌측에 주요 기능(툴바)를 삽입하였다.

툴바는 크게 두 가지 기능으로 구분할 수 있는데, 상단에는 장소 검색 기능, 하단에는 리뷰 검색 및 작성 기능을 넣었다.

또한 툴바의 모든 기능과 지도를 최대한 한 화면에 담을 수 있도록 검색 결과는 웹 전체가 아닌 각각의 스크롤을 통해 둘러볼 수 있도록 만들었다.

푸터는 툴바 내부에 배치하였다. 푸터를 지도와 툴바의 형제 요소로 삽입할 경우 불필요하게 너무 많은 공간을 차지하기 때문이다.


좁은 width

좁은 width 환경에서는 지도의 크기를 대폭 줄였다.

콘텐츠의 가독성을 위해 전체적인 레이아웃을 세로로 정렬했는데, 이 때 기존의 지도가 차지하는 크기 비율을 유지할 경우 지도와 툴바를 한 화면에 최대한 출력하고 제어하기가 힘들어지기 때문이다.


5. 프로필 페이지

프로필 페이지는 상단에 프로필 수정, 하단에 내가 쓴 리뷰 목록을 배치하였다.

로그인 페이지와 마찬가지로 큰 특이사항은 없다.






사용한 API와 라이브러리

1. React, TypeScript

React, TypeScript로 구현한 프로젝트이다.


2. Redux

유저 데이터, 지도 데이터, 리뷰 데이터처럼 전역으로 사용되는 상태만 Redux로 관리 하였고 그 외 상태들은 컴포넌트간 상속을 통해 주고받을 수 있도록 관리하였다.


3. 카카오맵

Map

지도를 화면에 출력하고 컨트롤, 마커 등 지도 제어에 대한 전반적인 기능을 지원한다.

new window.kakao.maps.Map(element, options);

지도를 삽입할 HTML 요소와 옵션을 인자로 전달한다. 옵션으로는 지도 시작 위치와 확대 비율 등을 전달할 수 있다. React 환경에서 개발했기 때문에 요소는 레퍼런스로 전달하였다.

Redux Thunk를 통해 불러오도록 하였다.

Places

장소명 혹은 주소를 통한 검색 기능을 지원한다.

places.keywordSearch(검색어, 콜백, [옵션]);

검색어와 콜백 함수를 메소드로 전달하여 검색을 실행한다.

콜백함수의 인자는 검색 결과, 상태(status), 페이지네이션으로 이루어진다. 상태에 따라 검색 결과를 처리하고 검색 결과가 많을 경우 페이지네이션을 통해 페이지를 설정할 수 있다.

추가로 다양한 옵션을 지정할 수 있는데, 그 중 location 옵션에 현위치 정보를 전달하여 위치 정보 액세스 허용일 경우 현위치 근처 우선으로 검색 결과를 출력하도록 하였다.

검색 결과의 타입은 배열이며, 각각의 검색 결과가 배열 내부에 객체로 저장된다.

[{
  address_name: "서울 중구 태평로1가 31"
  category_group_code: "PO3"
  category_group_name: "공공기관"
  category_name: "사회,공공기관 > 지방행정기관 > 시청 > 특별시청"
  distance: "9716"
  id: "8430129"
  phone: "02-120"
  place_name: "서울특별시청"
  place_url: "http://place.map.kakao.com/8430129"
  road_address_name: "서울 중구 세종대로 110"
  x: "126.978652258823"
  y: "37.56682420267543"
}]

Geocoder

좌표 데이터를 주소로 변환하는 기능을 지원한다.

현위치 좌표 및 지도 중심 위치(마커 위치)의 좌표를 주소로 변환하여 검색하는 기능 구현에 사용하였다.


4. Firebase

로그인, 회원가입, 비밀번호 재설정, 닉네임 설정, 리뷰 데이터 및 사진 저장 등의 백단 기능을 구현하였다.

이전 프로젝트에서 사용한 것과 기능 자체는 비슷하지만 이번에 사용한 최신버전은 구버전과 코드가 많은 부분이 달라져서 공식 문서를 꼼꼼히 다시 읽어봐야 했다.

또한 이전 웹사이트는 SNS라는 특성상 프로필 사진 기능이 거의 필수적이었으나 이번 웹사이트는 리뷰의 공유가 주목적이기 때문에 굳이 불필요한 기능이라 생각되어 추가하지 않았다.


5. geolocation

geolocationgetCurrentPosition() 메소드를 통해 사용자 위치 정보에 액세스를 요청하고 활용하도록 하였다.


6. 기타

classnames

sass(scss)

uuid

gh-pages






후기

프로젝트 초반에는 카카오맵 공식 문서에 나와있는 바닐라 JS 코드를 React & Redux 환경에서 구현하기 위해 고민을 많이 했다. 또 Firebase의 공식 문서도 계속 들락날락 거렸는데, 이번에는 이전 프로젝트와 달리 최신 버전의 Firebase를 사용했기 때문이다.

이와 관련하여 프로젝트를 진행 중 가장 힘들었던 부분은 컴포넌트나 Redux의 기능 분리에 관한 부분이었다. 처음 다뤄보는 내용이 많다보니 잘 정리되지 않고 다 따로노는 듯한 느낌을 많이 받았다.

그래서 스타일 작업을 마치고 프로젝트 마무리 단계에 꽤 많은 시간을 코드를 다듬는데 사용하였다. 코드를 다듬으며 기능을 개선하고 추가하다 보니 마무리 단계라고 생각한 부분이 제일 오래 걸렸다.

물론 마무리로 투자한 시간에 비해 깔끔하게 다듬어지지는 않았지만 코드를 다듬는데 쓴 많은 시간 동안 직접 작성한 코드를 여러차례 곱씹어 볼 수 있는 시간이었기 때문에 개인적으로 매우 알차게 보냈다고 생각한다.

profile
https://www.rarebeef.co.kr/

0개의 댓글