티스토리 뷰

반응형

🚀 FastAPI 기반 로컬 LLM + RAG 챗봇 – 4.1.1 JWT 기반 인증 방식

이번 글에서는 JWT(JSON Web Token) 기반 인증 방식의 개념과 구조, 그리고 Next.js에서 JWT를 활용하는 방법을 다룹니다.
JWT의 기본 개념을 이해하고, Access Token과 Refresh Token의 차이를 학습합니다.
Next.js API Route에서 JWT 인증을 구현하는 방법을 실습합니다.


📌 1. JWT란?

✅ 1.1 JWT 개념 및 구조

JWT(JSON Web Token)는 토큰 기반 인증 방식으로, 클라이언트와 서버 간 인증 정보를 안전하게 주고받을 수 있도록 설계되었습니다.

📌 JWT는 3가지 주요 구성 요소로 이루어져 있습니다.

Header.Payload.Signature

예제 JWT 토큰:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEyMywiZXhwIjoxNjg2NzI2MDAwfQ.9m2nH0qyxm1t0lKf9Ow3K4BZc2YnTzF7T8wMxBHY8lA

각 부분의 역할은 다음과 같습니다.

구성 요소 설명

Header 토큰의 타입(JWT) 및 암호화 알고리즘 (HS256, RS256 등)
Payload 사용자 ID, 권한, 토큰 만료 시간(exp) 등 포함
Signature 토큰의 위변조 방지를 위한 서명

JWT는 서버에서 클라이언트에게 발급한 후, 클라이언트가 API 요청 시 포함하여 인증을 수행하는 방식입니다. 🚀


📌 2. Access Token vs Refresh Token

JWT를 활용한 인증에서는 Access TokenRefresh Token을 구분하여 사용합니다.

구분 설명 만료 시간 저장 위치

Access Token API 요청 시 사용되는 인증 토큰 짧음 (5~30분) 메모리 or HTTP Only 쿠키
Refresh Token Access Token이 만료되었을 때 재발급하는 토큰 김 (7일~30일) 데이터베이스 or Secure Cookie

Access Token은 보안상 짧은 유효 기간을 가지며, Refresh Token을 활용하여 갱신합니다. 🚀


📌 3. Next.js에서 JWT 인증 구현하기

반응형

✅ 3.1 JWT 토큰 생성하기

📌 Step 1: JWT 라이브러리 설치

npm install jsonwebtoken bcryptjs

📌 Step 2: JWT 유틸리티 함수 생성 (app/utils/jwt.ts)

import jwt from "jsonwebtoken";

const SECRET_KEY = process.env.JWT_SECRET || "your_secret_key";

export const generateToken = (userId: string) => {
  return jwt.sign({ userId }, SECRET_KEY, { expiresIn: "15m" });
};

export const verifyToken = (token: string) => {
  try {
    return jwt.verify(token, SECRET_KEY);
  } catch (error) {
    return null;
  }
};

이제 JWT를 생성하고 검증하는 기능을 구현했습니다! 🚀


✅ 3.2 Next.js API Route에서 JWT 로그인 구현

📌 app/api/auth/login/route.ts (로그인 시 JWT 발급)

import { NextResponse } from "next/server";
import { generateToken } from "@/app/utils/jwt";

export async function POST(req: Request) {
  const { username, password } = await req.json();

  // (실제 서비스에서는 데이터베이스에서 사용자 검증 필요)
  if (username !== "admin" || password !== "1234") {
    return NextResponse.json({ error: "Invalid credentials" }, { status: 401 });
  }

  const token = generateToken(username);
  return NextResponse.json({ token });
}

이제 /api/auth/login 엔드포인트를 통해 JWT를 발급할 수 있습니다! 🚀


✅ 3.3 Next.js API Route에서 JWT 검증하기

📌 app/api/protected/route.ts (JWT 검증 및 보호된 API)

import { NextResponse } from "next/server";
import { verifyToken } from "@/app/utils/jwt";

export async function GET(req: Request) {
  const authHeader = req.headers.get("authorization");

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const token = authHeader.split(" ")[1];
  const decoded = verifyToken(token);

  if (!decoded) {
    return NextResponse.json({ error: "Invalid token" }, { status: 403 });
  }

  return NextResponse.json({ message: "Protected data", user: decoded });
}

이제 /api/protected 엔드포인트를 호출하면 JWT 인증을 거쳐야 합니다! 🚀


✅ 3.4 클라이언트에서 JWT 로그인 요청하기

📌 app/components/Login.tsx (JWT 로그인 요청)

"use client";

import { useState } from "react";

export default function Login() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [token, setToken] = useState("");

  const handleLogin = async () => {
    const res = await fetch("/api/auth/login", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ username, password }),
    });

    const data = await res.json();
    if (res.ok) {
      setToken(data.token);
      alert("로그인 성공! 토큰이 저장되었습니다.");
    } else {
      alert("로그인 실패: " + data.error);
    }
  };

  return (
    <div>
      <input type="text" placeholder="Username" onChange={(e) => setUsername(e.target.value)} />
      <input type="password" placeholder="Password" onChange={(e) => setPassword(e.target.value)} />
      <button onClick={handleLogin}>로그인</button>
      {token && <p>발급된 JWT: {token}</p>}
    </div>
  );
}

이제 클라이언트에서 로그인 요청을 보내면 JWT를 받아 인증할 수 있습니다! 🚀


📌 4. JWT 보안 강화 Best Practices

  • HTTP Only 쿠키 사용 → 클라이언트에서 직접 접근할 수 없도록 설정
  • Refresh Token을 활용한 자동 재발급 → Access Token이 만료되었을 때 새로운 토큰 발급
  • JWT 서명 키를 안전하게 관리 (.env 파일 사용)
  • JWT 토큰의 유효 기간을 짧게 설정 (15~30분)
  • OAuth와 조합하여 보안 강화 (Google, GitHub 로그인)

📌 5. 결론 및 다음 단계

JWT의 개념과 구조를 학습했습니다.
Access Token과 Refresh Token의 차이를 이해했습니다.
Next.js API Route에서 JWT 인증을 구현하고, 클라이언트에서 로그인 요청하는 방법을 실습했습니다.
보안을 강화하기 위한 Best Practices를 정리했습니다.

🚀 다음 글에서는 "4.1.2 NextAuth.js를 활용한 OAuth 로그인"을 진행합니다!

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함
반응형