18.Next.js와 Nest.js로 사용자 인증 구현하기, 클라이언트 측에서 JWT 인증 토큰 처리 방법

최근 웹 애플리케이션 개발에서 사용자 인증은 매우 중요한 요소입니다. 특히, 프로젝트 규모가 커질수록 보안과 사용자 관리의 필요성이 증가합니다. Nest.js와 Next.js는 각각 서버 및 클라이언트 사이드에서 강력한 기능을 제공하여 사용자의 인증을 보다 쉽게 구현할 수 있습니다. 이 게시물에서는 Nest.js를 백엔드로 사용하여 JWT(JSON Web Token)를 사용한 사용자 인증을 설정하고, Next.js 클라이언트에서 이 과정을 처리하는 방법에 대해 자세히 설명하겠습니다.

1. Nest.js 소개

Nest.js는 Node.js 환경에서 서버사이드 애플리케이션을 구축하는 데 사용되는 프레임워크로, Angular에서 영감을 받아 모듈화와 의존성 주입 기능을 제공합니다. Nest.js는 TypeScript로 작성되어 있어 정적 타입 검사와 더 나은 개발 경험을 제공합니다. 빠른 개발과 유지 관리, 높은 성능을 제공하며, RESTful API 및 GraphQL 서비스를 쉽게 구축할 수 있도록 도와줍니다.

2. Next.js 소개

Next.js는 React 프레임워크를 기반으로 하는 서버 사이드 렌더링(SSR) 및 정적 웹사이트 생성(SSG)을 가능하게 해주는 프레임워크입니다. Next.js는 페이지 기반 라우팅, API 라우팅, 정적 데이터 패칭, 빠른 빌드 속도 등 다양한 기능을 제공하여 리액트 애플리케이션을 만드는 개발자들에게 많은 사랑을 받고 있습니다. 클라이언트 측 사용자 인터페이스는 Next.js를 통해 효율적으로 관리할 수 있습니다.

3. JWT(Json Web Token) 소개

JWT는 클라이언트와 서버 간의 안전한 정보 전송을 위한 오픈 스탠다드(JSON Web Token)입니다. JWT는 JSON 객체로 구성되어 있으며, 이러한 정보는 디지털 서명을 통해 안전하게 보호됩니다. JWT를 사용하여 사용자의 인증 토큰을 생성하고 클라이언트 측에서 이를 저장하여 후속 요청 시 사용자 정보를 증명할 수 있습니다.

4. Nest.js에서 사용자 인증 구현하기

4.1 Nest.js 프로젝트 설정

먼저, Nest.js 프로젝트를 생성합니다. 아래 명령어를 사용하여 Nest CLI를 설치한 후 새로운 프로젝트를 생성합니다.

npm install -g @nestjs/cli
nest new project-name

이제 생성된 프로젝트 폴더로 이동하고 필요한 패키지를 추가합니다.

cd project-name
npm install @nestjs/jwt @nestjs/passport passport passport-jwt bcrypt

4.2 인증 모듈 및 서비스 생성

이제 사용자 인증을 위한 모듈과 서비스를 생성해야 합니다. 먼저, 사용자 인증과 관련된 기능을 구현할 AuthModule을 생성합니다.

nest g module auth
nest g service auth
nest g controller auth

4.3 사용자 엔티티 정의

사용자 정보를 저장할 엔티티를 정의합니다.

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({ unique: true })
    email: string;

    @Column()
    password: string;
}

4.4 JWT 생성 및 검증

이제 JWT를 생성하고 검증하는 방법을 설정합니다. AuthService에 다음 코드를 추가합니다.

import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { User } from './user.entity';

@Injectable()
export class AuthService {
    constructor(private jwtService: JwtService) {}

    async login(user: User) {
        const payload = { email: user.email, sub: user.id };
        return {
            access_token: this.jwtService.sign(payload),
        };
    }
}

4.5 로그인 API 구현

이제 클라이언트가 로그인할 수 있도록 로그인 API를 구현해 보겠습니다. AuthController에 로그인 메서드를 추가합니다.

import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';

@Controller('auth')
export class AuthController {
    constructor(private authService: AuthService) {}

    @Post('login')
    async login(@Body() loginDto: { email: string; password: string }) {
        // 실제로는 DB에서 사용자 확인 로직이 필요합니다.
        const user = { id: 1, email: loginDto.email }; 
        return this.authService.login(user);
    }
}

5. Next.js에서 클라이언트 인증 구현하기

5.1 Next.js 프로젝트 생성

Next.js 프로젝트를 생성하려면 다음 명령어를 실행합니다.

npx create-next-app@latest project-name

그 후 생성된 프로젝트 폴더로 이동합니다.

cd project-name

5.2 axios 설치

서버와 통신하기 위해 Axios를 설치합니다.

npm install axios

5.3 로그인 페이지 생성

로그인 기능을 구현할 로그인 페이지를 생성합니다. pages 폴더에 login.js를 만든 후 다음과 같이 구현합니다.

import axios from 'axios';
import { useState } from 'react';

const Login = () => {
    const [email, setEmail] = useState('');
    const [password, setPassword] = useState('');

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            const response = await axios.post('http://localhost:3000/auth/login', {
                email,
                password,
            });
            localStorage.setItem('token', response.data.access_token);
        } catch (error) {
            console.error('Login failed:', error);
        }
    };

    return (
        
setEmail(e.target.value)} /> setPassword(e.target.value)} />
); }; export default Login;

5.4 JWT 저장 및 클라이언트 인증 처리

로그인 후 받은 JWT를 로컬 스토리지에 저장합니다. 이렇게 해 놓으면 다른 API 요청 시 토큰을 포함시켜 사용자 인증을 수행할 수 있습니다. 이를 위해 API 요청을 보내는 Axios 인스턴스를 생성하고 해당 토큰을 포함시킵니다.

import axios from 'axios';

const axiosInstance = axios.create({
    baseURL: 'http://localhost:3000',
});

axiosInstance.interceptors.request.use((config) => {
    const token = localStorage.getItem('token');
    if (token) {
        config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
});

export default axiosInstance;

6. 결론

이번 포스트에서는 Nest.js와 Next.js를 사용하여 JWT 기반의 사용자 인증을 구현하는 방법을 살펴보았습니다. Nest.js는 강력한 서버 사이드 기능을 제공하며, Next.js는 클라이언트 측에서 사용자 인증을 처리하는 데 유용합니다. 이 조합은 현대 웹 애플리케이션에서 안전하고 효율적인 사용자 인증 시스템을 구축할 수 있게 해줍니다. 프로젝트 제작 시 이와 같은 인증 시스템을 반드시 구현하여 보안을 강화하는 것이 중요합니다.

미래의 어플리케이션에서는 사용자 경험을 향상시키고 보안을 강화하기 위해 다양한 인증 방법이 지속적으로 발전할 것입니다. 따라서, 최신의 인증 방식과 보안 정책을 이해하는 것이 중요합니다. 이 강좌가 여러분의 Nest.js와 Next.js 프로젝트에 도움이 되기를 바랍니다.

7. 참고 자료