[탐나BnB] 프로젝트 회고록

Joah·2022년 7월 17일
1

프로젝트-탐나BnB

목록 보기
7/7
post-custom-banner

2차 프로젝트 탐나BnB 회고록

프로젝트 깃헙주소


⛳ 프로젝트 준비

📍 욕심나는 airbnb
📍 새롭게 적용하는 기술 및 기능
📍 담당한 페이지 분석


📍 욕심나는 airbnb

airbnb를 클론 코딩할 수 있는 기회는 모든 개발자들이 욕심낼 수 밖에 없다. airbnb는 서버와 클라이언트 모두 다양한 시도와 도전을 할 수 있으며 그 도전의 벽을 넘기란 사실 쉽지 않았다. 하지만 이번 프로젝트를 통해 엄청난 성장을 이룰 수 있겠다라는 확신을 주는 airbnb 서비스는 다시 프로젝트를 시작할 수 있는 원동력이 되었다.


📍 새롭게 적용하는 기술 및 기능

1차 프로젝트와 달리 2차 프로젝트에서는 모든 라이브러리를 사용할 수 있다. 또한 CSS 및 SCSS 파일을 따로 생성하지 않고 styled components를 사용하여 component를 생성함과 동시에 스타일링 할 수 있다.

새로운 기능과 기술을 적용할 수 있다는 설렘이 있지만 반면 해당 기술들에 익숙해질 때까지 시간이 걸린다는 점이다. 하지만 프로젝트의 기간은 오직 2주! 적응과 동시에 적용해야 한다.


📍 담당한 페이지 분석

» Social Login

  • 로그인 버튼을 클릭하면 모달창을 통해 로그인을 진행할 수 있다.

  • airbnb에서는 페이스북, 구글 등의 소셜 로그인을 제공하고 있다.

  • 따로 전화번호를 통해 airbnb에 로그인 또는 회원가입이 가능하다.


» Navigation Bar

  • airbnb의 내비게이션 바에는 지역, 날짜, 인원을 바로 검색하여 필터링 되는 결과를 즉시 볼 수 있게 검색창이 있다.

  • 초기화면에서는 보이지 않다가 내비게이션 바를 클릭하면 해당 옵션들을 볼 수 있다.


⚙️내비게이션 바를 선택한 이유

1차 프로젝트에서 동료가 구현한 내비게이션 바에는 회원가입/로그인 기능이 있었다. 개인적으로 가장 어려워 보였다. 로그인과 회원가입은 모든 서비스에서 필요한 기능이기 때문에 반드시 구현하고 싶었다. 또한 airbnb의 내비게이션 바는 누구에게나 매력적으로 다가온다. 어려워 보일수록 더 도전하고 싶은 법!

2차 프로젝트에서는 회원가입과 로그인 기능을 카카오 소셜 로그인으로 대체하기로 했다. 오히려 좋다. 거의 모든 서비스에서 소셜 로그인을 제공하고 있기에 반드시 알아야할 기능이다.


⛳ 프로젝트 진행

📍 구현 내용
📍 Errors & Blockers


📍 구현 내용

소셜 로그인 (Kakao)

소셜 로그인 구현 과정

내비게이션 바 (Modal without library)

내비게이션 바 구현 과정

달력 library 사용하기 (feat.react-datepicker)

달력 library 구현 과정


📍 Errors & Blockers
이번 프로젝트에서는 Blockers가 많았기에 Blockers 위주로 작성

🚫로그인 성공! 하지만 로그인 버튼이 변경되지 않는다?

위의 소셜 로그인 구현 내용의 gif 동영상을 참고하면 로그인에 성공하는 즉시 로그인 버튼이 user의 카카오 프로필 사진으로 변경된다. 하지만 여기에는 수많은 "왜 안돼??"라는 고민이 있었다.

로그인 성공 ▶️ 프로필 사진 변경❌
로그인에 성공하고 다시 메인 페이지로 돌아갔을 때는 로그인 버튼에 아무런 변화가 없지만 해당 버튼을 한번 더 클릭하거나 새로고침 했을 때 프로필 사진으로 변경된다. 즉, 리렌더링이 되어야 로그인 버튼의 상태가 변경된다.

왜 일까?
React에서 화면을 리렌더링 하기 위한 조건은?
바로 state가 업데이트 되어야 한다는 것! 또는 새로고침!

//kakao.js

  useEffect(() => {
    fetch(`http://서버주소/users/kakao-signin?code=${code}`)
      .then(res => res.json())
      .then(data => {
        if (data.access_token) {
          localStorage.setItem('token', data.access_token);
          localStorage.setItem('userImage', data.user_image);
          localStorage.getItem(‘token’)
          ? navigate(/main’)
          : alert(‘로그인에 실패하였습니다’);
      });
  }, []);
  • 위의 과정은 인가코드를 서버에 보내고 다시 서버에서 토큰을 넘겨준다. 넘겨준 토큰을 로컬 스토리지에 'token'이라는 이름으로 저장한다.

  • getItem 메서드로 로컬 스토리지에 'token'이 있다면, useNavigate를 사용하여 URL 주소를 /main으로 변경하게 된다.

  • 정리하자면, 서버에서 받아온 토큰을 로컬 스토리지에 저장하고 로컬 스토리지에 토큰이 있다는 것을 확인하면 메인 페이지로 이동하라는 함수다.

✅위의 과정에서 state를 업데이트하는 코드가 있나?

토큰을 받거나 로컬 스토리지에 토큰을 저장하는 로직에는 그 어떤 state도 업데이트 되지 않는다.

✅그럼 로컬 스토리지에 저장된 token의 유무에 따라 state를 부여할까?

kakao.js에서 useState를 작성하여 토큰의 유무에 따라 true, false를 지정한다고 해도 해당 stateprops로 로그인 버튼이 있는 Login.js에 넘겨주어야 한다. 하지만 둘은 부모 자식 관계가 아니다. 그렇다면 전역에 해당 state를 정의해야 한다는 뜻인다. 그렇기에는 아직 Redux에 대해 공부하지 않은 상태라 최대한 Redux나 Recoil 없이 프로젝트를 진행하고자 했다.

👌 해결은 강제 새로고침
💻적용한 코드

//kakao.js

  useEffect(() => {
    fetch(`http://서버주소/users/kakao-signin?code=${code}`)
      .then(res => res.json())
      .then(data => {
        if (data.access_token) {
          localStorage.setItem('token', data.access_token);
          localStorage.setItem('userImage', data.user_image);
          window.open('http://localhost:3000', '_self');
        } else {
          alert('로그인 실패');
        }
      });
  }, []);

찝찝함을 뒤로하고 강제 새로고침을 선택한 이유는 다양한 시도를 했지만 아직까지는 그렇다할 해결을 찾지 못했다.

만약 로그인 버튼을 <Link />태그로 감싸면 자동으로 새로고침이 되며 페이지로 이동하니 적용을 해보았다.

아주 기이하게도 브라우저 <a>태그는 브라우저에 CLIENT_ID를 노출시켜 버린다. 이것에 대한 원인을 아직 찾지 못했다.

따라서 아래의 코드로 강제 새로고침을 진행했다.

window.open('http://localhost:3000', '_self')

window.open은 다음의 주소를 새로운 창에서 열어주는 메서드이다. 뒤에 _self 속성을 붙여 현재 페이지에 로드하도록 지정한다.

결과적으로 로컬 스토리지에 토큰이 있다는 것이 확인되면 즉시 새로고침을 하여 로그인 버튼이 사용자의 카카오 프로필 사진으로 변경되는 것을 알 수 있다.


🚫라이브러리가 능사는 아니다! 직접 구현할 수 있다면 도전하기!

유독 모달창이 많았던 이번 프로젝트 내비게이션 바. 모달창을 구현한 경험이 없기 때문에 오! 라이브러리를 사용해 볼까? 하는 마음에 사전 조사 없이 무작정 react-modal을 설치했다.

이미 만들어진 컴포넌트를 붙여넣기 하고 공식 문서에 명시된 속성들을 추가해서 설정할 수 있다.

하지만 라이브러리를 사용했을 때, 모달창의 state를 관리하는 것이 쉽지 않았다. 대략 한 프로젝트에 하나의 모달을 구현할 때 아주 적합했던 라이브러리였다고 할 수 있다.

이 시점에서 고민을 했다. 아직 6개의 모달 중 하나의 모달만 만들었으니 라이브러리의 단점을 빨리 찾아서 다행이다. 모달창을 많이 만들어야 하니 내 입맛대로 구현할 수 있고 state 관리도 내가 만든 로직안에서 통제할 수 있도록 직접 만들어 보자고 결정했다.

그 결과 모달창은 겨우 2개의 컴포넌트만 있으면 직접 구현할 수 있었다.


  <ModalOutside onClick={closeWhereModal} />
  <SelectWrapper onClick={e => e.stopPropagation()}>
  	<JejuCity>제주시</JejuCity>
	<SeogwipoCity>서귀포시</SeogwipoCity>
  </SelectWrapper>
  • 직접 구현의 장점은 내가 원하는 방향으로 구현 가능하다는 점이다. 어떤 모달창은 닫고 어떤 모달창은 열고 등의 함수도 작성할 수 있다.
  const closeButWhere = () => {
    setWhereModal(!whereModal);
    setWhenModal(false);
    setVisitorsModal(false);
  };
  const closeButWhen = () => {
    setWhenModal(!whenModal);
    setWhereModal(false);
    setVisitorsModal(false);
  };
  const closeButVisitors = () => {
    setVisitorsModal(!visitorsModal);
    setWhereModal(false);
    setWhenModal(false);
  };

라이브러리를 당연히 사용해야할 때도 있지만 직접 구현할 수 있다는 것을 명심하자! 라이브러리의 장단점과 직접 구현의 장단점을 확실하게 알 수 있는 계기가 되었다.

🚫Styled Components

컴포넌트를 생성하는 동시에 스타일을 적용할 수 있다니! className을 짓기 위해서 더 이상 고민하지 않아도 된다니!!
2차 프로젝트부터 적용하는 styled components는 다소 생소했지만 깔끔하게 정리되어 있는 코드를 선호하는 나에게는 반가운 라이브러리이다.

하지만 사용하다보니 propsprimary 개념이 슬슬 헷갈리기 시작했고, <GlobalStyle/><ThemeProvider />를 어떻게 적용해야 하는지 감이 안잡혔다.

theme의 개념을 알기 전, 항상 variables.jsimport하는 문장을 작성해야 했다. 매우 귀찮았다.

import variables from '../styles/variabled'
.
.
.
const LogInArea = styled.div`
  ${variables.flex()}
  width: 300px;
`;

theme은 index.js에 최상단으로 명시되어 있어 해당 프로젝트 모든 곳에서 사용 가능하다.

//index.js

import GlobalStyle from './styles/GlobalStyle';
import theme from './styles/theme';
import variables from './styles/variables';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <ThemeProvider theme={{ style: theme, variables }}>
    <GlobalStyle />
    <Router />
  </ThemeProvider>
);

따라서 themevariables에 접근하여 굳이 import를 하지 않아도 미리 정의된 스타일을 지정할 수 있다.

const LogInArea = styled.div`
  ${({ theme }) => theme.variables.flex('flex-end', '')}
  width: 300px;
`;

🚫git rebase

이번 프로젝트부터는 git merge 명령어를 git rebase 명령어로 대체하게 되었다.

rebase는 새로운 개념으로 다가왔다. rebase를 하면서 동시에 squash 를 사용해 커밋을 하나로 정리 할 수 있기 때문이다.

git 명령어를 입력할 때는 항상 주변에 동료가 지켜봐야 마음이 편할 정도로 조심스럽다. 혹여나 main이나 master에 push 해서 이제까지 merge한 작업이 모두 사라질까봐...

하지만 git rebase abort, git continue 등 멘붕인 상황에서 구해줄 명령어들이 있으니 너무 겁먹지 말자!

  • conflict 해결하기
    - git checkout main 우선 메인에서 remote pull 받기
    - git pull origin master
    - git checkout 작업하던 브랜치
    - git rebase -i main / git fetch -p ▶️ git rebase main
    - conflict 해결하기
    - git add .
    - git rebase --continue
    그래도 계속 conflict가 있다면 해결하고 다시 add . ▶️ --continue
    - git push origin 브랜치

  • remote에서 동료의 브랜치 나의 local로 가져오기
    - git remote update



⛳ 프로젝트를 마무리하며

📍 힘들었던 점
📍 스스로를 칭찬하고 싶었던 점
📍 프로젝트 전 / 후의 나


📍 힘들었던 점

🧩새로운 개념에 적응하기
2차 프로젝트는 서비스 자체가 난이도가 있었으며 styled components, library, git rebase 등을 사용하면서 새로운 개념들을 적용해야 했다. 이런 개념들을 정확하게 숙지하지도 못한 상태에서 마냥 소스를 작성해 나갔다.

잘 모르는 상태에서 이렇게 코드를 작성해 나가도 될까? 걱정했다. 공식 문서를 차분히 읽을 시간 없이 프로젝트를 진행해야 했다. 하지만 결국은 수많은 에러를 만나면서 자연스럽게 개념을 이해하게 되었다.

에러 해결에는 정말 많은 수고와 노력이 필요했지만 확실하게 개념이 잡히는 과정 중에 하나였다.

🧩스스로 해내기(사실은 함께해서 가능했다)
내비게이션 바는 특히 다른 팀원들과 겹치는 기능, 스타일, 컴포넌트가 없었다. 즉, 혼자 힘으로 해결해야 한다. 소셜 로그인을 처음 구현하는 입장에서는 혼자 구현하기란 쉽지 않았다.

또한 백엔드 개발자와 많은 결정을 함께 내려야했던 소셜 로그인은 서로의 대한 이해와 지속적인 소통이 필요했다.

하지만 언제나 그렇듯 이미 나의 상황을 경험한 많은 개발자분들의 블로그를 참고하여 성공적으로 구현할 수 있었다.

주변에 당장 날 도와줄 개발자가 없다고 하더라도 이미 나의 고민을 똑같이 고민했던 개발자들이 도와줄 수 있다.

가장 중요한 것은 포기하지 않고 끝까지 도전하는 것!


📍 스스로를 칭찬하고 싶었던 점

👍 끈기와 의지
이번 프로젝트를 통해 나도 몰랐던 나를 발견할 수 있었다. 강점이 많은 나의 유일한 약점은 끈기가 없다는 것이다.

하지만 뒤엉킨 모달창의 state와 최상위 부모에서 자식의 자식의 자식의 형제의 자식의 자식에게 props를 전달하는 복잡한 코드를 매일 새벽까지 파고 또 팠다.

하나만 고치면 될 것 같아! 조금만 더 하면 될 것 같아! 그렇게 일주일 하루 16시간 동안 코딩을 했다. 결국 성공했다. 꼭 해내겠다는 의지와 그 의지를 뒷받침할 끈기가 있었기 때문이다.

매 순간 포기하고 싶었지만 절대 놓치지 않도록 도와준 팀원, 멘토님 그리고 내 자신에게 고맙다.

👍 외롭지만 소통!
탐나BnB에서 내비게이션 바를 선택한 이유는 위에 언급한 바와 같이 로그인과 회원가입을 구현해 보고 싶었기 때문이다. 1차때는 못했던 모달창 또한 구현하고 싶었다.

하지만 간과하고 있었다. 내비게이션 바는 독립적인 요소이기 때문에 다른 팀원들과의 소통이 크게 필요하지 않았다. 혼자 묵묵히 구현하면 되었다.

컴퓨터와의 대화보다는 사람과의 대화를 선호하는 나에게는 외로운 프로젝트였다. 첫 일주일은 다른 페이지의 진행 상황에 대해서 신경을 쓸 수 없을 정도로 정신없이 흘러갔지만 2주차부터 팀원들과 소통을 시작했다.

역시 소통의 과정에서 서로가 생각하지도 못했던 해결책을 제시하기도 하고 놓쳤던 에러를 발견하기도 한다. 1차, 2차 느꼈지만 프로젝트의 핵심은 소통이다.


📍 프로젝트 전 / 후의 나
1차 프로젝트 이후 자신감이 생겼다. 이미지 슬라이드, 데이터 map 함수, 컴포넌트 재사용 등 내가 작성한 코드가 정상적으로 작동했기 때문이다.

2차 프로젝트는 1차와는 차원이 다른 난이도였다. 자신감이 모두 사라지고 2주동안 절대 못할 것 같은 느낌이 강하게 들었다.

하루하루가 지나며 소셜 로그인을 이해하고 있는 나, 모달창 라이브러리를 과감하게 삭제하고 직접 구현하고 있는 나, 달력 라이브러리를 자유자재로 커스터마이징 하고 있는 나, 검색 결과를 메인 페이지로 넘겨주는 방법을 백엔드에게 과감하게 제시하는 나.

항상 프로젝트를 진행하면서 성정하는 나를 발견한다. 그 성취감을 위해서 몰입하다보면 완성된 프로젝트와 함께 점점 프론트 엔드 개발자가 되어가고 있었다.

앞으로 더 많은 공부를 해야한다. 더 어려운 에러가 나타날 것이지만 프로젝트를 했던 경험을 되살려 끈기있게 도전한다면 어느새 모두 이루고 있는 내 모습을 볼 수 있을 것이다.

profile
Front-end Developer
post-custom-banner

0개의 댓글