Next.js JWT를 이용한 인증 구현하기
KUKJIN LEE • 5개월 전 작성
먼저 필요한 패키지를 설치합니다.
npm install jsonwebtoken bcryptjs
JWT와 bcrypt를 이용한 API 작성
app/api/auth/register.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { NextResponse } from 'next/server';
const users = []; // 실제 구현 시 데이터베이스 사용
export async function POST(request) {
const { username, password } = await request.json();
const hashedPassword = await bcrypt.hash(password, 10);
const user = { id: Date.now(), username, password: hashedPassword };
users.push(user);
const token = jwt.sign({ id: user.id, username: user.username }, 'jwt_secret', {
expiresIn: '1h',
});
return NextResponse.json({ token });
}
app/api/auth/login.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { NextResponse } from 'next/server';
const users = []; // 실제 구현 시 데이터베이스 사용
export async function POST(request) {
const { username, password } = await request.json();
const user = users.find(user => user.username === username);
if (!user || !(await bcrypt.compare(password, user.password))) {
return NextResponse.json({ error: 'Invalid username or password' }, { status: 401 });
}
const token = jwt.sign({ id: user.id, username: user.username }, 'jwt_secret', {
expiresIn: '1h',
});
return NextResponse.json({ token });
}
로그인 및 회원가입 페이지 작성
app/login/page.js
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export default function LoginPage() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const router = useRouter();
const handleSubmit = async (e) => {
e.preventDefault();
const res = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
if (res.ok) {
const data = await res.json();
localStorage.setItem('token', data.token);
router.push('/');
} else {
alert('Invalid credentials');
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
/>
<button type="submit">Login</button>
</form>
);
}
app/register/page.js
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export default function RegisterPage() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const router = useRouter();
const handleSubmit = async (e) => {
e.preventDefault();
const res = await fetch('/api/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ username, password }),
});
if (res.ok) {
const data = await res.json();
localStorage.setItem('token', data.token);
router.push('/');
} else {
alert('Registration failed');
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Username"
required
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
required
/>
<button type="submit">Register</button>
</form>
);
}
JWT 검증을 위한 미들웨어 작성
Next.js 14에서는 미들웨어를 사용하여 JWT를 검증할 수 있습니다.
middleware.js
import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';
export async function middleware(request) {
const token = request.headers.get('Authorization')?.split(' ')[1];
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
try {
jwt.verify(token, 'jwt_secret');
return NextResponse.next();
} catch (err) {
return NextResponse.redirect(new URL('/login', request.url));
}
}
export const config = {
matcher: ['/protected/*'],
};
로그인, 회원가입 페이지는 기본 디자인입니다. 최근에는 Next Auth 또는 Clerk와 같은 라이브러리를 사용하는 프로젝트가 많이 있습니다. JWT를 필요로 하는 서비스에서는 위 내용을 바탕으로 JWT를 구현할 수 있지만, 라이브러리를 사용해 빠르게 개발하는 것도 좋은 방법입니다.