TypeScript + Express + typeORM으로 서버 세팅하기(1)

조성철 (JoSworkS)·2020년 2월 4일
7

이번 프로젝트는 앞서 SR에서 사용하기로 결정한 TypeScript, Express, TypeORM으로 서버를 세팅하였다. 특히 TypeScript와 TypeORM은 처음 써보는 스택이었기 때문에 Express 서버에 적용하는데 있어서 시행착오가 많았다.

이번 로그에서는 TypeScript와 Express를 이용하여 서버를 구축하는 것까지 기록하도록 하겠다.

Initial Directory Structure

먼저 초기 세팅이 완료된 서버의 디렉토리 구조를 보면 다음과 같다.

.
├── README.md
├── env.sample
├── node_modules
├── ormconfig.json
├── package-lock.json
├── package.json
├── src
│   ├── controllers
│   │   ├── application.ts
│   │   ├── favs.ts
│   │   ├── houses.ts
│   │   ├── payment.ts
│   │   ├── review.ts
│   │   └── users.ts
│   ├── entities
│   │   ├── Amenity.ts
│   │   ├── Application.ts
│   │   ├── Favorite.ts
│   │   ├── House.ts
│   │   ├── Image.ts
│   │   ├── Review.ts
│   │   └── User.ts
│   ├── index.ts
│   ├── migrations
│   ├── routes
│   │   ├── application.ts
│   │   ├── favs.ts
│   │   ├── houses.ts
│   │   ├── payment.ts
│   │   └── users.ts
│   ├── server.ts
│   └── uploads
│       ├── 1580953191488.jpg
│       ├── 1580953191496.jpg
│       └── 1580953191497.jpg
└── tsconfig.json

tsconfig.json 설정

TypeORM의 init 커맨드를 이용하여 빠르게 express에 TypeORM을 적용하는 방법도 있었지만 구조를 직접 구현해보고 싶어서 TypeScript + Express 스타터 샘플을 보고 기본적인 서버를 구현한 후 TypeORM을 입히는 순으로 진행하였다.(스타터 샘플을 맨 아래 참고자료 1번을 참고하였다.)

먼저 타입스크립트를 자바스크립트로 변환하는 컴파일 작업을 위해 아래와 같이 tsconfig.json에 컴파일 설정을 해주었다.

// tsconfig.json

{
  // 기본 타입정의 라이브러리를 어떤 것을 사용할 것인지
   "compilerOptions": {
      "lib": [
         "es5",
         "es6"
      ],
     // 결과물을 어떤 버전으로 할 것인지
      "target": "es2015",
     // 컴파일 된 모듈의 결과물을 어떤 모듈 시스템으로 할 것인지
      "module": "commonjs",
     // ts소스에서 모듈을 사용하는 방식
      "moduleResolution": "node",
     // 컴파일된 js파일을 어디에 둘 것인지
      "outDir": "dist",
     // TS타입 체크를 엄격할게 할 것인지. 다양한 세부옵션이 있음
      "strict": true,
     // TypeORM 사용 시에 decoration 관련 옵션
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "sourceMap": true
   },
  // 어디에 있는 파일을 컴파일 할 것인지
   "include": [
    "src/**/*"
  ],
  // 컴파일에서 제외되는 파일들
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

index.ts 소스코드

필요한 모듈들을 세팅하고 각 api를 분기하기 위해 라우터를 만들어서 라우터에서 각 컨트롤러를 연결하는 작업을 진행하였다.

// index.ts

import 'reflect-metadata';
import { createConnection } from 'typeorm';
import * as express from 'express';
import * as compression from 'compression';
import * as bodyParser from 'body-parser';
import * as cors from 'cors';
import * as morgan from 'morgan';
import 'dotenv/config';

// Import Routers
import { usersRouter } from './routes/users';
import { housesRouter } from './routes/houses';
import { favsRouter } from './routes/favs';
import { applicationRouter } from './routes/application';
import { paymentRouter } from './routes/payment';
import { authRouter } from './routes/auth';
import { forumRouter } from './routes/forum';

// Connect typeORM mysql
createConnection()
  .then(() => {
    console.log('Database Connected :)');
  })
  .catch((error) => console.log(error));

// Create express server
const app = express();

// middlewares
app.set('port', process.env.PORT || 3000);
app.use(compression());
app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: false,
  }),
);
app.use(morgan('dev'));
app.use(
  cors({
    origin: [`${process.env.TEST_IP}`],
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    credentials: true,
  }),
);

// Routes
app.use('/users', usersRouter);
app.use('/houses', housesRouter);
app.use('/favs', favsRouter);
app.use('/application', applicationRouter);
app.use('/payment', paymentRouter);
app.use('/auth', authRouter);
app.use('/forum', forumRouter);

export default app;

모든 서버코드가 index.ts에 작성되어 있으면 가독성이 떨어지므로 app.listen() 부분을 server.ts로 분리하였다.

./src/server.ts

import app from './index';

// Express Server Connection
const server = app.listen(app.get('port'), () =>
  console.log(`BillyZip App Listening on PORT ${app.get('port')}`),
);

export default server;

결론

처음에는 Typescript + Express + TypeORM으로 서버를 구축하게 되면 Javascript + Express + Sequelize로 구성하는 서버와 많이 다르지 않을까 라고 생각했었지만'microsoft/TypeScript-Node-Starter'를 참고하여 구축하였더니 큰 차이가 있지는 않았다.

차이가 있다고 한다면 Typescript를 사용함에 따라 컴파일을 설정하기 위해 tsconfig.json을 구축하고자 하는 소프트웨어에 맞게 설정해주는 부분이 추가된 점이 거의 다였다.

물론 위와 같은 방식과 다른 형태의 방식도 있을 것이다. 그런 부분에 있어서는 자신만의 서버구축 컨벤션을 만들어 보면서 시도해보면 좋을 것 같다.

참고자료

  1. https://github.com/Microsoft/TypeScript-Node-Starter#typescript-node-starter

0개의 댓글