전 과정 중 2차 프로젝트가 끝이 났습니다!! 룰루 ˞♡ฅ(ᐤ꒳ᐤฅ) ‹3
이번 프로젝트에서 저는 [ 프론트 개발, 팀장 ]을 맡았습니다.
이번 프로젝트가 1차보다 조금 더 길어서 그런지 조금,,,,,,,더,,,,,,,,,,,기가 빨린 느낌,,,,,,,,,,,,,,,,,,
그래도 디벨롭하는 현재까지도 잘 진행이 되고 있어 마무리가 괜찮은 것 같습니다.
발표할 때 웹 배포가 제대로 안되가지고,,,,얼마나 좌절했는지,, 다들 양해해 주셔서 감사해요

예 제가 이번 플젝에서 난생 처음 프론트를 하면서 3만에 육박하는 코드를 작성하였어요.
저도 제 컨트리뷰터 보고 감작 놀랬어요 ㅎ..................
진짜 폭풍 코딩 하느라 바빠서 팀원들을 제대로 못챙긴것같아 미안합니다..................
역시 프론트는 빡세
서론은 그만하고
저희 웹사이트를 만들면서, 제가 도전했던 것에 대해 적어보도록 하겠습니다.
1. 웹사이트 간단 설명
저희는 [ Wait Mate ]라는 웨이팅 구인 구직 플랫폼을 만들었습니다.
그래서 돈을 지불하고 웨이팅을 부탁할 사람(별칭: 웨이트메이트)과,
돈을 받고 웨이팅을 해줄 사람(별칭: 프록시)을 구하는 플랫폼을 기획하고 만들었습니다.

2. 디자인적 요소
정말 정말 고민을 많이 했는데, 귀여운 캐릭터와 어울리는 웹페이지 테마를 만들고
둥글둥글한 요소를 많이 넣었어요. 색감 팔레트도 최종 발탁된 보라색과 함께 넣었습니다.

그리고 제일 고민하던 메인페이지는 크몽에 맡기고, 그 해당하는 메인페이지 느낌을 살려서
나머지 페이지 디자인을 하였습니다.
그리고, 디자인 및 기획 소통은 figma로 진행하였습니다!!!
난생처음 해보는 figma였는데, ppt와 포토샵의 중간 같아서 재밌었어요

3. 프론트에 사용한 기술 스택

- 리액트 (React)
저희가 수업시간에 배웠던 리액트를 활용하였습니다.

- 테일윈드 (tailwind)
파일을 따로 만들지 않고, 트렌디하며 저희처럼 간소한 페이지에 제격인 테일윈드를 사용하였습니다.

- Scss
테일윈드로 보완되지 않는 css를 위해 보조 개념으로 Scss를 사용하였습니다.
- JavaScript
저희가 수업시간에 이틀에 걸쳐 TypeScript를 배웠으나, 부족하며 단기간 완성해야 하는 프로젝트에는
빠른 코딩이 불가하다고 판단하에 협의하여 TypeScript를 도입하지 않기로 하였습니다.
4. 내가 도전한 것들
4-1. 반응형에 대한 고민
일단 첫 프론트 도전인 만큼, 반응형에 대해 고민이 많았습니다.
다들 반응형 뒤늦게 하려고 하면 너무 힘들다고 해서 처음부터 반응형을 많이 고려하고 싶었기 때문이죠.
일단 저희 웹 사이트는 헤더와 사이드바로 구성되어 있었습니다.

이렇게 구성하다 보니 세로로 긴 모바일에서는
많은 부분이 가려지고, 옆 방향 스크롤이 생기고, 튕겨 나와서 보이지 않으며
무엇보다 사용감이 좋지 않아 고민을 한 결과,
웹 사이즈에서 보이는 사이드바와 모바일에서 보이는 사이드바 컴포넌트를 따로 작성하기로 하였습니다.

저희 웹사이트는 헤더와 사이드바, 풋터가 반복되고, 이를 제외한 나머지 영역의 컴포넌트만 바뀌면 되기 때문에
Templete이라는 파일이 있어, 그 안에 컴포넌트를 넣어서 보여주는 방식이었습니다.

여기서 사이드 바를 보여줄 때 Mobile크기라면 (700px 이하라면)
MobileSidebar 컴포넌트가 보이고, 웹 크기라면 (700px 이상이라면) 그냥 Sidebar 컴포넌트가 보이게 되는 것이죠.
이렇게 왼쪽에 구성되어 있던 사이드바를 모바일에선 위로 올려, 모바일에서도 예쁜 모양을 유지할 수 있었습니다.
그리고, 이 사이드바뿐만 아니라 다른 페이지 들도 반응형을 위해 노력했습니다.
반응형에 대처하는 방법은 여러 가지가 있지만,
저는 컴포넌트마다 700px이하 이었는지 아닌지 상태를 관리하는 변수를 넣어서 실시간으로 감지하도록 하였습니다.

그리하여, 아래에선 이 변수를 삼항연산자로 이용해 flex 방향을 바꾸기도 하고, Text 크기도 바꾸기도 하였습니다.

이렇게 삼항연산자로 사용하니, 테일윈드의 장점도 부각되고 단점도 부각되어
다음에는 조금 더 가독성이 좋은 방법을 물색하는 것이 목표입니다.
4-2. KAKAO 우편번호 API 사용
저희 사이트는 유저가 웨이팅 장소를 등록하고, 이 장소를 map에 띄워주는 서비스가 있습니다.
한국 지리에도 잘 맞고, 유저가 등록한 우편번호를 좌표로 변경하여 map에 띄워줄 수 있다는 점에서
KAKAO API를 적극 활용하기로 하였습니다.

이 우편번호 API를 이용해서 주소 검색을 띄우는 것은 어렵지 않았으나
여기서 사용자가 검색을 완료해서 적용하는 부분이 어려웠습니다.
그러니까, 사용자가 주소 검색을 완료한 후에 저 form의 주소 필드에 그 값을 넣는 것이 어려웠습니다.
그 값이 form의 input 태그에 열심히 넣어줘도 정작 form 내 data에는 그 input값이 먹지 않았습니다.
결국 우편주소의 api와 react-hook-form의 Controller가 컴플릭트가 난다고 판단하고,
모달을 띄우는 컴포넌트를 따로 분리하여 해결하였습니다.

원인을 아주 정확히 찾지는 못하겠으나, 놀랍게도 컴포넌트를 분리하여 처리 과정을 따로 만들고
세터 함수를 프롭으로 넘겨주어 세팅하니 잘 작동이 되었습니다.
그리고 이 address 정보를 map에 띄우기 위하여 좌표를 가져와야 했는데요,
안타깝게 이 우편주소 API으 기본 기능에 해당 주소의 좌표는 없었습니다....
그래서 인터넷을 뒤졌지만, 생각보다 자료가 없고 찾아도 잘 먹히지 않아서 공식문서를 샅샅이 뒤졌습니다.

일단 config를 통해 headers에 인증키와 Content-Type을 공식 문서에 나와있는 대로 넣었습니다.
참고로 여기서 이 apiKey는 KAKAO DEVELOPER에서 발급받은 제 REST API KEY입니다.
(다른 키 아니고 무조건 REST API KEY)이어야 합니다...... 다시 말합니다 무조건 REST API KEY)
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
그리하여 이 url을 세팅하여 axios 요청을 날리면 result에 데이터를 받아서
카카오 공식문서에 있는 대로 result.data.documents[0]에 각각의 x와 y 좌표가 있습니다.
그리하여 x와 y변수에 해당하는 좌표값을 넣어주었습니다.
생각보다 간단하면서 시간도 많이 들였고, 공식 문서의 위대함을 알 수 있었던 부분이었습니다.
(워낙 바닥이라 성장할 일 밖에 없지만 성장한 듯,,,)
4-3. 사용자 경험을 위한 쿠키 사용
저는 사실 지난번에는 백을 담당했었기 때문에, 프론트의 기본인 쿠키와 세션 사용을 몰라서
언젠가는 해야겠는데, 사용자 입장에서 쿠키가 필요하면서 보안에 노출되어도 걱정 없는 파트가 무엇일까
생각을 했었습니다.
저희 웹사이트는 지역기반인 경우가 많습니다.
뭐 예를 들어, 웨이팅 장소뿐만 아니라 웨이팅을 대신해줄 사람(프록시)를 찾는 것도
다 시군구 단위의 지역을 기반으로 찾을 수 있습니다.

그런데 여기서 만약 저 list 중 하나를 눌러 detail 페이지에 갔다가 다시 list로 나오게 된다면
검색했던 지역이 사라지고 다시 전체 리스트가 뜨게 됩니다.
사용자의 입장에서 분명 검색했던 리스트 그대로 보고 싶을 텐데 저조차도 매우 불편하더라고요.
그래서 지역 검색 기록을 쿠키로 사용하게 되었습니다.
물론 쿠키를 도입하기 전에 세션과 쿠키를 고민하였습니다.
일단 사용자가 창을 닫으면 사라진다는 점에서 세션을 사용해야 할 것 같았는데,
저는 작은 메모리지만, 서버와의 연결도 서버의 메모리 사용도 원하지 않고
그저 클라이언트 쪽에서 가볍게 사용하기를 원했습니다.
그래서 쿠키를 도입하기로 합니다.
일단 react-cookie npm을 사용하였습니다.

말씀드렸듯이, 매우 가벼운 쿠키 사용을 원하여, set과 get만 해주었습니다.

select 박스의 default value로 cookies의 address의 value의 값이 있다면 찾아서 넣고,
애초에 cookies.address 내에 값이 없다면, cookie 내에 value가 없어서 에러가 뜨기 때문에
find 함수를 사용하였습니다.
그리고 cities의 리스트 내에서 만약 선택을 해서 onChange를 한다면 선택한 옵션에 따라
setCookies를 통해 address 쿠키 항목에 선택한 address의 value값을 넣어주고 600초 간 유지하도록 했습니다.
maxAge 같은 경우 조금 고민을 했지만, 일단 저희의 원활한 테스트를 위해서 600초로 제한하였습니다.
만약 진짜로 시중에 배포를 하게 된다면 이 maxAge를 적절한 시간으로 유저 데이터를 통해
제한할 것 같습니다.
4-4. react-select npm 사용
저는 사용자의 지역 기반 list를 구성할 때 어떻게 하면
사용자에게 시군구를 편리하게 제공할지 고민하였습니다.
앞서 사용한 KAKAO 우편번호 API를 사용하여 유저가 입력하게 할 수 있지만,
웨이팅을 부탁할 프록시를 찾는 것도, 내가 앞으로 웨이팅을 할 리스트를 찾는 일도
'시군구 단위'를 통해 선택하여 지정하는 것이 편리하다고 생각하였습니다.
그래서 select 박스를 선택하였고 list가 있는 페이지는 cities를 props로 넘겨
사용하였습니다.

하나 초장기 react 내 날 것의 select box는 사용자가 지역을 검색할 수 없었습니다.
구글링 하며 검색한 결과, react에 select box를 위한 npm이 있다는 것을 알게 되었고,
무엇보다 유저가 select box 내에서 지역을 직접 검색이 가능하다는 편리성을 위해 적용하였습니다.

앞서 쿠키를 보여드리며 설명드렸던 그 코드가 react select npm을 도입한 모습입니다.

이 select npm을 도입하는 것은 어렵지 않았지만, 의외로 작업이 좀 오래 걸렸던 것은
전국의 시군구 list가 있는 cities를 전면 개조하는 것이었습니다.
본래, select npm을 도입하기 전에는 label로 '시'와 '도'를 표현하고 그 아래에 군구 단위를
선택할 수 있도록 하였으나 select npm은 오로지 label과 value를 일대일 data 매칭으로 이루어져
있어서 저 cities를 싹 다 갈아엎는 작업이 오래 걸렸습니다.
4-5. react-hook-form npm 사용
저희는 웨이팅을 기다리고 돈을 버는 입장(프록시)이든,
웨이팅을 돈을 내고 부탁하는 입장(웨이트메이트)이든,
사용자가 정보를 등록해야 하는 구조를 가지고 있습니다.
하여 수업시간에도 배웠던 react-hook-form을 적극 사용하기로 하였습니다.
특히 wait mate의 register의 경우, 사용자에게 받는 정보가 워낙 많기에
이 npm을 도입하지 않을 이유가 없었습니다.

이 react-hook-form을 통해 많은 옵션도 걸어주고, 유효성 검사와 그 결과에 따른
메시지도 다르게 보여줄 수 있었습니다.
여기서 register를 클릭하지 않아도 무조건 경고문이 뜨는 것을 방지하여
폼의 규칙을 반하여 register 버튼을 눌렀을 경우에만 해당하는 경고문들을 띄우도록
clickReigster라는 옵션을 넣음으로써 무조건 유저가 폼의 순서대로 입력하지 않아도
경고문이 뜨지 않도록 하였습니다!
(만약 title을 작성하지 않고 다른 항목으로 넘어갈 경우, title을 입력하라고 경고문이 나오게 되고
이는 유저의 반감을 살 수 있다고 판단하였습니다. register를 하려고 할 때 고쳐야 할 경우 나와야 하는 것이
UX 상 더욱 좋아 보였습니다)
5. 트러블 슈팅
협업 과정에서 트러블 슈팅도 있었지만, 개인적으로 고군분투했던 트러블 슈팅 위주로 적어보겠습니다.
5-1. 배열에서 함수 사용 시 배열이 있는지부터 체크해볼것
list 페이지 작업하면서 내 나름 트러블이 있었던 구간은
slice 함수가 적용되지 않는다는 빨간 에러가 뜨는 것이었다.

이게 저를 많이 많이 괴롭혔었는데, 아니 대체 잘 설정된 배열 타입에 slice라는 properies가 되지 않는다고
외치느냐 말이야ㅠㅠㅠ 하면서 옵셔널 체이닝도 적용해보고 배열타입이라고 지정도 해줬는데
해결이 되지 않았다...
=> 해결 방법은, server에서 데이터를 넘겨서 배열에 set해줄 때, 정확한 데이터로 set을 해줘야한다는 것이었다.

여기서 오타가 나거나 구조분해로 가져오지 않는다면,
set 함수로 값을 지정해줄 때 제대로 된 배열이 먹히지 않으니 type도 바뀌어버려서
배열 관련된 메서드가 먹지 않는 것 같다.
5-2. 폼 데이터 유효성 검사
아직 해결을 제대로 못한 트러블 슈팅이긴한데, 너무 충격적이라 남겨본다...ㅋㅋ
마찬가지로 type 어쩌고가 절 많이 괴롭혔는데 (이래서 typescript 사용하나봐요,,,,,ㅠㅠ)

이 이슈가 생긴 폼은 유난히 유저에게 요구하는 정보가 많았던
웨이팅 메이트 등록 폼인데요, 유저가 정말 폼에 있는 순서 그대로 작성하면 상관이 없지만,
다음 API 우편주소 모달을 거친 부분에서 하나라도 뒤틀리게 된다면 바로 에러가 납니다.
다음 API 우편 주소 모달로 컴포넌트가 이동 될 때 자꾸 제 멋대로 register를 진행하더라구요.
(다른 필수값이 채워지지 않은채로 register가 진행됨)
그래서 form data를 server로 보내는 submit을 하기 전에 유효성을 한번 더 체크해줬어요!

이렇게 되면 alert가 뜨면서 register를 클릭했던 상태도 false로 바꿔주고 제출도 막아줄 수 있었습니다.
완전 유하게 UX를 만든 건 아니지만, 그래도 데이터 오류로 폼이 제출 되는 것보다는 한번 alert를 넣으니
server와의 동작에서는 예외처리를 할 수 있었습니다.
앞으로 사용자에게 정보를 받는 폼같은 경우는 버튼을 한번 누른다면 비활성화도 하고
여러번 등록하지 못하도록 하는 예외처리 같은게 중요하다고 느꼈습니다.
5-3. 로컬 스토리지로 유저 데이터 보관하기
자바스크립트는 다들 아시겠지만 비동기 언어라서, 때로 저희를 당혹스럽게 만들 때가 있습니다.
저희가 구현한 채팅방의 경우, 사용자의 id값을 확인해서
수신자와 발신자가 같은 사람의 채팅방이 생성되는 것을 방지하고,
이미 있는 채팅방의 경우에도 굳이 다른 채팅방을 만들 필요가 없다고 판단하여
채팅방이 새로 생성되는 것을 방지하였습니다.
저희가 로그인한 유저의 정보를 어떻게 관리할 것인지 여기저기 물어보았는데,
현재 압도적이라고 할 만한 방법은 없고
프로젝트의 특성에 잘 맞추어 반영을 해야한다는 답변만 들을 뿐이었습니다.
그러나 저희는 초보라서 어떤 프로젝트에 어떤 특성을 반영하기 보다는
가볍고 사용감이 당장 좋았던 zustand를 선택하여 사용하였으나,
이 zustand는 채팅방을 생성하기 전에 id값을 가져와서 예외처리들을 확인하기에는
가져오는 id값 속도가 굉장히 느린 친구였습니다.
하여 뒤늦게라도 리더님의 충고에 따라 Local Storage를 도입하였습니다.
(세션스토리지랑 고민하였으나, 탭을 닫아도 지속적으로 유지해야하는 채팅창의 속성을 따라서 로컬스토리지로 결정)
사용법은 굉장히 간단하였습니다.


그리하여 개발자 탭에서 손쉽게 로컬 스토리지의 값을 볼 수 있었습니다!
토큰과 같은 인증이 아닌 단순 id값이라서 암호화같은 건 도입하지 않았습니다 :)
이 간단한 것을 모르고 사용할 줄 몰랐다니,,,,,,,,,,,,,,, 진작에 도입하지 않아서
혼란을 초래한 시간들이 아깝습니다......
6. 아쉬웠던 점
개인적으로는, 리액트의 컴포넌트 성질을 많이 이용하려 노력하였으나 겹치는 비효율적인 코드가 많았던 것 같습니다.
이걸 줄이는 방안으로 3차를 진행하고, 추후에 2차를 디벨롭할 수 있도록 하겠습니다.
그리고, 제 파트도 너무 많아서 잘 참여하지 못했던 소캣 chatting 프론 부분도 아쉬워서
다음에는 이 부분도 많이 참여하고 싶다는 생각이 들었습니다 :)
'개발 공부한 것들 > SeSSAC 웹 풀스텍 과정 회고록' 카테고리의 다른 글
| [SeSSAC] 웹 풀스택 영등포 5기 과정_Java(Class) (2) | 2023.11.25 |
|---|---|
| [SeSSAC] 웹 풀스택 영등포 5기 과정_socket (1) | 2023.11.17 |
| [SeSSAC] 웹 풀스택 영등포 5기 과정_REACT(7)_Redux (0) | 2023.10.22 |
| [SeSSAC] 웹 풀스택 영등포 5기 과정_REACT(6)_Routing, Form (1) | 2023.10.17 |
| [Sessac] 프로젝트 회고록_CRUD (0) | 2023.10.14 |