27.블로그 포스트 작성 및 에디터 기능 추가, 서버에서 마크다운 파일을 HTML로 변환하여 렌더링

현대 웹 애플리케이션 개발에서 블로그 시스템은 많은 인기를 끌고 있습니다. 특히나 개인이 자신을 표현할 수 있는 공간으로 블로그는 매우 중요한 역할을 합니다. 이번 포스트에서는 Nest.js와 Next.js를 활용하여 블로그 포스트 작성 및 에디터 기능을 추가하는 방법에 대해 논의하고자 합니다.

1. 프로젝트 구성

Nest.js는 서버 사이드 프레임워크로, TypeScript로 작성되어 있으며, Next.js는 리액트 기반의 서버 사이드 렌더링(SSR) 프레임워크입니다. 이 두 프레임워크를 조합하여 효율적인 블로그 애플리케이션을 구현할 수 있습니다. 먼저, Nest.js를 사용하여 API 서버를 구축하고, Next.js로 클라이언트 애플리케이션을 만듭니다.

2. Nest.js API 서버 구축

Nest.js에서 API를 구축하는 기본적인 과정은 다음과 같습니다. 먼저, Nest.js CLI를 사용하여 프로젝트를 생성합니다.

npm i -g @nestjs/cli
nest new blog-server

생성된 프로젝트 폴더로 이동한 후, 필요한 패키지를 설치합니다. Markdown 파일을 처리하기 위해 `marked` 패키지를 사용할 것입니다.

npm install marked

다음으로, 포스트를 관리할 수 있는 기본적인 CRUD API를 만듭니다. `posts`라는 모듈을 생성합니다.

nest generate module posts
nest generate service posts
nest generate controller posts

2.1. 포스트 DTO(Data Transfer Object) 정의

포스트 데이터를 다루기 위해 DTO를 만듭니다. `create-post.dto.ts` 파일을 생성하고 아래와 같이 작성합니다.

import { IsString, IsNotEmpty } from 'class-validator';

        export class CreatePostDto {
            @IsString()
            @IsNotEmpty()
            title: string;

            @IsString()
            @IsNotEmpty()
            content: string;
        }

2.2. 서비스 구현

`posts.service.ts` 파일을 열고 포스트 데이터를 관리하는 메서드를 추가합니다. 여기서는 간단히 메모리에 데이터를 저장합니다.

import { Injectable } from '@nestjs/common';
        import { CreatePostDto } from './dto/create-post.dto';

        interface Post {
            id: number;
            title: string;
            content: string;
        }

        @Injectable()
        export class PostsService {
            private posts: Post[] = [];
            private idCounter = 1;

            create(postDto: CreatePostDto): Post {
                const newPost = {
                    id: this.idCounter++,
                    ...postDto,
                };
                this.posts.push(newPost);
                return newPost;
            }

            findAll(): Post[] {
                return this.posts;
            }

            findOne(id: number): Post {
                return this.posts.find(post => post.id === id);
            }
        }

2.3. 컨트롤러 구현

`posts.controller.ts` 파일을 열고 API 엔드포인트를 추가합니다. 포스트를 추가하고, 목록을 가져오는 기능을 구현합니다.

import { Controller, Post, Body, Get } from '@nestjs/common';
        import { PostsService } from './posts.service';
        import { CreatePostDto } from './dto/create-post.dto';

        @Controller('posts')
        export class PostsController {
            constructor(private readonly postsService: PostsService) {}

            @Post()
            create(@Body() postDto: CreatePostDto) {
                return this.postsService.create(postDto);
            }

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

3. 클라이언트 애플리케이션 Next.js 구축

이제 Next.js를 사용하여 블로그 클라이언트를 구축하겠습니다. 새로운 Next.js 프로젝트를 생성합니다.

npx create-next-app blog-client

클라이언트 애플리케이션에서도 Markdown 파일을 사용하기 위해 `remark` 패키지를 설치합니다.

npm install remark remark-html

3.1. 포스트 작성 페이지

포스트를 작성할 수 있는 페이지를 만들어야 합니다. `pages/create-post.js` 파일을 생성하고 아래와 같이 작성합니다.

import { useState } from 'react';

        export default function CreatePost() {
            const [title, setTitle] = useState('');
            const [content, setContent] = useState('');

            const handleSubmit = async (e) => {
                e.preventDefault();
                const response = await fetch('http://localhost:3000/posts', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({ title, content }),
                });
                if (response.ok) {
                    alert('포스트가 성공적으로 작성되었습니다.');
                }
            };

            return (
                
setTitle(e.target.value)} required />
); }

4. 마크다운 처리 및 HTML 렌더링

사용자가 작성한 마크다운 내용을 HTML로 변환하여 렌더링하는 기능을 추가해야 합니다. 이 과정에서 `remark`와 `remark-html`을 사용하여 마크다운을 HTML로 변환합니다.

4.1. Markdown to HTML 변환 구현

포스트를 조회하는 페이지를 만들어 HTML로 변환된 내용을 렌더링합니다. `pages/posts/[id].js` 파일을 생성하고 아래와 같이 작성합니다.

import { useEffect, useState } from 'react';
        import { remark } from 'remark';
        import html from 'remark-html';

        const Post = ({ post }) => {
            const [contentHtml, setContentHtml] = useState('');

            useEffect(() => {
                const convertMarkdownToHtml = async () => {
                    const processedContent = await remark()
                        .use(html)
                        .process(post.content);
                    setContentHtml(processedContent.toString());
                };
                convertMarkdownToHtml();
            }, [post.content]);

            return (
                

{post.title}

); }; export async function getServerSideProps(context) { const { id } = context.params; const res = await fetch(`http://localhost:3000/posts/${id}`); const post = await res.json(); return { props: { post } }; } export default Post;

5. 전체 흐름 정리

이제 사용자가 블로그 포스트를 작성하고, 이를 마크다운 형식으로 저장하고, 이후 이를 HTML로 변환하여 렌더링할 수 있는 전체적인 기능을 갖춘 시스템이 완성되었습니다. Nest.js는 백엔드에서 포스트를 저장하고 관리하며, Next.js는 클라이언트에서 포스트 작성과 내용을 표시하는 역할을 합니다. 이러한 시스템 구성은 개발의 유연성을 높여주며, 유지보수 또한 쉽게 만들어줍니다.

6. 결론

블로그 포스트 작성 및 에디터 기능을 추가하는 과정에서 Nest.js와 Next.js를 활용한 다양한 예제를 살펴보았습니다. 마크다운을 HTML로 변환하는 과정은 블로그 개발에서 매우 중요한 부분이며, 이를 통해 사용자에게 더 나은 콘텐츠를 제공할 수 있습니다. 앞으로 자신만의 블로그를 구축하는 데 있어 Nest.js와 Next.js를 적극 활용해보세요!

저자: 조광형

게시일: 2024년 11월 26일

6.Next.js와 Nest.js 기본 프로젝트 구조 만들기, Next.js의 페이지와 Nest.js의 모듈 구성하기

JavaScript 생태계에서 Next.js와 Nest.js는 각각 프론트엔드와 백엔드 개발에 혁신적인 접근 방식을 제공합니다. Next.js는 React 기반의 프레임워크로, 서버 사이드 렌더링(SSR)과 정적 웹 사이트 생성을 간편하게 처리할 수 있도록 도와줍니다. 반면, Nest.js는 Node.js의 기반 위에 구축된 프로그레시브한 백엔드 프레임워크로, 모듈화와 클래스 기반의 아키텍처를 강조합니다. 본 강좌에서는 Next.js와 Nest.js의 기본 프로젝트 구조를 만드는 방법과 각각의 페이지 및 모듈 구성하는 방법에 대해 자세히 알아보겠습니다.

1. Next.js 프로젝트 구조 이해하기

Next.js 프로젝트는 일반적으로 다음과 같은 구조를 가집니다:

    my-next-app/
    ├── public/
    ├── pages/
    ├── components/
    ├── styles/
    ├── package.json
    └── next.config.js
    

여기서 각 디렉토리와 파일의 역할은 다음과 같습니다:

  • public/: 정적 파일(이미지, 아이콘 등)을 저장하는 디렉토리입니다. 이곳에 있는 파일은 “/” 경로로 접근할 수 있습니다.
  • pages/: Next.js에서 가장 중요한 디렉토리로, 애플리케이션의 각 페이지를 정의합니다. 파일 이름이 URL 경로에 직접적으로 매핑됩니다. 예를 들어, pages/index.js는 루트 페이지(/)를 나타냅니다.
  • components/: 여러 페이지에서 재사용할 수 있는 React 컴포넌트들을 저장하는 디렉토리입니다.
  • styles/: CSS 파일이나 스타일 관련 모듈을 여기에 보관합니다. Next.js는 CSS와 Sass를 지원합니다.
  • package.json: 프로젝트의 메타데이터와 의존성을 정의합니다.
  • next.config.js: Next.js의 다양한 설정을 구성할 수 있는 파일입니다.

2. Nest.js 프로젝트 구조 이해하기

Nest.js 프로젝트는 다음과 같은 구조를 가집니다:

    my-nest-app/
    ├── src/
    │   ├── app.module.ts
    │   ├── main.ts
    │   └── /
    │       ├── .module.ts
    │       ├── .controller.ts
    │       └── .service.ts
    ├── test/
    ├── package.json
    └── tsconfig.json
    

각 디렉토리와 파일의 역할은 다음과 같습니다:

  • src/: 애플리케이션의 모든 소스 코드를 포함합니다. Nest.js의 핵심 로직이 여기에 위치합니다.
  • app.module.ts: 애플리케이션의 루트 모듈입니다. 모든 모듈을 조합하는 역할을 합니다.
  • main.ts: 애플리케이션의 진입점으로, Nest.js 서버를 시작하는 파일입니다.
  • /: 특정 모듈을 위한 디렉토리입니다. 각 모듈은 controller, service 및 다른 관련 파일들을 포함할 수 있습니다.
  • test/: 테스트 관련 파일을 저장하는 디렉토리입니다.
  • package.json: 프로젝트의 메타데이터와 의존성을 정의합니다.
  • tsconfig.json: TypeScript 컴파일러 설정 파일입니다.

3. Next.js 프로젝트 만들기

먼저 Next.js 프로젝트를 만듭니다. 터미널에서 다음 명령어를 실행하세요:

npx create-next-app my-next-app

이 명령어는 Next.js의 템플릿을 기반으로 새로운 프로젝트를 생성합니다. 생성된 my-next-app 디렉토리로 이동한 후 실행하면 기본 Next.js 애플리케이션을 확인할 수 있습니다:

cd my-next-app
npm run dev

브라우저를 열고 http://localhost:3000에 접속하면 기본 페이지를 확인할 수 있습니다.

4. Nest.js 프로젝트 만들기

Nest.js 프로젝트를 생성하기 위해 Nest CLI를 사용합니다. 먼저 Nest CLI를 설치합니다:

npm i -g @nestjs/cli

설치가 완료되면 새로운 Nest.js 프로젝트를 생성합니다:

nest new my-nest-app

생성된 my-nest-app 디렉토리로 이동하여 서버를 실행합니다:

cd my-nest-app
npm run start

브라우저를 열고 http://localhost:3000에 접속하면 기본 Nest.js 애플리케이션을 확인할 수 있습니다.

5. Next.js의 페이지 구성하기

Next.js에서 페이지를 구성하기 위해 pages/ 디렉토리에 새로운 JavaScript 파일을 추가합니다. 예를 들어, pages/about.js를 생성하고 다음 코드를 작성합니다:

import React from 'react';

    const About = () => {
        return (
            

About Us

이곳은 우리의 소개 페이지입니다.

); }; export default About;

웹 브라우저에서 http://localhost:3000/about를 열면 방금 작성한 소개 페이지를 확인할 수 있습니다. Next.js는 파일 기반 라우팅을 지원하기 때문에, 다른 페이지를 추가하는 것도 매우 쉬운 작업입니다.

6. Nest.js의 모듈 구성하기

Nest.js에서는 모듈을 통해 애플리케이션을 구성합니다. 예를 들어, ‘users’ 모듈을 생성하고 구성하는 방법을 보겠습니다. 터미널에서 다음 명령어를 실행하여 모듈을 생성합니다:

nest generate module users
nest generate controller users
nest generate service users

이 명령어는 src/users/ 디렉토리를 생성하고, 사용자 관리에 필요한 서비스 및 컨트롤러를 자동으로 생성합니다. src/users/users.module.ts 파일을 다음과 같이 수정합니다:

import { Module } from '@nestjs/common';
    import { UsersController } from './users.controller';
    import { UsersService } from './users.service';

    @Module({
        controllers: [UsersController],
        providers: [UsersService],
    })
    export class UsersModule {}

이제 src/users/users.controller.tssrc/users/users.service.ts 파일을 수정하여 컨트롤러와 서비스의 로직을 추가할 수 있습니다. 아래는 사용자 목록을 반환하는 간단한 서비스와 컨트롤러의 예입니다.

import { Controller, Get } from '@nestjs/common';
    import { UsersService } from './users.service';

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

        @Get()
        getAllUsers() {
            return this.usersService.findAll();
        }
    }
    
import { Injectable } from '@nestjs/common';

    @Injectable()
    export class UsersService {
        private readonly users = ['Alice', 'Bob', 'Charlie'];

        findAll() {
            return this.users;
        }
    }
    

위의 코드를 바탕으로 Nest.js 애플리케이션에서 사용자 목록을 반환하는 API를 구성할 수 있습니다. 브라우저에서 http://localhost:3000/users에 접속하면 사용자 목록을 확인할 수 있습니다.

7. Next.js와 Nest.js를 함께 사용하기

Next.js와 Nest.js를 함께 사용하여 풀스택 애플리케이션을 구축할 수 있습니다. 이러한 구조에서는 Next.js가 프론트엔드 부분을 담당하고, Nest.js가 백엔드 API를 제공하는 역할을 수행합니다. 다음 단계에서는 두 애플리케이션이 서로 통신할 수 있도록 설정합니다.

7.1. Nest.js API 서버 설정

먼저 Nest.js 애플리케이션을 다음과 같이 설정하여 CORS를 활성화합니다:

import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';

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

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

Next.js 애플리케이션에서 Nest.js API를 호출하려면 데이터 패칭을 위해 axios와 같은 라이브러리를 사용할 수 있습니다. pages/index.js 파일을 다음과 같이 수정합니다:

import React, { useEffect, useState } from 'react';
    import axios from 'axios';

    const Home = () => {
        const [users, setUsers] = useState([]);

        useEffect(() => {
            const fetchUsers = async () => {
                const response = await axios.get('http://localhost:3000/users');
                setUsers(response.data);
            };
            fetchUsers();
        }, []);

        return (
            

사용자 목록

    {users.map(user => (
  • {user}
  • ))}
); }; export default Home;

이제 Next.js 애플리케이션의 홈 페이지에서 Nest.js API를 통해 사용자 목록을 가져오는 기능이 추가되었습니다.

8. 결론

Next.js와 Nest.js를 함께 사용하여 풀스택 애플리케이션을 구축하는 방법에 대해 살펴보았습니다. 각 프레임워크의 프로젝트 구조와 구성 방법을 이해하고, 두 애플리케이션 간의 데이터 통신을 설정하는 과정을 통해, 여러분은 효율적이고 강력한 애플리케이션을 개발할 수 있습니다.

이번 강좌를 통해 Next.js와 Nest.js의 기본적인 사용법뿐만 아니라, 실제로 프로젝트를 설정하고 페이지 및 모듈을 구성하는 방법을 배웠습니다. 앞으로 이 두 기술을 바탕으로 더욱 발전된 애플리케이션을 만들어보시기를 바랍니다.

17.Next.js와 Nest.js로 사용자 인증 구현하기, 로그인, 로그아웃, 회원가입 API 만들기

웹 개발에서 사용자 인증은 필수적인 요소입니다. 사용자가 안전하게 시스템에 접근할 수 있도록 하고, 개인정보를 보호하는 것이 매우 중요하다. 이번 강좌에서는 Next.js와 Nest.js를 사용하여 사용자 인증을 구현하는 방법을 자세히 살펴보겠습니다.

1. 프로젝트 설정

사용자 인증 시스템을 구현하기 위해 두 가지 프레임워크인 Next.js와 Nest.js를 사용할 것입니다. Next.js는 프론트엔드 프레임워크로 서버 사이드 렌더링(SSR)과 정적 웹사이트 생성을 지원합니다. 반면 Nest.js는 Node.js 기반의 백엔드 프레임워크로, 현대적인 서버 애플리케이션을 구축하는 데 적합합니다.

1.1 Nest.js 초기 설정

npm i -g @nestjs/cli
nest new backend
cd backend
npm install @nestjs/passport passport passport-local @types/passport-local bcrypt @types/bcrypt
npm install --save @nestjs/jwt passport-jwt @types/passport-jwt

1.2 Next.js 초기 설정

npx create-next-app frontend
cd frontend
npm install axios

2. Nest.js에서 사용자 인증 API 구현

Nest.js에서는 사용자 인증을 구현하기 위해 Passport.js와 JWT(JSON Web Token)를 사용할 것입니다.

2.1 User 엔티티 생성

먼저 User 엔티티를 생성합니다. 다음은 user.entity.ts 파일의 코드입니다.

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

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

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

    @Column()
    password: string;
}

2.2 UserService 및 UserModule 생성

import { Injectable } from '@nestjs/common';
import { User } from './user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';

@Injectable()
export class UserService {
    constructor(
        @InjectRepository(User)
        private userRepository: Repository,
    ) {}

    async create(userDto: { email: string; password: string }): Promise {
        const hashedPassword = await bcrypt.hash(userDto.password, 10);
        const user = this.userRepository.create({ ...userDto, password: hashedPassword });
        return this.userRepository.save(user);
    }

    async findByEmail(email: string): Promise {
        return this.userRepository.findOne({ where: { email } });
    }
}

2.3 AuthModule 및 AuthService 생성

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from './auth.service';
import { LocalStrategy } from './local.strategy';
import { UsersModule } from '../users/users.module';

@Module({
    imports: [
        UsersModule,
        PassportModule,
        JwtModule.register({
            secret: 'SECRET_KEY', // 비밀키 설정
            signOptions: { expiresIn: '60s' }, // 토큰 유효 시간 설정
        }),
    ],
    providers: [AuthService, LocalStrategy],
})
export class AuthModule {}

2.4 로그인 및 회원가입 API 엔드포인트 추가

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

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

    @Post('register')
    async register(@Body() userDto: { email: string; password: string }) {
        return this.authService.register(userDto);
    }

    @Post('login')
    async login(@Body() userDto: { email: string; password: string }) {
        return this.authService.login(userDto);
    }
}

3. Next.js의 사용자 인증 UI 구현하기

Next.js에서는 사용자 인증을 위한 로그인 및 회원가입 폼을 구현합니다. 사용자 입력을 처리하여 Nest.js 백엔드로 요청을 보내도록 합니다.

3.1 로그인 페이지 구현

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

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

    const handleSubmit = async (e) => {
        e.preventDefault();
        const response = await axios.post('/api/auth/login', { email, password });
        // 로그인 성공 시 처리
    };

    return (
        
setEmail(e.target.value)} placeholder="Email" /> setPassword(e.target.value)} placeholder="Password" />
); }; export default Login;

3.2 회원가입 페이지 구현

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

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

    const handleSubmit = async (e) => {
        e.preventDefault();
        const response = await axios.post('/api/auth/register', { email, password });
        // 회원가입 성공 시 처리
    };

    return (
        
setEmail(e.target.value)} placeholder="Email" /> setPassword(e.target.value)} placeholder="Password" />
); }; export default Register;

4. 사용자 인증 상태 관리

로그인 이후에는 사용자의 인증 상태를 관리해야 합니다. Next.js에서는 Context API 또는 Redux와 같은 상태 관리 라이브러리를 활용할 수 있습니다.

4.1 Context API를 사용한 상태 관리

import { createContext, useContext, useState } from 'react';

const AuthContext = createContext();

export const AuthProvider = ({ children }) => {
    const [user, setUser] = useState(null);
    const login = (userData) => setUser(userData);
    const logout = () => setUser(null);

    return (
        
            {children}
        
    );
};

export const useAuth = () => useContext(AuthContext);

5. 마무리

이번 강좌에서는 Next.js와 Nest.js를 사용하여 사용자 인증 시스템을 구현하는 방법을 살펴보았습니다. 우리는 로그인, 회원가입, 로그아웃 API를 생성하고 프론트엔드에서는 사용자 인터페이스를 구성했습니다.

사용자 인증은 웹 애플리케이션에서 매우 중요한 기능입니다. 이를 통해 사용자의 개인정보와 데이터 안전성을 높일 수 있습니다. 추가적으로 JWT를 사용하여 인증 상태를 유지하고, Refresh Token과 같은 기능을 구현하면 더욱 안전한 인증 시스템을 만들 수 있습니다.

앞으로 이 시스템에 추가할 수 있는 기능들로는 비밀번호 찾기, OAuth 인증(구글, 페이스북 등), 사용자 권한 관리 등이 있습니다. 이러한 기능들을 통해 더 강력하고 유용한 인증 시스템으로 발전시킬 수 있습니다.

15.Next.js와 Nest.js 연동하여 데이터 가져오기, 블로그 목록 페이지와 상세 페이지에 데이터 연결하기

이번 글에서는 Next.jsNest.js를 활용하여 블로그 목록 페이지와 상세 페이지에 데이터를 연동하는 방법에 대해 자세히 알아보겠습니다. Next.js는 React 기반의 프레임워크로, 서버 사이드 렌더링과 정적 사이트 생성을 지원하여 최적의 성능을 자랑합니다. Nest.js는 Node.js 애플리케이션을 위한 강력한 프레임워크로, 특히 RESTful API 개발에 적합합니다. 이 두 프레임워크를 결합하여 효율적인 웹 애플리케이션을 만들 수 있습니다.

1. 프로젝트 구조 설정

먼저, 두 프레임워크를 연동할 프로젝트 구조를 설정합니다. Nest.js를 백엔드 API 서버로, Next.js를 프론트엔드 웹 애플리케이션으로 사용할 것입니다.

  • 프로젝트 루트 폴더
    • nest-backend/
    • next-frontend/

1.1 Nest.js 프로젝트 생성

먼저, Nest.js 프로젝트를 생성합니다. Nest CLI를 사용하여 새로운 프로젝트를 생성하고 의존성을 설치합니다.

            
            npm install -g @nestjs/cli
            nest new nest-backend
            cd nest-backend
            npm install @nestjs/typeorm typeorm mysql2
            
            

여기서는 MySQL을 데이터베이스로 사용하였지만, 필요한 경우 다른 데이터베이스를 사용할 수도 있습니다.

1.2 Next.js 프로젝트 생성

그 다음, Next.js 프로젝트를 생성합니다. create-next-app을 사용하여 빠르게 설정할 수 있습니다.

            
            npx create-next-app next-frontend
            cd next-frontend
            npm install axios
            
            

axios는 클라이언트에서 API를 호출할 때 사용할 라이브러리입니다.

2. Nest.js API 구축

Nest.js를 사용하여 블로그 API를 구축합니다. 블로그 포스트를 다루기 위해 Post 엔티티를 생성하고, CRUD 기능을 구현합니다.

2.1 Post 엔티티 생성

Nest.js의 TypeORM을 사용하여 Post 엔티티를 생성합니다. src/posts/post.entity.ts 파일을 생성하고 다음과 같이 작성합니다:

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

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

                @Column()
                title: string;

                @Column('text')
                content: string;

                @Column()
                createdAt: Date;

                @Column()
                updatedAt: Date;
            }
            
        

2.2 Posts 모듈 및 서비스 생성

Posts 모듈을 생성하고 CRUD 로직을 추가합니다. src/posts/posts.module.tssrc/posts/posts.service.ts 파일을 각각 생성합니다.

            
            import { Module } from '@nestjs/common';
            import { TypeOrmModule } from '@nestjs/typeorm';
            import { PostsController } from './posts.controller';
            import { PostsService } from './posts.service';
            import { Post } from './post.entity';

            @Module({
                imports: [TypeOrmModule.forFeature([Post])],
                controllers: [PostsController],
                providers: [PostsService],
            })
            export class PostsModule {}
            
        

2.3 Posts Controller 생성

PostsController를 생성하여 API 엔드포인트를 정의합니다. src/posts/posts.controller.ts 파일을 다음과 같이 작성합니다:

            
            import { Controller, Get, Post, Body, Param } from '@nestjs/common';
            import { PostsService } from './posts.service';
            import { Post } from './post.entity';

            @Controller('posts')
            export class PostsController {
                constructor(private readonly postsService: PostsService) {}

                @Get()
                async findAll(): Promise {
                    return this.postsService.findAll();
                }

                @Get(':id')
                async findOne(@Param('id') id: string): Promise {
                    return this.postsService.findOne(+id);
                }

                @Post()
                async create(@Body() post: Post): Promise {
                    return this.postsService.create(post);
                }
            }
            
        

2.4 Posts Service 구현하기

최종적으로, PostsService를 구현하여 데이터베이스와의 상호작용을 처리합니다. src/posts/posts.service.ts 파일을 다음과 같이 작성합니다:

            
            import { Injectable } from '@nestjs/common';
            import { InjectRepository } from '@nestjs/typeorm';
            import { Repository } from 'typeorm';
            import { Post } from './post.entity';

            @Injectable()
            export class PostsService {
                constructor(
                    @InjectRepository(Post)
                    private postsRepository: Repository,
                ) {}

                async findAll(): Promise {
                    return this.postsRepository.find();
                }

                async findOne(id: number): Promise {
                    return this.postsRepository.findOne(id);
                }

                async create(post: Post): Promise {
                    return this.postsRepository.save(post);
                }
            }
            
        

3. Next.js와 API 연동하기

이제 Next.js 애플리케이션에서 Nest.js API를 호출하여 데이터를 가져오고 페이지에 렌더링합니다. 블로그 목록 페이지와 상세 페이지를 구현해 보겠습니다.

3.1 블로그 목록 페이지 생성

블로그 목록 페이지를 생성하여 모든 포스트를 표시합니다. pages/index.js 파일을 다음과 같이 수정합니다:

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

            const Home = () => {
                const [posts, setPosts] = useState([]);

                useEffect(() => {
                    const fetchData = async () => {
                        const result = await axios('http://localhost:3000/posts');
                        setPosts(result.data);
                    };
                    fetchData();
                }, []);

                return (
                    

블로그 목록

); }; export default Home;

3.2 블로그 상세 페이지 생성

각 포스트의 상세 정보를 보여주기 위해 블로그 상세 페이지를 생성합니다. pages/post/[id].js 파일을 생성하고 다음과 같이 작성합니다:

            
            import { useRouter } from 'next/router';
            import { useEffect, useState } from 'react';
            import axios from 'axios';

            const PostDetail = () => {
                const router = useRouter();
                const { id } = router.query;
                const [post, setPost] = useState(null);

                useEffect(() => {
                    if (id) {
                        const fetchData = async () => {
                            const result = await axios(`http://localhost:3000/posts/${id}`);
                            setPost(result.data);
                        };
                        fetchData();
                    }
                }, [id]);

                if (!post) return 

Loading...

; return (

{post.title}

{post.content}

); }; export default PostDetail;

4. 결론

이번 글에서는 Next.js와 Nest.js를 연동하여 블로그 앱을 만드는 과정을 안내했습니다. Nest.js를 통해 API 서버를 구축하고, Next.js를 사용하여 클라이언트 사이드에서 데이터를 가져와서 렌더링하는 방법을 배웠습니다. 이 과정을 통해 두 프레임워크의 특성을 이해하고, 실전에 어떻게 활용할 수 있는지에 대한 통찰을 얻을 수 있었기를 바랍니다.

여기서 소개한 방법은 기본적인 예제에 불과하며, 실제 프로젝트에서는 좀 더 복잡한 상태 관리, 에러 처리, 팬던시 구현 등을 고려해야 합니다. 여러분의 프로젝트에 맞게 다양한 기능을 추가하고 발전시켜 나가십시오.

32.다국어 지원 및 로컬라이제이션, Nest.js에서 언어별 데이터 처리하기

현대 웹 애플리케이션에서 다국어 지원 및 로컬라이제이션은 매우 중요한 요소입니다. 여러 언어를 지원함으로써, 비즈니스는 더 넓은 시장을 대상으로 서비스를 제공하고, 사용자 경험을 개선할 수 있습니다. 이 글에서는 Nest.js를 사용하여 언어별 데이터 처리를 구현하는 방법에 대해 자세히 설명하겠습니다.

1. 다국어 지원의 필요성

다국어 지원은 기업이 다양한 문화적 배경을 가진 사용자에게 서비스를 제공하는 데 도움을 줍니다. 다음과 같은 이유로 다국어 지원이 필요합니다:

  • 글로벌 시장 접근성: 다국적 기업들이 자신의 서비스를 다양한 언어로 제공함으로써, 전 세계의 사용자들에게 접근할 수 있습니다.
  • 사용자 경험 향상: 사용자가 익숙한 언어로 서비스를 사용할 수 있어, 더 나은 사용자 경험을 제공합니다.
  • 문화적 민감성: 언어 지원은 다양한 문화적 특성과 사용자의 기대를 이해하고 대응할 수 있는 방법 중 하나입니다.

2. Nest.js 소개

Nest.js는 최신 JavaScript 및 TypeScript를 사용하여 구축된 서버 측 애플리케이션 프레임워크입니다. 강력한 타입 지원과 모듈화된 구조로 구성되어 있어, 유지보수하기 쉽고 확장성이 뛰어난 애플리케이션을 개발할 수 있습니다. Nest.js는 Express 또는 Fastify를 기반으로 하며, 이를 통해 고성능 웹 애플리케이션을 구성할 수 있습니다.

3. Nest.js에서 다국어 지원 구현하기

3.1. 필요 라이브러리 설치

다국어 처리를 위해 i18n 라이브러리를 사용할 것입니다. 다음 명령어로 설치할 수 있습니다:

npm install i18n

3.2. i18n 설정하기

Nest.js 애플리케이션에서 i18n을 설정하려면, 먼저 생성한 애플리케이션의 메인 파일인 main.ts에 다음과 같이 코드를 추가합니다.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as i18n from 'i18n'; 

async function bootstrap() {
    i18n.configure({
        locales: ['en', 'ko', 'ja'], // 지원할 언어 목록
        directory: __dirname + '/locales', // 번역 파일이 위치할 디렉토리
        defaultLocale: 'ko', // 기본 언어
        autoReload: true, // 코드 변경 시 리로딩 여부
        syncFiles: true // 동기화 여부
    });

    const app = await NestFactory.create(AppModule);
    app.use(i18n.init); // i18n 초기화
    await app.listen(3000);
}
bootstrap();

3.3. 언어별 데이터 준비

각 언어에 대한 번역 문자열을 별도의 JSON 파일로 생성합니다. locales 디렉토리를 생성하고 그 안에 en.json, ko.json, ja.json 파일을 만듭니다. 예를 들어:

// locales/ko.json
{
    "greeting": "안녕하세요",
    "farewell": "안녕히 가세요"
}
// locales/en.json
{
    "greeting": "Hello",
    "farewell": "Goodbye"
}
// locales/ja.json
{
    "greeting": "こんにちは",
    "farewell": "さようなら"
}

3.4. 언어 결정 및 사용하기

클라이언트가 요청한 언어에 따라 적절한 번역을 사용하기 위해, 요청 헤더나 쿼리 매개변수를 통해 언어를 결정할 수 있습니다. 다음과 같이 컨트롤러를 작성하여 다국어 지원을 구현할 수 있습니다:

import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller('greet')
export class GreetController {
    @Get()
    getGreeting(@Req() req: Request): string {
        return req.__('greeting'); // 요청에 따른 인사말 반환
    }
}

4. 클라이언트에서 언어 선택하기

클라이언트 측에서는 사용자가 선호하는 언어를 선택할 수 있는 인터페이스를 제공합니다. 예를 들어, Next.js 프레임워크를 사용하여 사용자가 선택한 언어에 따라 요청을 보낼 수 있습니다.

4.1. Next.js 클라이언트 작성하기

Next.js에서 페이지를 생성하고 언어 선택 버튼을 만든 후, 사용자가 언어를 변경할 수 있도록 로직을 구현합니다. 아래는 언어 선택 버튼이 포함된 간단한 페이지 예제입니다:

import { useState } from 'react';

const LanguageSelector = () => {
    const [language, setLanguage] = useState('ko');

    const changeLanguage = (lang) => {
        setLanguage(lang);
        // 서버 요청 보내기
        fetch(`http://localhost:3000/greet?lang=${lang}`)
            .then(response => response.text())
            .then(data => alert(data));
    }

    return (
        

언어 선택

); }; export default LanguageSelector;

5. 결론

Nest.js를 사용하여 다국어 지원 및 로컬라이제이션 기능을 구현하는 과정은 복잡할 수도 있으나, 필요한 도구와 설정을 통해 쉽게 할 수 있습니다. 위의 내용에서는 i18n 라이브러리를 통해 다양한 언어를 지원하는 방법과 클라이언트에서 언어를 선택할 수 있는 간단한 인터페이스를 구현하는 방법을 설명했습니다. 이를 통해 사용자 경험을 향상시키고 글로벌 시장에 접근하는 데 도움이 되는 웹 애플리케이션을 개발할 수 있습니다.

앞으로 더 많은 기능과 사용자 친화적인 인터페이스를 추가하여, 다국어 지원을 더욱 강화할 수 있습니다. 독자 여러분의 프로젝트에도 다국어 지원을 성공적으로 적용하시길 바랍니다!