oauth를 구현하기 위해 인가 서버로부터 받아온 인가 코드를 통해 액세스 토큰을 받아오고 그것으로 유저 정보를 받아왔다.
유저 정보의 이메일 값(유니크)이 디비에 저장되어 있지 않았다면 새로운 유저 테이블을 생성해줬다.
로그인 유지를 세션 방식으로 하기 위해 유저와 연결 된 세션을 새로 생성해줬고 생성된 세션의 id를 쿠키에 저장하기 위해 next/headers의 cookies를 가져왔다.
import {cookies} from "next/headers"
const ServerComponent= async()=>{
const cookieStore = await cookies()
cookieStore.set("key","value",options)
}
위와 같이 서버 액션으로 set을 하면 에러가 발생한다. RSC 에서의 쿠키는 read-only이기 때문이다.
서버 액션으로 설정할 순 없나 실험해보기 위해 route handler를 사용했는데 localhost:3000/api/auth/route.ts로 fetch를 했고 그 안에서 next/headers cookies로 set을 해보니 이건 또 됐다. 하지만 이것은 서버 컴포넌트에서 서버로 통신한 결과이기 때문에 브라우저에 저장되는 쿠키와 연동이 안된다. 때문에 위의 fetch 동작이 끝난 후 다른 페이지에서 cookies로 get을 해오더라도 undefined가 발생한다.
때문에 쿠키를 설정하는 것을 서버 컴포넌트에서 서버로 통신하는 것이 아닌 클라이언트 컴포넌트를 생성한 후에 거기에서 /api/auth/route.ts 로 통신하여 브라우저 쿠키에 키를 설정해줬다.
async function OAuthHostPage({ params, searchParams }: OAuthHostPage) {
const { host } = await params;
const { code } = await searchParams;
if (!isValidHost(host) || !code) throw new Error('로그인 과정에서 에러가 발생했습니다');
const accessToken = await getAccessTokenFromHostServer(host as OAuthHostType, code);
const userInfoFromHost = await getUserInfoFromHostServer(accessToken, host as AuthHostType);
return (
<>
<SetCookieComponent userInfoFromHost={userInfoFromHost} />
</>
);
}
export default OAuthHostPage;
'use client';
import { UserInfoFromHostServer } from '@/types/auth';
import { redirect } from 'next/navigation';
import { useEffect } from 'react';
function SetCookieComponent({ userInfoFromHost }: { userInfoFromHost: UserInfoFromHostServer }) {
useEffect(() => {
(async () => {
const res = await fetch(`/api/auth`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userInfoFromHost),
credentials: 'include',
});
if (res.status !== 200) {
throw new Error('error 발생');
}
redirect('/auth/redirect');
})();
}, [userInfoFromHost]);
return <div></div>;
}
export default SetCookieComponent;
// api/auth/route.ts
import { getUserFromDatabase } from '@/lib/auth/oauth';
import { createSessionAndSetCookie } from '@/lib/auth/session';
import { NextResponse } from 'next/server';
export async function POST(req: Request) {
try {
const body = await req.json();
const userId = await getUserFromDatabase(body);
await createSessionAndSetCookie(userId);
const response = NextResponse.json({ success: true });
return response;
} catch (error) {
if (error instanceof Error) {
return NextResponse.json(error.message, {
status: 500,
});
}
return NextResponse.json('internal error', {
status: 500,
});
}
}
위와 같이 클라이언트 컴포넌트를 자식에 선언한 뒤 그 곳에서 통신해주고 쿠키를 셋팅했더니 브라우저 쿠키에 저장되어 있는 것을 확인할 수 있었다.
'클라이언트 사용';
'@/type/auth'에서 {userinfofromhostserver} import;
'Next/Navigation'에서 {redirect} 가져 오기;
'react'에서 {useeffect} 가져 오기;
함수 setCookieComponent ({userInfofromHost} : {userInfofromHost : userInfofromhostserver}) {
useeffect (() => {
(async () => {
const res = await fetch (`/api/auth`, {
방법 : 'post',
헤더 : {
'Content-Type': 'Application/JSON',
},
바디 : JSON.Stringify (userInfofromhost),
자격 증명 : '포함',
});
if (res.status! == 200) {
새 오류를 던지십시오 ( '오류 (');
}
리디렉션 ( '/auth/redirect');
}) ();
}, [userInfofromHost]);
반환 <div> </div>;
}
내보내기 기본 setcookiecomponent;
'FrontEnd > Next.js' 카테고리의 다른 글
| 서버 컴포넌트에서 fetch와 캐싱 동작: SSR, SSG, ISR 관점에서 정리 (0) | 2025.09.13 |
|---|---|
| Resend로 발송 시 개발 모드에서 이메일이 오지 않는 경우 (0) | 2025.08.19 |
| 모노레포의 공통 ui 컴포넌트에 tailwind 적용 안될 때 (turborepo, tawilwind) (0) | 2024.12.11 |
| 모노레포로 공통 된 tailwind config를 생성하기(turborepo, next.js, tailwind) - 2024.12.11 기준 (0) | 2024.12.11 |
| Next.js에서 data를 받아오는 방식에 따른 장단점 (2) | 2024.12.09 |