3.Next.js와 Nest.js 개요와 환경 설정, Next.js와 Nest.js를 함께 사용해야 하는 이유

웹 개발의 최신 트렌드는 프론트엔드와 백엔드 기술 스택 간의 통합으로, 이를 통해 보다 일관되고 효율적인 애플리케이션 개발이 가능합니다. 특히, React 기반의 프레임워크인 Next.js와 Node.js 기반의 프레임워크인 Nest.js는 이러한 통합을 돕는 강력한 도구입니다. 본 글에서는 Next.js와 Nest.js에 대한 개요, 환경 설정 방법, 그리고 이를 함께 사용해야 하는 이유를 자세히 설명하겠습니다.

Next.js 개요

Next.js는 React 애플리케이션을 구축하기 위한 프레임워크입니다. Vercel에서 개발한 이 프레임워크는 서버사이드 렌더링(SSR), 정적 사이트 생성(SSG), API 라우팅 및 빠른 코드 분할과 같은 기능을 제공합니다. 이를 통해 개발자는 SEO에 최적화되어 있고 빠른 웹 애플리케이션을 쉽게 만들 수 있습니다.

Next.js의 주요 특징

  • 서버사이드 렌더링(SSR): 서버에서 페이지를 미리 렌더링하여 사용자에게 HTML을 전달, 초기 로딩 속도를 개선.
  • 정적 사이트 생성(SSG): 빌드 시 미리 페이지를 생성하여 정적 파일로 제공, 빠른 응답 속도를 보장.
  • API 라우트: 서버리스 API를 쉽게 생성하여 외부 데이터와의 통신 지원.
  • 자동 코드 분할: 페이지별로 필요한 코드만 로드하여 성능을 최적화함.

Nest.js 개요

Nest.js는 TypeScript로 작성된 Node.js 웹 프레임워크로, 강력한 아키텍처와 모듈 시스템을 제공합니다. Angular에서 영감을 받아 만들어졌으며, 응집력 있는 개발 패턴을 통해 대규모 애플리케이션을 쉽게 관리할 수 있습니다. Nest.js는 Express.js를 기본으로 하거나 Fastify와 같은 다른 프레임워크를 사용할 수 있는 유연성을 제공합니다.

Nest.js의 주요 특징

  • 모듈화: 애플리케이션을 모듈 단위로 구성하여 각 모듈을 독립적으로 관리 가능.
  • 의존성 주입: 서비스 간의 의존성을 관리하여 테스트 용이성과 코드 재사용성을 향상시킴.
  • 유연한 미들웨어 시스템: 다양한 미들웨어를 사용하여 요청 및 응답 처리 가능.
  • RESTful API 및 GraphQL 지원: RESTful API와 GraphQL 엔드포인트를 쉽고 빠르게 구축 가능.

환경 설정

Next.js 환경 설정

Next.js 프로젝트를 설정하기 위해서는 Node.js와 npm이 필요합니다. 다음은 Next.js 프로젝트를 설정하는 단계입니다:

npx create-next-app@latest my-next-app

위 명령어를 실행하면 my-next-app이라는 이름의 새로운 Next.js 프로젝트가 생성됩니다. 생성된 디렉토리로 이동하여 프로젝트를 실행합니다.

cd my-next-app
npm run dev

Nest.js 환경 설정

Nest.js 프로젝트를 설정하기 위해서는 Nest CLI가 필요합니다. Nest CLI를 사용하면 효율적으로 Nest.js 애플리케이션을 생성 및 관리할 수 있습니다. 다음은 Nest.js 프로젝트를 설정하는 단계입니다:

npm i -g @nestjs/cli
nest new my-nest-app

위 명령어를 통해 my-nest-app이라는 이름의 새로운 Nest.js 프로젝트를 생성합니다. 생성된 디렉토리로 이동하여 서버를 실행합니다.

cd my-nest-app
npm run start

Next.js와 Nest.js를 함께 사용해야 하는 이유

Next.js와 Nest.js를 함께 사용하는 것은 여러가지 장점이 있습니다. 이 두 프레임워크를 결합함으로써 얻을 수 있는 주요 이점은 다음과 같습니다:

1. 효율적인 풀스택 개발

Next.js는 프론트엔드 개발을 위한 최적의 선택이자, Nest.js는 확장 가능한 백엔드 아키텍처를 제공합니다. 이 두 프레임워크를 함께 사용하면 클라이언트와 서버 간의 원활한 통신이 이루어지고, 코드의 일관성을 유지하기 쉽습니다.

2. 서버사이드 렌더링과 API 통합

Next.js는 SSR을 통해 웹 페이지를 사용자에게 빠르게 로드할 수 있는 반면, Nest.js는 백엔드에서 API를 통한 데이터 처리를 담당합니다. 이러한 통합은 개발자가 클라이언트 사이드와 서버 사이드에서 더욱 원활하게 작업할 수 있도록 도와줍니다.

3. 통합된 인증 및 권한 관리

Next.js와 Nest.js를 함께 사용하면 사용자 인증 및 권한 관리를 효율적으로 구현할 수 있습니다. Nest.js에서 JWT(Json Web Token)를 사용해 인증을 처리하고, Next.js에서 이를 관리함으로써 보안성을 높일 수 있습니다.

4. 코드 공유와 재사용성

TypeScript를 사용하여 두 프레임워크 모두에서 코드 품질과 재사용성을 높일 수 있습니다. 공통 모듈이나 유틸리티 함수를 작성하여 Next.js와 Nest.js 간에 재사용함으로써 개발 효율성을 극대화할 수 있습니다.

5. 커뮤니티 지원과 생태계

Next.js와 Nest.js는 각각의 강력한 커뮤니티와 생태계를 가지고 있습니다. 이를 통해 다양한 리소스, 라이브러리 및 툴을 활용하여 프로젝트를 보다 효과적으로 진행할 수 있습니다. 또한 문서화가 잘 되어 있어 문제 해결에도 유용합니다.

결론

Next.js와 Nest.js는 웹 애플리케이션 개발에 있어 강력하고 효율적인 조합입니다. 프론트엔드와 백엔드 두 측면에서 각각의 역할을 충실히 수행하며, 그 결합을 통해 고품질의 애플리케이션을 개발할 수 있습니다. 이 글에서는 두 프레임워크에 대한 개요와 환경 설정, 그리고 함께 사용해야 하는 이유를 살펴보았습니다. 앞으로의 웹 개발에서 이 두 가지 툴을 적극적으로 사용해 보시기를 권장합니다.

43.Next.js와 Nest.js에서 API 캐싱과 성능 최적화, Redis를 사용한 캐싱 처리와 성능 개선

현대 웹 애플리케이션에서 성능은 사용자 경험을 결정짓는 핵심 요소 중 하나입니다. 이러한 성능을 개선하기 위한 여러 가지 방법 중 API 캐싱은 매우 중요한 역할을 합니다. 이번 글에서는 Next.js와 Nest.js를 활용한 웹 애플리케이션에서 API 캐싱을 어떻게 구현할 수 있는지, 그리고 Redis를 사용하여 성능을 개선하는 방법에 대해 자세히 다루겠습니다.

1. API 캐싱의 필요성

API 호출은 네트워크를 통해 데이터를 가져오기 때문에 상대적으로 시간이 걸리는 작업입니다. 이를 최소화하기 위해 API 호출 결과를 캐싱하면, 동일한 데이터를 여러 번 요청할 필요가 없어져 성능을 대폭 향상시킬 수 있습니다.

  • 서버 부하 감소: 데이터베이스나 외부 API에 대한 요청이 줄어듭니다.
  • 응답 시간 단축: 캐시된 데이터를 메모리에서 즉시 반환할 수 있습니다.
  • 스케일링 용이: 높은 트래픽을 효율적으로 처리할 수 있습니다.

2. Next.js와 API 캐싱

Next.js는 React 기반의 프레임워크로 서버 측 렌더링(SSR)과 정적 사이트 생성(SSG)을 지원합니다. API 요청에 대한 캐싱은 클라이언트 측에서도, 서버 측에서도 가능합니다.

2.1 클라이언트 측의 데이터 패칭

Next.js에서는 getStaticPropsgetServerSideProps를 사용하여 데이터를 패칭합니다. 이를 통해 SSR이나 SSG를 활용하여 데이터를 캐싱할 수 있습니다. 아래의 코드는 getStaticProps를 사용하는 예시입니다.

export async function getStaticProps() {
    const res = await fetch('https://api.example.com/data');
    const data = await res.json();

    return {
        props: { data }, // 데이터를 props로 전달
        revalidate: 60, // 60초마다 데이터 재검증
    };
}

위의 예에서는 60초마다 API를 재검증하므로, 일정 시간 동안엔 캐시된 데이터를 사용하게 됩니다.

2.2 서버 측 API 캐싱

Next.js API Routes를 이용하여 서버 측에서 API를 호출하고 캐싱할 수 있습니다. 이 경우 Redis와 같은 인메모리 데이터베이스를 활용하면 성능을 더욱 개선할 수 있습니다.

import Redis from 'ioredis';

const redis = new Redis();

export default async function handler(req, res) {
    const cacheKey = 'my-data';

    // Redis에서 데이터 가져오기
    const cachedData = await redis.get(cacheKey);
    if (cachedData) {
        return res.status(200).json(JSON.parse(cachedData));
    }

    // 캐시 미스 시 API 호출
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();

    // 데이터 캐싱
    await redis.set(cacheKey, JSON.stringify(data), 'EX', 60); // 60초 동안 캐싱

    return res.status(200).json(data);
}

위의 코드는 클라이언트가 API를 요청할 때 Redis에서 먼저 캐시된 데이터를 확인하고, 캐시가 없을 경우 API를 호출하여 데이터를 가져온 후 캐시합니다.

3. Nest.js와 API 캐싱

Nest.js는 Express 기반의 프레임워크로, API 서버를 구축할 때 여러 모듈과 데코레이터를 사용하여 구조화된 코드를 작성할 수 있습니다. Nest.js에서도 Redis를 이용한 API 캐싱을 쉽게 구현할 수 있습니다.

3.1 Redis 모듈 설치

먼저 Redis 클라이언트를 설치합니다. 아래의 명령어로 설치해 주세요.

npm install --save redis ioredis

3.2 캐싱을 위한 서비스 생성

Nest.js에서는 서비스를 생성하여 Redis와의 인터페이스를 관리할 수 있습니다.

import { Injectable, Cacheable, CachePut } from '@nestjs/common';
import { Redis } from 'ioredis';

@Injectable()
export class CacheService {
    private redis: Redis;

    constructor() {
        this.redis = new Redis();
    }

    async getCache(key: string) {
        const data = await this.redis.get(key);
        return data ? JSON.parse(data) : null;
    }

    async setCache(key: string, value: any, expiration: number) {
        await this.redis.set(key, JSON.stringify(value), 'EX', expiration);
    }
}

위의 CacheService 클래스는 Redis에서 데이터를 가져오고 설정하는 메서드를 제공합니다.

3.3 캐싱을 적용한 컨트롤러

컨트롤러에서 서비스를 이용하여 캐싱을 구현할 수 있습니다.

import { Controller, Get } from '@nestjs/common';
import { CacheService } from './cache.service';

@Controller('data')
export class DataController {
    constructor(private readonly cacheService: CacheService) {}

    @Get()
    async getData() {
        const cacheKey = 'api:data';
        
        // 캐시에서 데이터 확인
        const cachedData = await this.cacheService.getCache(cacheKey);
        if (cachedData) {
            return cachedData;
        }

        // 캐시 미스 시 API 호출
        const response = await fetch('https://api.example.com/data');
        const data = await response.json();

        // 데이터 캐싱
        await this.cacheService.setCache(cacheKey, data, 60); // 60초 동안 캐싱

        return data;
    }
}

위의 예에서는 Nest.js 컨트롤러에서 API 요청을 처리하고, Redis를 통해 캐싱을 관리하고 있습니다.

4. Redis를 활용한 성능 개선

Redis는 인메모리 데이터베이스로 매우 빠른 데이터 읽기와 쓰기 속도를 제공합니다. 또한, 데이터 구조가 다양하여 여러 형태의 데이터를 쉽게 관리할 수 있습니다. 이에 따라 Redis를 사용하여 성능을 최적화하는 방법에 대해 살펴보겠습니다.

4.1 데이터 구조

Redis는 문자열, 해시, 리스트, 셋 등 다양한 데이터 구조를 지원합니다. 적절한 데이터 구조를 선택하여 캐시 성능을 최적화할 수 있습니다.

  • 문자열: 간단한 캐싱에 적합합니다.
  • 해시: 객체 형태의 데이터를 저장할 때 유용합니다.
  • 리스트: 정렬된 데이터 목록을 관리할 때 좋습니다.
  • 셋: 중복되지 않는 데이터를 저장하는 데 유리합니다.

4.2 TTL(Time-To-Live) 설정

캐시된 데이터의 생명 주기를 설정하는 것은 매우 중요합니다. TTL을 사용하여 더 이상 필요하지 않은 캐시 데이터를 자동으로 제거할 수 있습니다. 이는 메모리 사용량을 줄이고, 오래된 데이터를 사용하지 않도록 도와줍니다.

4.3 캐싱 전략

효율적인 캐싱 전략을 수립하는 것이 중요합니다. 다음과 같은 기본적인 캐싱 전략을 고려해 볼 수 있습니다.

  • 정적 캐싱: 변화가 적은 데이터에 대해 캐싱합니다.
  • 동적 캐싱: 주기적으로 업데이트되는 데이터를 캐싱합니다.
  • 부분 캐싱: 전체 데이터를 가져오지 않고 필요한 부분만 캐싱합니다.

5. 결론

Next.js와 Nest.js를 활용하여 API 캐싱과 성능 최적화를 구현하는 방법을 알아보았습니다. Redis를 이용한 캐싱 처리는 빠른 데이터 접근과 높은 성능을 보장합니다. 따라서, 애플리케이션의 구조에 맞는 적절한 캐싱 전략을 수립하는 것이 중요합니다. 최적화된 API를 통해 사용자에게 쾌적한 경험을 제공할 수 있습니다.

이제 여러분은 Next.js와 Nest.js에서 API 캐싱을 구현하고 Redis를 사용하여 성능을 개선하는 방법을 충분히 이해하게 되었습니다. 이 글을 통해 웹 애플리케이션의 성능 최적화에 큰 도움을 받을 수 있기를 바랍니다.

11.Nest.js로 RESTful API 구축하기, Nest.js에서 컨트롤러와 서비스 구현하기

현대 웹 개발에서 RESTful API는 데이터와 서비스를 클라이언트와 서버 간에 효과적으로 공유하는 데 필수적입니다. Nest.js는 Node.js 기반의 웹 애플리케이션 프레임워크로, 확장성과 유지보수성을 고려하여 설계되었습니다. 이 글에서는
Nest.js를 사용하여 RESTful API를 구축하는 방법에 대해 자세히 알아보겠습니다. 또한, API의 기본을 이해하기 위해 컨트롤러와 서비스의 구현 방법에 대해서도 살펴보겠습니다.

1. Nest.js 소개

Nest.js는 TypeScript로 작성된 프레임워크로, Angular에서 영감을 얻어 모듈화된 구조를 갖추고 있습니다. Nest.js의 주요 장점 중 하나는 의존성 주입(Dependency Injection)을 통해 코드의 재사용성과 테스트 용이성을 높일 수 있다는 점입니다.
이를 통해 대규모 애플리케이션을 체계적으로 설계하고 관리할 수 있습니다.

2. Nest.js 설치 및 초기 설정

Nest.js를 설치하기 위해 Node.js가 필요합니다. Node.js가 설치된 후, Nest CLI를 통해 빠르게 프로젝트를 생성할 수 있습니다. CLI 도구를 설치하려면, 다음 명령어를 실행합니다:


            npm install -g @nestjs/cli
        

Nest CLI를 설치한 후, 새로운 Nest.js 프로젝트를 생성하는 명령어는 다음과 같습니다:


            nest new my-nest-app
        

생성된 프로젝트 디렉토리로 이동하고 다음 명령어로 개발 서버를 실행합니다:


            cd my-nest-app
            npm run start
        

3. RESTful API의 개념

REST(Representational State Transfer)는 클라이언트와 서버 간의 데이터 교환을 위한 아키텍처 스타일입니다. RESTful API는 주로 HTTP 프로토콜을 사용하여 CRUD(Create, Read, Update, Delete) 작업을 수행합니다.
RESTful API의 주요 특징은 상태를 유지하지 않으며, 모든 요청에 대해 클라이언트가 필요한 정보를 제공해야 한다는 점입니다.

4. Nest.js에서 RESTful API 만들기

이제 실제로 RESTful API를 구축해봅시다. 여기서는 간단한 “투두(Todo)” 리스트 애플리케이션을 예로 들겠습니다. 이 애플리케이션은 사용자가 투두 항목을 추가하고, 조회하고, 수정하고, 삭제할 수 있는 API를 제공합니다.

4.1. Todo 모듈 생성

먼저, Todo 모듈을 생성합니다. 터미널에서 다음 명령어를 입력하여 Todo 모듈을 생성합니다:


            nest generate module todo
        

4.2. Todo 서비스 생성

Todo 서비스를 생성하여 비즈니스 로직을 처리합니다. 다음 명령어를 입력합니다:


            nest generate service todo
        

서비스 파일은 todo.service.ts라는 이름으로 생성됩니다. 다음은 TodoService의 기본 코드입니다:


            import { Injectable } from '@nestjs/common';
            import { Todo } from './todo.entity';

            @Injectable()
            export class TodoService {
                private todos: Todo[] = [];

                findAll(): Todo[] {
                    return this.todos;
                }

                create(todo: Todo): Todo {
                    this.todos.push(todo);
                    return todo;
                }
                
                // Todo 항목 수정 및 삭제 메서드 추가
            }
        

4.3. Todo 컨트롤러 생성

이제 컨트롤러를 생성하여 사용자 요청을 처리합니다. 다음 명령어를 입력합니다:


            nest generate controller todo
        

컨트롤러 파일은 todo.controller.ts라는 이름으로 생성됩니다. 이 파일에 RESTful API의 엔드포인트를 정의합니다:


            import { Controller, Get, Post, Body } from '@nestjs/common';
            import { TodoService } from './todo.service';
            import { Todo } from './todo.entity';

            @Controller('todos')
            export class TodoController {
                constructor(private readonly todoService: TodoService) {}

                @Get()
                findAll(): Todo[] {
                    return this.todoService.findAll();
                }

                @Post()
                create(@Body() todo: Todo): Todo {
                    return this.todoService.create(todo);
                }
                
                // 추가적인 엔드포인트 구현
            }
        

4.4. Todo 엔티티 생성

이제 Todo의 구조를 정의하는 엔티티를 생성합니다. todo.entity.ts라는 파일을 생성하고 아래와 같이 작성합니다:


            export class Todo {
                id: number;
                title: string;
                completed: boolean;
            }
        

4.5. 모듈 통합

마지막으로 todo.module.ts 파일에 서비스와 컨트롤러를 통합합니다:


            import { Module } from '@nestjs/common';
            import { TodoController } from './todo.controller';
            import { TodoService } from './todo.service';

            @Module({
                controllers: [TodoController],
                providers: [TodoService],
            })
            export class TodoModule {}
        

5. 애플리케이션 실행 및 테스트

이제 모든 구현을 완료했습니다. 터미널에서 애플리케이션을 실행하면, 기본적으로 http://localhost:3000/todos에서 API에 접근할 수 있습니다.
Postman이나 Curl 등의 도구를 사용하여 API의 엔드포인트를 테스트해볼 수 있습니다.

5.1. Todo 항목 추가하기

POST 요청을 통해 투두 항목을 추가할 수 있습니다.
예를 들어, 아래와 같은 JSON 형식으로 요청을 보낼 수 있습니다:


            {
                "id": 1,
                "title": "첫 번째 투두",
                "completed": false
            }
        

5.2. Todo 항목 조회하기

GET 요청을 통해 모든 투두 항목을 조회할 수 있습니다.
http://localhost:3000/todos로 GET 요청을 보내면, 추가한 투두 항목 전체 목록을 확인할 수 있습니다.

6. 결론

이번 글에서는 Nest.js를 활용하여 RESTful API를 구축하는 방법에 대해 알아보았습니다. Nest.js는 강력하고 유연한 구조를 제공하여 대규모 애플리케이션 개발에 적합합니다.
컨트롤러와 서비스의 패턴을 통해 비즈니스 로직과 HTTP 요청 처리를 분리하여 코드의 가독성과 유지보수성을 높일 수 있습니다.
더욱 다양한 사용 사례와 고급 기능에 대해 공부하면서 Nest.js의 매력을 더 깊이 발견할 수 있기를 바랍니다.

작성자: 조광형

날짜: 2024년 11월 26일

14.Next.js와 Nest.js 연동하여 데이터 가져오기, Nest.js API와 프론트엔드의 통신 구조 이해

프론트엔드와 백엔드 개발의 통합은 현대 웹 애플리케이션 개발의 중요한 요소 중 하나입니다. 본 글에서는 Next.js와 Nest.js를 사용하여 데이터 가져오기와 API 통신 구조에 대해 깊이 있는 설명을 제공합니다.

1. Next.js와 Nest.js 소개

Next.js는 React 기반의 프레임워크로, 서버 사이드 렌더링(SSR) 및 정적 사이트 생성을 지원합니다. 이로 인해 SEO 최적화 및 빠른 페이지 로딩 속도를 구현할 수 있습니다. 반면, Nest.js는 TypeScript 기반의 백엔드 프레임워크로, 모듈화 및 테스트 용이성을 중시하는 구조를 가지고 있습니다. 이 두 프레임워크의 결합은 강력한 풀스택 개발 환경을 만들어냅니다.

2. Nest.js API 생성하기

Nest.js를 사용하여 RESTful API를 생성하는 과정은 다음과 같습니다.

2.1 Nest.js 설치

우선 Nest.js를 설치합니다. 터미널에서 다음 명령어를 실행합니다:
npm i -g @nestjs/cli
그 후 새로운 프로젝트를 생성합니다:
nest new project-name

2.2 컨트롤러 및 서비스 생성

API의 기본 구성 요소로서 컨트롤러와 서비스를 생성합니다. 예를 들어, 사용자 데이터를 가져오는 API를 추가합니다. 터미널에서 다음 명령어를 실행합니다:
nest generate controller users
nest generate service users

2.3 비즈니스 로직 구현

users.service.ts 파일에서 간단한 메모리 기반의 사용자 데이터를 추가합니다:

class UsersService {
    private users = [
        { id: 1, name: 'John Doe' },
        { id: 2, name: 'Jane Doe' },
    ];

    findAll() {
        return this.users;
    }
}
                

2.4 API Route 설정

users.controller.ts 파일을 수정하여 GET 요청을 처리합니다:

@Controller('users')
export class UsersController {
    constructor(private readonly usersService: UsersService) {}

    @Get()
    findAll() {
        return this.usersService.findAll();
    }
}
                

2.5 Nest.js 서버 실행

모든 설정이 완료되면 Nest.js 서버를 실행합니다:
npm run start
이로써 API 서버가 http://localhost:3000/users에서 실행됩니다.

3. Next.js에서 API 호출하기

이제 Next.js를 사용하여 Nest.js에서 만든 API로부터 데이터를 가져오는 과정을 설명합니다.

3.1 Next.js 설치

새로운 Next.js 프로젝트를 생성합니다. 터미널에서 다음 명령어를 실행합니다:
npx create-next-app client

3.2 API 호출 구현

Next.js의 페이지 인터페이스에서 Nest.js API를 호출합니다. pages/index.js 파일을 수정하여 데이터를 가져옵니다:

import { useEffect, useState } from 'react';

export default function Home() {
    const [users, setUsers] = useState([]);

    useEffect(() => {
        fetch('http://localhost:3000/users')
            .then(response => response.json())
            .then(data => setUsers(data));
    }, []);

    return (
        

사용자 목록

    {users.map(user => (
  • {user.name}
  • ))}
); }

3.3 CORS 설정

Nest.js와 Next.js가 서로 다른 포트를 사용하기 때문에 CORS 설정이 필요합니다. main.ts 파일을 수정하여 CORS를 허용합니다:

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    app.enableCors();
    await app.listen(3000);
}
                

4. 데이터 통신 구조 이해하기

Next.js와 Nest.js 간의 데이터 통신 구조는 클라이언트-서버 아키텍처에 기반합니다. 클라이언트는 사용자 요청을 생성하고, 서버는 요청을 처리하여 응답을 반환합니다. 이 과정에서 API 요청 시 발생하는 데이터를 어떻게 관리할지에 대한 고민이 필요합니다.

4.1 상태 관리

Next.js에서 데이터의 상태 관리에는 React의 상태 관리 훅을 사용할 수 있으며, 이외에도 Redux나 Zustand와 같은 외부 상태 관리 라이브러리를 활용할 수 있습니다.

4.2 응답 구조 설계

API의 응답 구조도 고려해야 합니다. 예를 들어, 클라이언트에서 데이터를 구분하기 쉽도록 응답 시 각 데이터에 대한 메타 정보를 포함시켜 구현할 수 있습니다.

5. 결론

Next.js와 Nest.js의 조합은 현대 웹 애플리케이션 개발에 매우 강력한 도구입니다. 두 프레임워크를 통합하면 SEO 최적화 및 모듈화된 코드 베이스를 유지하면서도 효율적인 데이터 통신 구조를 설계할 수 있습니다. 이 글을 통해 기본적인 데이터 가져오기와 API 통신 구조에 대한 이해를 돕고자 했습니다. 지속적인 학습을 통해 보다 깊이 있는 통합 개발을 경험하시길 바랍니다.

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. 참고 자료