Next.JS 처음입니다. 찾아보며 기능적으로는 동작하지만 이러한 방법이 효율적인 방법인지는 더욱 찾아봐야합니다
async signIn(body: AuthSignInRequestDto, res: Response) {
const { email, password } = body;
const user = await this.userRepository.findUserByEmail(email);
if (!user) {
throw AuthResponseDto.Fail('일치하는 사용자가 없습니다.');
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
throw AuthResponseDto.Fail('비밀번호가 일치하지 않습니다.');
}
const accessToken = await this.generateToken({ user_seq: user.seq, email: user.email, name: user.name }, '1h');
const refreshToken = await this.generateToken({ user_seq: user.seq, email: user.email, name: user.name }, '5d');
res.cookie('accessToken', accessToken, {
httpOnly: true,
// sameSite: 'strict',
maxAge: 60 * 1000 * 60,
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
// sameSite: 'strict',
maxAge: 60 * 1000 * 60 * 24,
});
// res.setHeader('Authorization', `Bearer ${accessToken}`);
const responseData = { email: user.email, name: user.name };
return res.send(AuthResponseDto.Success('로그인 성공', responseData));
}
import { useRouter } from 'next/navigation';
export default function useAuthMutation() {
const router = useRouter();
const onSignInMutation = useMutation<MutationResponse<IAuthSignInRes>, MutationError, IAuthSignInReq>({
mutationFn: (data) => AuthApi.signIn(data),
onSuccess: () => {
router.push('/board');
},
});
...
}
사실 html을 전달하는 것이 아닌 js를 전달하는 것이지만 해당 내용은 다음에...
// 미들웨어의 역할
// 미들웨어는 클라이언트의 요청을 가로채고, 필요에 따라 요청이나 응답을 수정하거나 리다이렉션 할 수 있는 기능을 제공합니다.
// 미들웨어는 주로 인증이나 권한 검사, 요청 기록, 리다이렉트 등의 작업에 사용됩니다.
import { NextRequest, NextResponse } from 'next/server';
import { cookies } from 'next/headers';
import { verifyToken } from '@/utils/verify';
export async function middleware(req: NextRequest) {
const { pathname } = req.nextUrl;
if (pathname === '/') {
return NextResponse.redirect(new URL('/auth', req.url));
}
const renewNextResponse = NextResponse.next();
const cookieStore = cookies();
const accessToken = cookieStore.get('accessToken')?.value || '';
const refreshToken = cookieStore.get('refreshToken')?.value || '';
if (!refreshToken) {
return NextResponse.redirect(new URL('/auth?expired=true', req.url));
}
const verifyAccessToken = await verifyToken(accessToken);
const verifyRefreshToken = await verifyToken(refreshToken);
if (!verifyRefreshToken) {
return NextResponse.redirect(new URL('/auth?expired=true', req.url));
}
if (!verifyAccessToken && verifyRefreshToken) {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}:${process.env.NEXT_PUBLIC_API_PORT}/${process.env.NEXT_PUBLIC_GLOBAL_PREFIX}/auth/refresh-token`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken }),
},
);
const responseData = await response.json();
const renewAccessToken = responseData.data.accessToken;
renewNextResponse.cookies.set('accessToken', renewAccessToken, { httpOnly: true, maxAge: 60 * 60 });
} catch (error) {
console.error('refresh token error', error);
}
}
return renewNextResponse;
}
export const config = {
matcher: ['/', '/board/:path*'],
};
import { decodeJwt, jwtVerify } from 'jose';
export async function verifyToken(token: string) {
try {
const secretKey = new TextEncoder().encode(process.env.NEXT_PUBLIC_JWT_SECRET_KEY);
if (!secretKey) {
console.error('JWT_SECRET_KEY is not defined.');
return null;
}
const { payload } = await jwtVerify(token, secretKey);
return payload;
} catch (error) {
console.error('JWT verification error:', error);
return null;
}
}
export function decodeToken(token: string) {
try {
return decodeJwt(token);
} catch (error) {
console.error('JWT decoding error:', error);
return null;
}
}
renewNextResponse.cookies.set('accessToken', renewAccessToken, { httpOnly: true, maxAge: 60 * 60 });
import { cookies } from 'next/headers';
export default async function BoardListPage({ searchParams }: IProps) {
const accessToken = cookies().get('accessToken');
const currentPage = searchParams.page ? parseInt(searchParams.page, 10) : 1;
let boardList: IBoardListRes[] = [];
let totalCount = 0;
try {
const response = await FetchConfig.get<{ list: IBoardListRes[]; totalCount: number }>({
url: 'board/board-list',
queryString: { page: currentPage, count: BOARD_ITEM_COUNT },
headers: { Cookie: `accessToken=${accessToken?.value}` },
});
const { data, result, message } = response;
boardList = data.list;
totalCount = data.totalCount;
} catch (error) {
console.error('API 호출 중 에러 발생', error);
}
return (
...
);
}