Seongwon Lim

[node.js] Typescript 기반 라우터 적용하는 법 본문

Node.js

[node.js] Typescript 기반 라우터 적용하는 법

limsw 2022. 5. 8. 16:02
반응형

서론

이전 포스팅 글에서는 index.ts 파일에서 User 테이블에 CRUD를 하는 미들웨어를 모두 구현했었다. 그러나 실제 프로젝트를 진행하는 경우 테이블의 개수가 더욱 많아지고 프로젝트 구조는 더욱 복잡해진다. 따라서 우리는 프로젝트를 진행할 때 테이블(혹은 기능)별로 파일을 분리하는 습관을 가져야 한다.

 

그래서 이번 포스팅 글에서는 자바스크립트와 달리 타입스크립트 환경에서는 어떻게 라우팅을 하는지 간단하게 알아보고자 한다.

 

  • 시리즈 1,2 내용에서 다룬 내용을 기반으로 진행하는 내용이므로 개발환경 설정이 되지 않은 분들은 시리즈1시리즈2를 참고하면 좋을 것 같다.
  • 또한 타입스크립트 기반이 아닌 Javascript + Express 기반 라우팅 사용법을 알아보고자 하는 분들은 여기를 참고하면 좋을 것 같다.

파일 구조 수정하기

기능 별로 파일을 분리하기 위해 src 디렉토리 안에 routes 디렉토리를 생성했다.

typeorm-example
├── src
│   ├── entity
│   │   └── User.ts
│   ├── migration
│   ├── routes (새로 추가된 디렉토리)
│   └── index.ts
├── node_modules
├── ormconfig.js
├── package-lock.json
├── package.json
├── README.md
├── .gitignore
└── tsconfig.json

다음으로는 이전에 구현한 User 테이블을 CRUD하는 4개의 미들웨어를 분리하기 위해 routes 디렉토리 안에 uesr.ts 라는 파일을 생성했다. 다시 src 디렉토리 구조를 살펴보면 다음과 같다.

src
 ├── entity
 │   └── User.ts
 ├── migration
 ├── routes (새로 추가된 디렉토리)
 │   └── user.ts (새로 추가된 파일)
 └── index.ts

user.ts 파일 정의하기

파일을 정의하기 전에 먼저 자바스크립트 기반에서 라우팅을 정의했을 때에는 다음과 같이 코드를 정의할 수 있었다.

const express = require('express');
const router = express.Router();

router.get('', (req, res, next) => {
    res.send("Hello world");
});

module.exports = router;

이런 식으로 익스프레스의 Routing() 메서드를 가져와서 module.exports = ... 형태로 정의했다.

타입스크립트의 경우에는 다음과 같이 라우팅을 정의한다.

import express, { Request, Response, NextFunction } from 'express';


const router = express.Router();

router.get('', async (req: Request, res: Response, next: NextFunction) => {
  res.send("Hello world");
});

export = router;

자바스크립트 코드와 거의 유사하지만 모듈을 가져오는 방법과 export하는 부분에서 약간의 차이가 있는 것을 확인할 수 있다.

이제 User Entity 파일을 가져와서 index.ts 파일에서 정의했던 CRUD 미들웨어를 해당 파일에서 다시 정의해보았다. user.ts 전체 코드는 다음과 같다.

import express, { Request, Response, NextFunction } from 'express';
import { User } from "../entity/User";

const router = express.Router();

router.get('/', async (req: Request, res: Response, next: NextFunction) => {
    const users = await User.find();
    res.send(users);
});

router.post('/', async (req: Request, res: Response, next: NextFunction) => {
   const user = new User();

   const {
        firstName,
        lastName,
        age
   } = req.body;
   
   user.firstName = firstName;
   user.lastName = lastName;
   user.age = age;

   await user.save().then((user) => {
       res.status(201).send(user);
   })
   .catch((err) => {
        res.status(400).send(err);
   });
});

router.patch('/', async (req: Request, res: Response, next: NextFunction) => {
    await User.update({
        id: 1,
    }, {
        age: 30,
    }).then((result) => {
        res.status(200).send(result);
    }).catch((err) => {
        res.status(400).send(err);
    });
});

router.delete('/', async (req: Request, res: Response, next: NextFunction) => {
    await User.delete({firstName: 'minsu'})
    .then((result) => {
        res.status(204).send(result);
    })
    .catch((err) => {
        res.send(err);
    })
});

export = router;

index.ts 파일 수정하기

index.ts 파일에서는 4개의 User 테이블에 대한 4개의 미들웨어를 정의할 필요가 없어졌으므로 다음과 같이 코드를 수정한다.

import "reflect-metadata";
import {createConnection} from "typeorm";
import userRouter from "./routes/user"; // 해당 부분 추가

import express, { Request, Response, NextFunction } from 'express';

import bodyParser from 'body-parser'; 

const app = express();

app.use(bodyParser.urlencoded({extended:true})); 
app.use(bodyParser.json());

app.use('/user', userRouter); // 해당 부분 추가


app.listen(3000, () => {
    console.log('Starting Server with 3000 port');

    createConnection().then(async connection => {
        console.log("디비 연결 성공");
    
    }).catch(error => console.log(error));

});

routes/user.ts를 가져오는데 이 때 이름을 userRouter로 지정해주었다. 나중에 프로젝트 규모가 커지게 되면 여러 라우팅 파일이 존재할 것이므로 네이밍을 적절하게 하는 것도 중요한 요소일 것 같다.

그리고 app.use('/user', userRouter); 코드를 통해 미들웨어를 추가했다.


위와 같이 미들웨어를 정의하면 localhost:3000/user 경로로 REST 요청을 보내면 된다.

이렇게 코드를 수정하면 index.ts 파일 사이즈를 줄일 수 있으며 파일을 기능별로 분할했기 때문에 유지보수 및 효율성 또한 좋아진다.

결과 확인하기

User 테이블에 1개의 데이터가 있도록 초기화를 먼저 해두었다. 그 상태에서 해당 경로로 GET요청을 보냈을 때 결과가 다음과 같이 적절하게 나온 것을 확인할 수 있다. (delete, update, create 기능에 대한 결과는 생략하기로 했다 😅)

Comments