👉 프로젝트 기간: 22년 7월 4일 ~ 22년 7월 15일
👉 프로젝트 명: GREENEEDS
👉 프로젝트 REPO: 34-2nd-greeeneeds-frontend
👉 프로젝트 소스: Tumblbug
👉 프로젝트 구성원: 프론트엔드 4명, 백엔드 2명
홈페이지 최종 결과물(gif)
프로젝트 팀원 사진
프로젝트간 활용 협업 Tool
1️⃣ Nav, Footer: Nav에 로그인이 되었을때와 아닐때 구분해서 기능구현
2️⃣ Login: 소셜로그인(kakao)을 활용한 로그인 페이지 구성하기
Nav는 로그인이 됐을 때와 안됐을 때를 컴포넌트 구분지어 만들었다.
차이점은 로그인이 됐을 땐 유저의 정보를 받아 로그인 버튼에 유저의 이름이 나오도록 구현하였고 안됐을 땐 로그인 버튼으로 클릭시 로그인 페이지로 넘어가게 구현했다.
로그인 안됀 Nav(Nav.js)
// Nav내에서 navigate가 여기서만 쓰이는것이 아니기에
// navigate 훅을 하나로 활용하기 위해 새로운 함수를 제작
// 가야될 페이지를 인자로 받기
const movePage = path => {
navigate(path);
};
// 로그인이 안돼있을 때 클릭 시 로그인 페이지로 이동
<GoToLogin
onClick={() => {
movePage('/login');
}}
>
<ProfileIcon src="images/Nav/profileIcon.png" alt="profile" />
<LoginButton>로그인/회원가입</LoginButton>
</GoToLogin>
로그인 됀 Nav(LoggedInNav.js)
<UserOption
onClick={() => {
showOptions();
}}
>
<ProfileIcon src="images/Nav/profileIcon.png" alt="profile" />
{userData && <UserName>{userData.nickname}</UserName>}
</UserOption>
{isShowOption && <ProfileOptionBlock onLogOut={onLogOut} />}
로그인이 됀 상태에서 UserOptionBlock을 만들어서 로그아웃 버튼을 만들어 로그아웃 기능을 적용하였다.
// Nav.js
// Nav.js에서 로그아웃 기능을 하는 함수를 만들어서
const onLogOut = () => {
localStorage.removeItem('token');
};
// LoggedInNav.js
// LoggedInNav.js에 props로 전달하였다.
<LogoutButton
onClick={() => {
onLogOut();
}}
>
로그아웃
</LogoutButton>
Footer는 초기 기획단계에서 기능은 모두 빼고 레이아웃만 잡는것으로 결정돼 크게 어려움을 느낀 작업은 아니었다.
Kakao Developers에 가입하여 로그인 API에 내 프로젝트를 만들어서 지금 하고있는 팀 프로젝트에 적용하였다.
사이트 도메인을 프론트엔드에서 작업중인 http://localhost:3000
으로 등록했다.
http://localhost:3000/users/signin/kakao
로 등록까지 마쳤다.그리고나서 REST API키값을 기존에는 코드에 반영해놨다가 민감한 정보는 노출되면 안돼기 때문에 숨겨야 한다는 말을 들었고 환경변수를 활용하면 된다는 말을 들었다.
process.env.[변수명]
이런식으로 활용하면 됐다..env파일에 명시된 REST_API_KEY값
REACT_APP_REST_API_KEY=카카오에서 받은 KEY값
REACT_APP_REDIRECT_URI=http://localhost:3000/users/signin/kakao
.env에 명시된 값들은 OAuth.js라는 파일을 만들어 인가코드를 받기 위해 사용했다.
const REST_API_KEY = process.env.REACT_APP_REST_API_KEY;
const REDIRECT_URI = process.env.REACT_APP_REDIRECT_URI;
export const KAKAO_AUTH_URL = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`;
이렇게 OAuth.js에서 KAKAO_AUTH_URL을 export시켜 Login.js에서 goToKakao라는 함수에 적용을 시켰다.
const goToKakao = () => {
window.open(KAKAO_AUTH_URL, '_self');
};
소셜로그인 버튼을 클릭하게되면 해당 함수가 실행되면서 인가코드를 받기위한 URL로 넘어가지는 과정이다.
저 URL로 넘어가짐과 동시에 브라우저 URL창에 인가코드가 찍히게 되는데 그때 code라는 변수에 인가코드를 담아 백엔드에게 전달해주는 코드를 구성했다.
const KakaoLoading = () => {
const navigate = useNavigate();
const location = useLocation();
// location.search를 활용해 뽑아와야할 code값을 찾는다.
// 그리고 qs를 활용해 값을 뽑아낸다.
const code = qs.parse(location.search, {
ignoreQueryPrefix: true,
}).code;
useEffect(() => {
// 받아온 code값을 백엔드 주소로 body에 실어서 보내준다.
axios.post(API.KAKAO_LOGIN, { code }).then(res => {
// 백엔드와 소통이 성공해서 오는 토큰값을 로컬스토리지에 저장
localStorage.setItem('token', res.data.token);
// 토큰을 로컬스토리지에 저장함과 동시에 메인페이지 이동
// 실패할 경우에는 catch를 사용하지 않고 조건부로 alert창을 띄우게 구성
res.data.token ? navigate('/') : alert('로그인에 실패하였습니다.');
});
}, []);
// 해당과정이 카카오 서버와 백엔드 서버간의 통신이 주요이다 보니
// 시간이 있어서 Loading이라는 컴포넌트를 만들어서 로딩화면 제작
return <Loading />;
};
// 로딩화면 제작
// 로딩화면이 필요한 곳에서 활용하도록 components폴더에 제작
import React from 'react';
import styled, { keyframes } from 'styled-components';
const Loading = () => {
return (
<LoadingWrapper>
<LoadingText>로딩 중</LoadingText>
<Dot delay="0s" />
<Dot delay="0.1s" />
<Dot delay="0.2s" />
</LoadingWrapper>
);
};
const BounceAnimation = keyframes`
0% {
margin-bottom: 0;
}
50% {
margin-bottom: 1rem;
}
100% {
margin-bottom: 0;
}
`;
const LoadingWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;
position: absolute;
right: 47%;
top: 45%;
`;
const LoadingText = styled.h3`
color: #568a35;
`;
const Dot = styled.div`
background-color: #568a35;
border-radius: 50%;
width: 0.75rem;
height: 0.75rem;
margin: 0 0.25rem;
animation: ${BounceAnimation} 0.5s linear infinite;
animation-delay: ${props => props.delay};
`;
export default Loading;
위의 과정을 거치고 성공적으로 통신이 완료됐다면 메인페이지로 넘어가짐과 동시에 Nav가 로컬스토리지에 토큰값을 확인후에 있다면 해당 유저의 정보(이름)을 띄운다.
- 기존에 지속적으로 프로젝트하면서 로그인과 회원가입 기능은 몇번씩 해봤었지만 소셜로그인 즉, 외부 API를 활용해서 로그인을 시도해본다는 점은 매우 신선하면서도 신나면서도 두려웠다.
상당히 어려울 것만 같고 이걸 어떻게 해야하나 걱정이 태산이었다.- 하지만 백엔드 팀원과 로그인 기능구현에 대해서 서로 회의를 하면서 역할 분담을 딱 하고 나니 매우 안심이 되었다.
useNavigate
를 활용했다.import { useNavigate } from 'react-router-dom';
import { KAKAO_AUTH_URL } from '../../OAuth';
/* ... */
const navigate = useNavigate();
const goToKakao = () => {
navigate(KAKAO_AUTH_URL);
}
/* ... */
// 기존에 a태그를 사용하지 않고 button으로 변경
<LoginButton
onClick={() => {
goToKakao();
}}
>
<KakaoLoginImg
src="/images/Login/kakaoLoginButton.png"
alt="loginBtn"
/>
<LoginButton />
useNavigate
를 활용해보니 useNavigate
는 라우터의 기능으로 Path를 지정하고 이동하게끔 해주는 기능을 하다보니 우리가 필요한 HOST URL은 변경이 불가능 한 것이다.window
를 사용하면 가능하다는 것이었다. import { KAKAO_AUTH_URL } from '../../OAuth';
/* ... */
// navigate만 빼고 그 자리를 window.open으로 변경
// '_self'는 새로운 탭으로 열리지 않고 현재탭에서 이어 가는 역할을 해줌
const goToKakao = () => {
window.open(KAKAO_AUTH_URL, '_self');
}
/* ... */
<LoginButton
onClick={() => {
goToKakao();
}}
>
<KakaoLoginImg
src="/images/Login/kakaoLoginButton.png"
alt="loginBtn"
/>
<LoginButton />
1️⃣ 성장했지만 그것에 도취되어 자만하지마라 그러다 훅간다.
2️⃣ 소통은 언제나 중요한 것! 프론트엔드든 백엔드든 사람과 함께라면 대화를 는 것이 중요하다!
3️⃣ 1차 프로젝트 때와 마찬가지로 모든 답은 가까이 있으며 내가 설명을 많이 한다해서 많이 아는게 아니다. 지금보다 더 월등하게 노력해야한다!!
4️⃣ 누군가를 도와주는것은 나에게도 좋은것이다. 도움이 필요한 사람에겐 망설임 없이 도와주자!(도와주면서 나도 많이 배우고 공부하게 되었음!)
5️⃣ 어쩌다 PM을 1차에 이어 2차에도 맡게 되었는데 믿고 따라와준 팀에게 진심으로 감사드리고 같은 팀이어서 행복했고 영광이었습니다!! ☺️