아워코드트립 프로젝트 후기

이민재·2021년 11월 7일

react

목록 보기
4/5
post-thumbnail

프로젝트 정보

"주제"

**여행 상품 판매 APP 마이리얼트립 홈페이지 클론코딩

"기간"

**10월 25일(월)~ 11월 5일(금)

"인원"

**F.E: 본인을 포함한 3명 / B.E: 2명

"github repository"

OCT(Our Code Trip)- front
OCT(Our COde Trip)- back

기술 스택

👏 F.E

  • HTML/CSS/SASS
  • JAVASCRIPT (ES6+)
  • REACT/ REACT ROUTER
  • STYLED-COMPONENTS
  • React Hooks
  • React Redux

프로젝트 소개 및 기능

마이리틀트립 홈페이지는 다양한 여행 상품을 판매하는 여행 플랫폼이며,
컴퍼넌트, 기능별로 구분하여 역할분담을 하기 아주 좋은 페이지였다.
특히, 메인페이지와 리스트 페이지, 위시 리스트 페이지들은 모두 카드 슬라이드로 되어 있었는데 다 조금씩 크기와 형태가 다른 카드 슬라이드. 하나의 컴퍼넌트로 여러 페이지들을 구현할 수 있다는 것이 단연 일품이다. 또한, 소셜 API 연동 로그인 페이지, 리뷰, 화려한 nav bar, 로딩 페이지, 프로필 등 redux, hooks, styeld-component를 적용해보고 화려하게 날아볼 수 있는 좋은 프로그램이었다.

우리 F.E 팀들은 '투어,티켓' 리스트 부분을 완벽하게 구현하고자 목표로 삼고 다음과 같이 구분하여 역할분담을 하였다.
그 중에 내가 맡은 부분은 sign-in, profile이었다.

  1. Front-end
    1) nav, footer bar
    2) carousel
    3) sign in(Social API)
    4) profile
    5) wish list
    6) detail page
    7) list page
    8) reivew

내가 구현한 기능들

카카오 API 로그인 기능 구현

"카카오 로그인 API 이해하기"


이미지 출처: kakao developers

사용자가 [카카오톡으로 로그인]을 선택하면 카카오톡 실행 또는 실행 중인 카카오톡으로 연결되고, [다른 카카오계정으로 로그인]을 선택하면 직접 계정 정보를 입력하는 화면이 출력됩니다.
카카오톡이 설치되어 있지 않은 기기나 PC 웹 환경에서는 직접 계정 정보를 입력하여 카카오계정으로 로그인하게끔 진행됩니다.
'카카오톡으로 간편로그인'한 경우, 카카오톡에 연결된 카카오계정의 자격정보(Credentials)를 통해 사용자를 인식합니다. 직접 카카오계정을 입력해 로그인한 경우에는 해당 계정의 자격정보로 인식합니다.
자격정보가 올바르다면 카카오 로그인 동의 화면을 통해 사용자로부터 사용자 정보 및 기능 활용 동의를 받습니다.
사용자가 필수 항목에 동의하고 로그인을 요청하면 인가 코드(Authorization Code)가 발급됩니다. 이 코드는 앱 정보의 Redirect URI에 전달됩니다.
앱은 전달 받은 인가 코드를 기반으로 토큰을 요청하고 받습니다.

F.E는 App key로 API를 실행시키고,(본인은 Javascrtip SDK 키를 사용한 방식을 사용) API를 호출해서 사용자 정보 및 기능 활용 동의와 로그인을 모두 성공적으로 완료하면 토큰을 받게 된다.
카카오부터 받은 이 토큰을 우리 사이트에서 쓸 수 있도록 사용하려면?!
우리는 JWT 토큰을 사용했다.
백엔드에게 토큰을 넘기면 백엔드는 우리 서버에서 유저 데이터를 확인하고 성공 시 JWT 토큰을 넘겨주게 되고, 활용하면 되겠다.

"카카오 인증 구현(카카오 토큰 받기)"

로그인

카카오 로그인 동의 화면을 팝업으로 띄우거나 클라이언트에서 모든 인증 처리를 하고 싶은 경우 Kakao.Auth.login 함수를 사용할 수 있습니다.
클릭 이벤트 핸들러에서 함수를 호출하면 카카오 로그인 동의 화면을 띄울 수 있으며, 동의 화면을 통해 사용자로부터 사용자 정보 및 기능 활용 동의를 받을 수 있습니다.
함수 호출 시 팝업으로 카카오 로그인 동의 화면이 표시됩니다. 로그인 요청 결과 토큰이 발급되며, 이 토큰은 SDK 내부적으로 사용되고 있기 때문에 별도의 처리가 필요하지 않습니다.
로그인 성공 시 서비스의 로그인 및 회원 가입 처리가 필요합니다. 인증 성공 시 서비스의 로그인 처리는 success 콜백 함수를 사용해야 합니다.

이미지 출처: kakao developers

내가 작성한 코드

const KakaoLoginHandler = () => {
    window.Kakao.Auth.login({
      scope: 'profile_nickname,profile_image,account_email',
      success: authObj => {
        const bearer = 'Bearer' + ' ' + authObj.access_token;
        fetch('http://localhost:8001/users/auth/kakao', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: bearer,
          },
        })
          .then(res => {
            return res.json();
          })
          .then(res => {
           		if (res.message === 'success') {
                  alert(`${res.name}님 환영합니다.`);
                } else {
                  alert('다시 시도해주세요');
                }
              });

로그아웃(연결 끊기)

앱과 사용자의 연결을 끊기 위해 호출하는 함수입니다. 사용자가 연결 끊기 버튼을 클릭했을 때, 클릭 이벤트 핸들러에서 Kakao.API.request 함수를 사용해서 연결 끊기를 요청할 수 있습니다.
Kakao.API.request 함수의 파라미터인 url에 '/v1/user/unlink'를 할당해서 사용합니다.

이미지 출처: kakao developers

내가 작성한 코드

const KakaoLogoutHandler = () => {
  if (window.Kakao.Auth.getAccessToken()) {
    window.Kakao.Api.request({
      url: '/v1/user/unlink',
      success: res => {
        console.log(res);
      },
      fail: err => {
        console.log(err);
      },
    });
  } else {
    console.log('Not logged in');
  }
};

Kakao.Auth.logout 함수는 로그인 시 발급받은 토큰을 만료시키는 함수이며, 카카오계정의 로그아웃이나 서비스의 로그아웃에 영향을 주지 않으므로 '연결 끊기'의 함수를 이용했다.
Kakao.Auth.getAccessToken 함수를 확인하고 Kakao.API.request 함수를 사용해서 연결 끊기를 요청하는 방식이다.

👉(직면한 문제)
동의 scope 항목, 토큰 형태, 통신 주소, 방식, 어디다가 담아서 보내야 할지? 어디에다가 저장해야할지? 정말 많은 고민을 했다. 방식은 fetch가 좋을까? axios가 좋을까? localStora에 저장할까? sessionStroage에 저장할까? localStroage? 그래? 왜? '현재 상황에'서 어떤 방식이 가장 좋을까 많은 토의를 했다. 특히, 이 사이트에서는 유저 로그인, 프로필에서만 5번의 API를 호출한다. 그 중 3번의 API는 형태가 다르기 때문에, 코드를 깔끔하게 하기 위한 노력을 많이 했다.

👆(해결)
처음에는 고유한 pathname에 따른 util 함수로 처리를 해서 호출을 했으나, 나름 여의치가 않아 해결하기 위해 고민하고 있다.

프로필 관리/편집 기능 구현

"기존 데이터를 어떻게 수정할 것인가?"

👉(직면한 문제)
사이트 내에서 사용할 유저 아이디, sms 수신 동의 여부, email 수신 동의 여부의 프로필을 편집하며, 서버에 요청을 보내서 데이터를 계속 수정해야 한다.
두 가지 방법으로 고민을 했다. useState 초기값을 기존 데이터가 갖고 있어야 하나, 아니면 빈 값에 계속 넣어주어야 하나

👆(해결)
빈 초기값에 useEffect 함수를 이용해서 넣어주어야 한다.
why? useState는 최초 한번만 호출되기 때문에 props값이 변경돼도 계속 영향을 주지 못하기 때문이다.
물론 현재 상황에서는 그렇게 편집 저장을 누르면 관리 페이지로 이동하기 때문에 큰 영향은 없지만, 되도록이면
useState 초기값에 props 값을 넘겨주는 방법은 지양해야겠다.

const EditingProfile = () => {
  const [userData, setUserData] = useState([]);
  
  // Email, sms동의 여부를 초기값 빈 값으로 설정.
  const [checkedEmail, setCheckedEmail] = useState('');
  const [checkedSms, setCheckedSms] = useState('');
  
  const [isKakaoLinked, setIsKakaoLinked] = useState(false);

  const handleSmsChecked = () => {
    setCheckedSms(!checkedSms);
  };

  const handleEmailChecked = () => {
    setCheckedEmail(!checkedEmail);
  };

  useEffect(() => {
    fetch('http://localhost:8001/users/profile/', {
      method: 'GET',
      headers: {
        Authorization: 'bearer ' + localStorage.getItem('token'),
        'Content-Type': 'application/json',
      },
    })
      .then(res => res.json())
    
    //useEffect 함수안에 setState를 활용해 수정된 데이터 값을 넣어주었다.
      .then(res => {
        console.log(res);
        const { data } = res;
        setUserData(data);
        setCheckedEmail(data.isEmailAgreed);
        setCheckedSms(data.isSmsAgreed);
        setIsKakaoLinked(data.platform === 'kakao');
      });
  }, []);

  return (
    <ProfileWrapper>
      <Header>
        <h1>프로필 편집</h1>
      </Header>
      <Main>
        <SideProfileSection userData={userData} />
        <EditingProfileMainSection
          userData={userData}
          checkedSms={checkedSms}
          checkedEmail={checkedEmail}
          handleSmsChecked={handleSmsChecked}
          handleEmailChecked={handleEmailChecked}
          isKakaoLinked={isKakaoLinked}
          setIsKakaoLinked={setIsKakaoLinked}
        />
      </Main>
    </ProfileWrapper>
  );
};

export default EditingProfile;

마친후 내 생각

  • "문서"를 많이 읽어야 한다. 특히, 공식 문서!
    처음에 잘 눈에 들어오지 않아서, 카카오 로그인 API 공식문서를 3~4번을 보면서 이해하려고 했다. 읽고 이해하는 것 조차 쉽지 않았지만, 반복하면 반복해서 읽을 수록 다음 번에 읽을 때는 이해가 쉬워졌다. 결국엔 읽고나니 손쉽게 적용할 수 있었다.
    리액트도 마찬가지다. styled-components, hooks, redux, 다른
    library.. 새로운 기술들을 적용하느라 빠르게 기능 구현을해서 결과물을 만들어 내야겠다는 생각에 조급했다. 생각해보면 나는 다 이해를 하지 못했다. 더 시간을 많이 들이는 것 같더라도 차분하게 내가 하고자 하는 부분의 공식문서를 읽고 이해해야 한다.

  • 존경하는 모든 팀원들로 부터 배운다. 성장했다!
    특히 이번 프로젝트는 같은 팀원이었던 욱창님을 보고 많이 배울 수 있었다. 가령 예를 들자면, 같은 문제가 발생했을 때 욱창님은 코드를 계속보며 어느 부분이 문제가 생겼는지 파악하기 시작한다. 그때의 나는 옆에서 눈에 보이지 않는 부분만 고치기 시작한다. 다시 욱창님은, 문서로 가서 문법을 다시 확인한다. 그때의 나는 아직도 잘 모른채로 고치기 시작한다. 욱창님은 더 빠르고 장기적으로 더 효율적으로 문제를 해결했다. 나는 해결했어도 해결을 했던 걸까?

  • "문제 해결 능력"은 내 문제를 파악하는데서 시작한다. 시간이 오래 걸리더라도 문제를 정확히 파악하고 해결하고, 다시 회고하는 시간을 가져야 한다! 우리 PM 같았던 원국님처럼 계속 작성하며, 사용자 관점에서 최고의 최적화를 할 수 있을때 까지 성장하자.

-더 성장해야 한다, 배움에 두려워 하지말고 욕심 내자.

프로젝트 시연 영상

[출처]

https://developers.kakao.com/

https://ko.reactjs.org/docs/hooks-intro.html

https://medium.com/@digruby/do-not-use-props-as-default-value-of-react-usestate-directly-818ee192f454

https://velog.io/@kairase024/Props%EB%A5%BC-React.useState-%EC%9D%98-%EA%B8%B0%EB%B3%B8%EA%B0%92%EC%9C%BC%EB%A1%9C-%EC%A7%81%EC%A0%91-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EB%A7%88%EC%8B%AD%EC%8B%9C%EC%98%A4

profile
스스로 기억하기 위해서, 기록해요

0개의 댓글