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

25.블로그 포스트 작성 및 에디터 기능 추가, Next.js에 마크다운 에디터 추가하기

최근 몇 년간 블로그와 콘텐츠 관리 시스템에서 마크다운(Markdown)의 사용이 급증했습니다.
마크다운은 간편하고 직관적인 문법을 제공하여, 사용자가 텍스트를 쉽게 포맷할 수 있게 해줍니다.
이번 포스트에서는 Next.js를 기반으로 마크다운 에디터를 추가하는 방법에 대해 자세히 설명하겠습니다.
또한 블로그 포스트 작성 및 에디터 기능 추가에 필요한 기술 스택과 구성 요소에 대해서도 다룰 것입니다.

1. Next.js 개요

Next.js는 React 기반의 정적 웹사이트 및 서버 사이드 렌더링(SSR) 웹 애플리케이션을 구축하기 위한 프레임워크입니다.
Next.js는 SEO 친화적이며, 페이지 최적화 및 코드 스플리팅을 자동으로 처리하여 성능을 극대화합니다.
이외에도 API 라우팅, 이미지 최적화, 정적 생성 등 다양한 기능을 제공하여 개발자들이 생산성을 높일 수 있도록 돕습니다.

Next.js 설치 및 설정

Next.js 프로젝트를 시작하려면 Node.js 및 npm이 설치되어 있어야 합니다.
다음 명령어를 통해 Next.js 프로젝트를 생성할 수 있습니다.

npx create-next-app my-blog

2. 마크다운 및 마크다운 에디터

마크다운은 텍스트 기반의 경량 마크업 언어로, HTML과 유사한 형식을 사용하여 문서의 구조를 정의할 수 있습니다.
마크다운을 활용하면 블로그 글 작성 시 포맷팅이 간편하고 빠르게 진행될 수 있습니다.
이번 섹션에서는 간단한 마크다운 문서를 작성해 보겠습니다.

마크다운 예시


# 제목 1
## 제목 2
### 제목 3

이것은 두 번째 단락입니다.

- 리스트 항목 1
- 리스트 항목 2
- 리스트 항목 3

[링크 텍스트](http://example.com)

**강조된 텍스트**
    

3. Next.js에 마크다운 에디터 추가하기

Next.js 프로젝트에 마크다운 에디터를 추가하기 위해 여러 패키지를 설치하고 설정해야 합니다.
다음은 우리가 사용할 주요 패키지 목록입니다.

  • react-markdown: 마크다운을 React 컴포넌트로 변환합니다.
  • react-quill: WYSIWYG 마크다운 에디터를 제공합니다.
  • remark-gfm: GitHub 스타일 마크다운을 지원합니다.

패키지 설치

아래 명령어를 사용하여 필요한 패키지를 설치합니다.

npm install react-markdown react-quill remark-gfm

에디터 컴포넌트 만들기

React 컴포넌트를 사용하여 마크다운 에디터를 만들고, 이를 Next.js에 통합합니다.
components/MarkdownEditor.js라는 파일을 생성하고 다음 코드를 추가합니다.


import React, { useState } from 'react';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css'; // 스타일 추가

const MarkdownEditor = () => {
    const [text, setText] = useState('');

    return (
        

미리보기

); }; export default MarkdownEditor;

페이지에서 에디터 사용하기

이제 작성한 에디터 컴포넌트를 페이지에서 사용해 보겠습니다.
pages/index.js 파일에 아래의 코드를 추가합니다.


import MarkdownEditor from '../components/MarkdownEditor';

export default function Home() {
    return (
        

블로그 포스트 작성

); }

4. 마크다운 파일 저장 및 불러오기

작성한 내용은 어딘가에 저장되어야 합니다. 이번 섹션에서는 마크다운 파일을 저장하고 불러오는 로직을 구현합니다.
파일 시스템 모듈을 사용하여 만들 수 있습니다.

파일 시스템 사용하기


import fs from 'fs';
import path from 'path';

const filePath = path.join(process.cwd(), 'posts', 'my-post.md');

const savePost = (content) => {
    fs.writeFileSync(filePath, content);
};

const loadPost = () => {
    return fs.readFileSync(filePath, 'utf8');
};
    

요청 핸들러 구축하기

Next.js의 API 라우트를 사용하여 클라이언트와 서버 간의 데이터 요청을 처리할 수 있습니다.
pages/api/posts.js 파일을 생성하고 POST, GET 요청을 처리하는 코드를 추가합니다.


export default function handler(req, res) {
    if (req.method === 'POST') {
        savePost(req.body.content);
        res.status(200).json({ message: '포스트 저장 완료' });
    } else {
        const content = loadPost();
        res.status(200).json({ content });
    }
}
    

5. 전체 구현 예시

위의 모든 코드를 모아 완성된 블로그 포스트 작성기 에디터를 구현해보겠습니다. 최종 코드는 아래와 같습니다.


// components/MarkdownEditor.js
import React, { useState, useEffect } from 'react';
import ReactQuill from 'react-quill';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import 'react-quill/dist/quill.snow.css';

const MarkdownEditor = () => {
    const [text, setText] = useState('');

    useEffect(() => {
        const loadPost = async () => {
            const response = await fetch('/api/posts');
            const data = await response.json();
            setText(data.content);
        };

        loadPost();
    }, []);

    const savePost = async () => {
        await fetch('/api/posts', {
            method: 'POST',
            body: JSON.stringify({ content: text }),
            headers: {
                'Content-Type': 'application/json',
            },
        });
    };

    return (
        

미리보기

); }; export default MarkdownEditor; // pages/index.js import MarkdownEditor from '../components/MarkdownEditor'; export default function Home() { return (

블로그 포스트 작성

); } // pages/api/posts.js import fs from 'fs'; import path from 'path'; const filePath = path.join(process.cwd(), 'posts', 'my-post.md'); const savePost = (content) => { fs.writeFileSync(filePath, content); }; const loadPost = () => { return fs.readFileSync(filePath, 'utf8'); }; export default function handler(req, res) { if (req.method === 'POST') { savePost(req.body.content); res.status(200).json({ message: '포스트 저장 완료' }); } else { const content = loadPost(); res.status(200).json({ content }); } }

6. 마무리

이번 포스트에서는 Next.js를 기반으로 마크다운 에디터를 추가하는 방법에 대해 알아보았습니다.
간단한 WYSIWYG 에디터를 통해 블로그 포스트를 작성하고, 서버에 데이터를 저장하는 방법까지 다뤘습니다.
앞으로 추가적인 기능을 구현하여 더욱더 풍부한 블로그 작성 경험을 제공할 수 있습니다.
Next.js의 애드온을 사용하여 자신만의 블로그 플랫폼을 만들어 보세요!

28.이미지 업로드 및 미디어 관리, Next.js와 Cloudinary, AWS S3 등을 이용한 이미지 업로드

현대 웹 애플리케이션에서 이미지 및 미디어는 필수적인 요소입니다. 사용자 경험을 높이고, 시각적인 요소를 강화하며, 브랜딩을 강화하는 데 중요한 역할을 합니다. 이미지 업로드와 관련된 기능을 구현하는 것은 많은 개발자들에게 도전 과제가 될 수 있습니다. 이번 포스팅에서는 Next.js와 함께 Cloudinary, AWS S3를 활용하여 이미지 업로드 및 미디어 관리하는 방법에 대해 자세히 다루어 보겠습니다.

1. 이미지 업로드의 중요성

이미지는 웹 페이지의 디자인에 큰 영향을 미치며, 콘텐츠를 시각적으로 풍부하게 만드는 데 기여합니다. 적절하게 관리되지 않은 이미지는 성능 저하, 느린 로딩 속도, 불필요한 서버 사용 등을 초래할 수 있습니다. 따라서 효율적인 이미지 업로드 및 관리는 매우 중요합니다.

2. Next.js 소개

Next.js는 React 기반의 서버 사이드 렌더링(SSR) 및 정적 웹 애플리케이션을 만들기 위한 프레임워크입니다. Next.js는 SEO 최적화, 빠른 페이지 로딩速度, 파일 기반 라우팅 등 다양한 장점을 제공합니다. 이러한 특성 덕분에 Next.js는 이미지 및 미디어 관리를 포함하는 복잡한 기능들을 쉽게 구현하는 데 유리한 도구입니다.

3. Cloudinary 및 AWS S3 소개

3.1 Cloudinary

Cloudinary는 클라우드 기반의 미디어 관리 플랫폼으로, 이미지 및 비디오의 업로드, 저장, 변환 및 처리 기능을 제공합니다. 개발자는 손쉽게 изображения тәжірибесін 개선할 수 있습니다. 특히 Cloudinary는 이미지 최적화, 자동 형식 변환 및 다양한 효과를 지원하여 빠르고 일관된 미디어 처리 경험을 제공합니다.

3.2 AWS S3

AWS S3(서비스)는 Amazon Web Services의 객체 스토리지 서비스로, 데이터를 안전하게 저장하고 검색하는 데 사용됩니다. AWS S3는 확장성이 뛰어나고 비용 효율적이며, 높은 내구성을 제공합니다. 특히 이미지 저장과 관리에 많은 개발자들이 포함하여, 장기적인 스토리지 솔루션으로 널리 사용되고 있습니다.

4. Next.js에서 이미지 업로드 구현하기

Next.js를 사용하여 이미지 업로드 기능을 구현하기 위해 각각 Cloudinary와 AWS S3를 사용하는 방법에 대해 살펴보겠습니다.

4.1 Cloudinary를 이용한 이미지 업로드

4.1.1 Cloudinary 계정 생성하기

먼저, Cloudinary에 회원가입하고 계정을 생성합니다. 계정을 생성하면 API 키와 API 비밀번호를 포함한 계정 정보를 확인할 수 있습니다. 이 정보는 Next.js 애플리케이션에서 Cloudinary API를 사용하여 이미지를 업로드하는 데 필요합니다.

4.1.2 Next.js 프로젝트 설정하기

Next.js 앱을 생성하고 필요한 패키지를 설치합니다.

npx create-next-app my-image-upload-app
cd my-image-upload-app
npm install cloudinary multer multer-storage-cloudinary

4.1.3 업로드 API 만들기

Next.js는 서버리스 기능을 제공하므로 API 라우트를 사용하여 이미지 업로드 API를 생성할 수 있습니다. pages/api/upload.js 파일을 생성하고 다음과 같이 구성합니다.

import { v2 as cloudinary } from 'cloudinary';
import multer from 'multer';
import { CloudinaryStorage } from 'multer-storage-cloudinary';

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});

const storage = new CloudinaryStorage({
  cloudinary: cloudinary,
  params: {
    folder: 'uploads',
    allowedFormats: ['jpg', 'png', 'jpeg', 'gif'],
  },
});

const upload = multer({ storage });

export default function handler(req, res) {
  upload.single('image')(req, res, () => {
    res.status(200).send(req.file);
  });
}

4.1.4 클라이언트에서 이미지 업로드하기

이제 클라이언트 측에서 이미지를 업로드하는 기능을 추가합니다. pages/index.js 파일을 수정하여 다음과 같이 작성합니다.

import { useState } from 'react';

export default function Home() {
  const [image, setImage] = useState(null);

  const handleImageChange = (event) => {
    setImage(event.target.files[0]);
  };

  const handleSubmit = async (event) => {
    event.preventDefault();
    const formData = new FormData();
    formData.append('image', image);

    const res = await fetch('/api/upload', {
      method: 'POST',
      body: formData,
    });
    const data = await res.json();
    console.log(data);
  };

  return (
    

이미지 업로드

); }

5. AWS S3를 이용한 이미지 업로드

5.1 AWS 계정 생성 및 S3 버킷 만들기

첫 번째 단계로 AWS에 계정을 생성하고 S3 버킷을 만들어야 합니다. 버킷을 만들고, 버킷 정책을 설정하여 파일 업로드에 대한 권한을 부여해야 합니다.

5.2 AWS SDK 설치

다음으로, AWS SDK를 설치합니다.

npm install aws-sdk multer multer-s3

5.3 S3 업로드 API 만들기

Cloudinary와 비슷하게 API 엔드포인트를 만들 수 있습니다. pages/api/upload-s3.js를 생성하고 다음과 같이 구성합니다.

import AWS from 'aws-sdk';
import multer from 'multer';
import multerS3 from 'multer-s3';

AWS.config.update({
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
  region: process.env.AWS_REGION,
});

const s3 = new AWS.S3();

const upload = multer({
  storage: multerS3({
    s3: s3,
    bucket: process.env.S3_BUCKET_NAME,
    acl: 'public-read',
    metadata: function (req, file, cb) {
      cb(null, { fieldName: file.fieldname });
    },
    key: function (req, file, cb) {
      cb(null, Date.now().toString() + '-' + file.originalname);
    },
  }),
});

export default function handler(req, res) {
  upload.single('image')(req, res, function (err) {
    if (err) {
      return res.status(500).send(err);
    }
    res.status(200).send(req.file);
  });
}

5.4 S3 클라이언트 업로드 구현하기

클라이언트에서 이미지 업로드를 구현하는 방법은 Cloudinary와 유사합니다. pages/index.js의 코드를 수정하여 S3 API를 사용할 수 있습니다.

import { useState } from 'react';

export default function Home() {
  const [image, setImage] = useState(null);

  const handleImageChange = (event) => {
    setImage(event.target.files[0]);
  };

  const handleUploadS3 = async (event) => {
    event.preventDefault();
    const formData = new FormData();
    formData.append('image', image);

    const res = await fetch('/api/upload-s3', {
      method: 'POST',
      body: formData,
    });
    const data = await res.json();
    console.log(data);
  };

  return (
    

이미지 업로드

); }

6. 이미지 리사이징 및 최적화

Cloudinary와 AWS S3를 이용한 업로드 외에도, 업로드된 이미지를 리사이즈하고 최적화하는 기능이 중요합니다. Cloudinary는 이러한 기능을 내장하고 있어 다양한 파라미터를 통해 이미지의 크기 및 품질을 자동으로 조정할 수 있습니다. AWS S3를 사용할 경우, 업로드 후 Lambda 함수를 이용해 이미지 최적화 작업을 진행할 수 있습니다.

7. 보안 고려사항

이미지 업로드 기능을 구현할 때는 보안 문제가 생길 수 있습니다. 파일 업로드 과정에서 악성 코드가 포함된 파일이 업로드될 수 있기 때문에, 파일 형식을 체크하고, 올바른 인증절차를 적용하는 것이 중요합니다. Cloudinary API와 AWS S3 모두 안전한 인증 방법을 제공합니다.

8. 결론

이번 포스팅에서는 Next.js와 Cloudinary, AWS S3를 이용하여 이미지 업로드 및 미디어 관리를 구현하는 방법에 대해 자세히 알아보았습니다. 이를 통해 웹 애플리케이션에 필요한 강력한 이미지 업로드 기능을 효과적으로 구축할 수 있습니다. 각 플랫폼의 장단점을 고려하여, 프로젝트에 가장 적합한 솔루션을 선택하시길 바랍니다.