소셜 로그인 연동(Kakao버전)
1. Next-auth 설치하기
session 관리를 위해서 next-auth라는 라이브러리로 쉽게 소셜 로그인을 구현할 수 있다고 한다.
$npm install --save next-auth
https://next-auth.js.org/getting-started/typescript
2. 프로젝트 생성 및 Next-auth 설정
테스트 프로젝트의 폴더 구조는 아래와 같이 구현했다.
pages\api\auth에 [...nextauth].ts 파일을 생성하고 다음과 같이 작성한다.
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import NaverProvider from "next-auth/providers/naver";
import KakaoProvider from "next-auth/providers/kakao";
export default NextAuth({
providers: [
GoogleProvider({
clientId : process.env.GOOGLE_ID as string,
clientSecret: process.env.GOOGLE_SECRET as string,
}),
NaverProvider({
clientId : process.env.NAVER_ID as string,
clientSecret: process.env.NAVER_SECRET as string,
}),
KakaoProvider({
clientId : process.env.KAKAO_ID as string,
clientSecret: process.env.KAKAO_SECRET as string,
})
],
session: {
strategy: 'jwt'
},
secret: process.env.SECRET as string,
});
각각 .env 에서 쓰이는 변수들은 .env.local 파일을 생성하여 그 안에 작성한다.
- NEXTAUTH_URL : 접속할 nextjs 앱의 url
- NEXTAUTH_SECRET: jwt를 암호화하거나 email token을 해쉬처리하기 위한 임의 string (openssl)을 이용하여 생성
- KAKAO_ID: kakao로부터 발급받은 REST API 키
- KAKAO_SECRET: kakao로부터 발급받은 Client Secret
2022.09.14 - [개발 Study/Node, js, react] - [Next.js] Kakao 로그인 API 발급 받기
_app.tsx 에 SessionProvider를 추가해 준다.
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { SessionProvider } from 'next-auth/react';
function MyApp({ Component, pageProps }: AppProps) {
return (
<SessionProvider session={pageProps.session}>
<Component {...pageProps} />
</SessionProvider>
);
}
export default MyApp
3. 페이지 구현
Next-auth는 기본적으로 Provider에 따라 로그인 화면을 제공해주지만 나는 Custom Login 화면을 구성하고 싶어서 직접 화면을 만들었다.
SSR을 이용하여 서버로부터 Session 정보를 받는 getServerSideProps를 이용하여 login page를 작성하였다.
import {NextPage} from 'next'
import {signIn, useSession, getSession, getProviders, getCsrfToken} from 'next-auth/react';
import Head from 'next/head'
import LoginButton from '../../components/LoginButton'
import Content from '../../components/ContentDiv'
const SocialLoginPage : NextPage = () => {
const { data: session } = useSession();
const login = async (provider : string) => {
const res = await signIn(provider);
console.log(res);
}
return (
<div className="container">
<Head>
<title>Login</title>
<meta name="description" content="Generated by jy" />
</Head>
{!session && (
<Content>
<LoginButton id="naver" text="네이버로 로그인" clickEventHandler={(e) => login('naver')}/>
<LoginButton id="kakao" text="카카오로 로그인" clickEventHandler={(e) => login('kakao')}/>
<LoginButton id="google" text="구글로 로그인" clickEventHandler={(e) => login('naver')}/>
</Content>
)}
</div>
);
}
export default SocialLoginPage;
export async function getServerSideProps(context : any) {
const { req } = context;
const session = await getSession({ req });
if (session) {
return {
redirect: { destination: "/auth/home" },
};
}
return {
props: {
providers: await getProviders(),
csrfToken: await getCsrfToken(context),
},
};
}
signIn('소셜') 함수로 provider에게 요청을 하여 세션정보를 받고 signOut() 함수로 세션을 종료하는데 세션을 받은 경우 /auth/home 으로 리디렉션하여 페이지 이동을 한다.
import {NextPage, InferGetServerSidePropsType } from 'next'
import {signOut, getSession} from 'next-auth/react';
import Head from 'next/head'
import LoginButton from '../../components/LoginButton'
import Content from '../../components/ContentDiv'
function HomePage({ session }: InferGetServerSidePropsType<typeof getServerSideProps>) {
console.log(session)
const logout = () => {
signOut();
}
return (
<div className="container">
<Head>
<title>Home</title>
<meta name="description" content="Generated by jy" />
</Head>
{session && (
<Content>
<LoginButton id="" text="로그아웃" clickEventHandler={(e) => logout()}/>
<></>
</Content>
)}
</div>
);
}
export default HomePage;
export async function getServerSideProps(context : any) {
const { req } = context;
const session = await getSession({ req });
if (!session) {
return {
redirect: { destination: "/auth/login" },
};
}
return {
props: {
session: session
},
};
}
로그인 하여 홈으로 들어가면 로그아웃 버튼이 뜨고 로그아웃 클릭 시 session이 종료되며 sessionToken이 쿠키에서 삭제된다. session이 없는 경우 다시 로그인 화면으로 리디렉션 하도록 getServerSideProps() 함수를 구현하였다.
로그인이나 로그아웃 후 리디렉션을 그냥 next-auth에서 pages 값에 설정하는 방법이 있는데 뭔가 잘 안되서.. 다음 기회에 다시 해봐야 할 것 같다.
4. 구현된 로그인 화면
우선 Kakao만 진행했고 추후 Naver와 Google도 연동할 예정이다. 기회가 된다면 로그인 token과 DB 가 연동된 것 까지 해볼 것이다. Typescript가 아직 생소하긴한데 배워가면서 알아가야할 것 같다.
'개발 Study > React' 카테고리의 다른 글
[NextJS] KaKao Map API로 좌표 얻기- Geocode사용하기 (1) | 2023.01.13 |
---|---|
[NextJS] SSR에서 Cookie 값 저장하고 가져오기 (1) | 2022.11.10 |
[Next.js] Kakao 로그인 API 발급 받기 (2) | 2022.09.14 |
[React/NextJS] NextJS 시작하기 (2) - fetch, redirect/rewrite, router (6) | 2022.09.06 |
[React/NextJS] NextJS 시작하기 (1) - NextJS vs ReactJS / CSR vs SSR (5) | 2022.09.05 |
댓글