728x90
반응형
MySQL, React, SpringBoot로 구현한 게시판 서비스에 네이버 아이디로 로그인 기능을 추가하는 과정으로, 실습에 사용한 코드는 https://myanjini.tistory.com/entry/board-%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C 에서 내려받을 수 있습니다.
애플리케이션 등록
네이버 개발자 사이트(https://developers.naver.com/)에서 애플리케이션을 등록하고, API를 설정합니다.
라이브러리 등록
SDK 다운로드 페이지(https://developers.naver.com/docs/login/sdks/sdks.md)에서 JavaScript용 네이버 로그인 라이브러리의 최신 버전 링크 주소를 확인합니다.
index.html 파일에 앞에서 복사한 링크 주소를 src 속성 값으로 갖는 <script> 태그를 추가합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
... (생략) ...
<!-- JavaScript용 네이버 로그인 라이브러리 추가 -->
<script type="text/javascript" src="https://static.nid.naver.com/js/naveridlogin_js_sdk_2.0.2.js" charset="utf-8"></script>
</head>
<body>
... (생략) ...
</body>
</html>
네이버 로그인 컴포넌트 추가
NaverLogin.js 파일을 생성하고, 아래 코드를 추가합니다. 해당 코드는 샘플 페이지(https://static.nid.naver.com/oauth/sample/javascript_sample.html)의 소스코드를 참고해서 작성했습니다.
import { useEffect } from "react";
const NaverLogin = () => {
// window 객체로 부터 naver와 관련한 항목을 객체 비구조화로 추출
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// index.html 페이지에 추가한 <script>에 의해서 설정
const { naver } = window;
// 네이버 개발자 사이트에 등록한 애플리케이션의 ID와 Callback URL을 상수로 정의
const NAVER_CLIENT_ID = `5chnMhfd1oStUPJr9rqa`;
const NAVER_CALLBACK_URL = `http://localhost:3000/login`;
// 네이버 로그인에 필요한 #1 값 설정, #2 초기화,
// #3 로그인 결과를 반환하는 콜백 함수를 등록해 주는 함수
const initializeNaverLogin = () => {
// #1
const naverLogin = new naver.LoginWithNaverId({
clientId: NAVER_CLIENT_ID,
callbackUrl: NAVER_CALLBACK_URL,
isPopup: true,
loginButton: { color: 'green', type: 3, height: 60 }
});
// #2
naverLogin.init();
// #3
naverLogin.getLoginStatus(function (status) {
// 로그인 성공 시 true를 값으로 가짐
if (status) {
// 로그인 성공 시 naverLogin의 user 객체에 있는 정보 중
// 필요한 정보를 로컬 스토리지에 저장
localStorage.setItem('userName', naverLogin.user.name);
localStorage.setItem('userNickname', naverLogin.user.nickname);
localStorage.setItem('userPhoto', naverLogin.user.profile_image);
// 부모 브라우저 창의 주소를 홈(/)으로 변경 후
// 팝업 브라우저 창을 닫음
window.opener.location.href = "/";
window.close();
}
});
};
// 최초 마운트 시 initializeNaverLogin 함수를 호출
useEffect(() => {
initializeNaverLogin();
}, []);
// 로그인 버튼을 출력(id는 고정된 값)
return <div id="naverIdLogin" />;
};
export default NaverLogin;
로그인 컴포넌트 추가
Login.js 파일을 생성하고, 아래 코드를 추가합니다. 해당 컴포넌트에서는 네이버 로그인을 비롯한 다양한 소셜 로그인과 ID, PW 기반 로그인을 쉽게 추가할 수 있도록 랩핑해 주는 역할을 합니다.
import NaverLogin from "./NaverLogin";
import { useEffect } from "react";
const Login = () => {
useEffect(() => {
// 로컬 스토리지에 userName이 존재하는 경우 로그인한 것으로 판단
// 이미 로그인한 경우 홈(/)으로 이동
const isLogin = !!window.localStorage.getItem('userName');
if (isLogin) {
window.location.href = '/';
}
}, []);
return (
<>
<div style={{ textAlign: 'center', padding: '30px' }}>
{/* 다양한 방식의 로그인 컴포넌트를 추가 */}
<NaverLogin />
</div>
</>
);
};
export default Login;
로그인/로그아웃 버튼 추가
로그인 여부에 따라 로그인/로그아웃 버튼을 제공하도록 App.js 파일을 수정합니다.
import './App.css';
import { Route } from 'react-router-dom';
import BoardList from "./board/BoardList";
import BoardDetail from "./board/BoardDetail";
import BoardWrite from './board/BoardWrite';
import Login from './Login';
const App = () => {
// 로그인 페이지로 이동
const handlerLogin = (e) => {
e.preventDefault();
window.location.href = '/login';
};
// 로그아웃 처리
// 로컬 스토리지 내용 삭제 후 홈(/)으로 이동
const handlerLogout = (e) => {
e.preventDefault();
localStorage.clear();
window.location.href = '/';
};
// 로그인 페이지가 아닌 경우 로그인/로그아웃 버튼을 제공
// 로그인 상태인 경우 로그인 정보와 로그아웃 버튼을
// 로그아웃 상태인 경우 로그인 버튼을 제공
const isNotLoginPage = window.location.pathname === '/login' ? false : true;
const isLogin = !!window.localStorage.getItem('userName');
return (
<>
<div style={{ textAlign: 'right', padding: '30px' }}>
{ isNotLoginPage && isLogin &&
<>
{ window.localStorage.getItem('userName') }님 환영합니다.
<button onClick={handlerLogout}>Logout</button>
</>
}
{ isNotLoginPage && !isLogin &&
<>
<button onClick={handlerLogin}>Login</button>
</>
}
</div>
<Route path="/" component={BoardList} exact={true} />
<Route path="/login" component={Login} exact={true} />
<Route path="/board" component={BoardList} exact={true} />
<Route path="/board/write" component={BoardWrite} />
<Route path="/board/detail/:boardIdx" component={BoardDetail} />
</>
);
};
export default App;
실행 결과
최종 코드
728x90
반응형
'개발' 카테고리의 다른 글
웹 애플리케이션에서 도커 컨테이너 실행, 삭제, 조회 (0) | 2023.04.10 |
---|---|
카카오 로그인 (0) | 2023.04.06 |
EC2 인스턴스에 React + SpringBoot + MySQL 연동 (0) | 2023.03.29 |
폼 데이터와 함께 파일 업로드 (0) | 2023.02.21 |
그래들 빌드 및 실행 (0) | 2023.01.17 |
댓글