Nestjs를 배워보자 8일차 - PostgreSQL과 TypeORM, Repository

1

Nestjs

목록 보기
8/9

Nest

본 강의는 'john ahn'님의 강의를 정리한 내용입니다.
https://www.youtube.com/watch?v=3JminDpCJNE

이번 강의는 PostgresSQL과 TypeORM에 대한 내용을 다룬다.

1. PostgresSQL 설치하기

이제부터는 진짜 DB를 사용하여 개발을 진행해보자

필요한 것은 두가지이다.

  1. PostgresSQL
  2. pqAdmin ( 데이터베이스를 보는 tool)

설치 방법은 다음에서 진행하면 된다.

윈도우에서 설치시에는 pgAdmin4를 같이 설치해준다.
설치할 때의 비밀번호와 포트를 잘 기억하도록 하자, 필자의 경우는 포트 5432에서 1234로 바꾸었었다.

2. PostgresSQL 실행하기

MAC은 따로 postgreSQL을 실행하고, pgAdmin으로 가면되고, 윈도우는 자동적으로 실행되므로 pgAdmin으로 바로 가면된다.


설치할 때 설정한 비밀번호를 눌러주고,

서버 생성버튼을 눌러준다.

다음과 같이 프로젝트 이름을 적어준다.

connection 탭으로 이동하여, ip와 포트번호, 비밀번호를 입력한다. 참고로 비밀번호는 설치시에 설정했던 비밀번호이고, 포트역시 설치할 때 사용한 비밀번호를 써야한다.

다음과 같이되어있다면 이제, DB를 생성할 차례이다.

만든 서버에 마우스 우클릭을 하면 Database를 생성할 수 있다.

DB이름을 정해준 다음, 확인버튼을 누르면

다음과 같이 DB가 생성되었음을 확인할 수 있다.

3. TypeORM ( Object Relational Mapping )

TypeORM 이란?

TypeORM는 nodejs에서 실행되고 , TypeScript로 작성된 객체 관계형 맵퍼 라이브러리이다. PostgreSQL 뿐만아니라, MySQL, MariaDB, SQLite 등등 여러 데이터 베이스를 지원한다.

ORM( Object Relational Mapping 이란)

객체와 관계형 데이터베이스의 데이터를 자동으로 변형 및 연결하는 작업이다. ORM을 이용한 개발은 객체와 데이터베이스의 변형에 유연하게 사용할 수 있다.

객체는 프로그래밍의 클래스 <-> 관계형 데이터의 테이블

이들은 매우 닮은 모습을 가졌기 때문에 서로 호환을 할 수 있는 것이다.
typeORM을 사용한 버전와 일반적인 query 사용을 비교해보도록 하자

const boards = Board.find( { title : "hello" , status: "PUBLIC"}) // typeORM 사용

db.query(
    "SELECT * FROM boards
     WHERE title = "hello" AND status = "PUBLIC"
, (err, result) => {
    if(err){
        throw new Error("Error")
    }
    boards = result.rows;
}) // 일반적인 query 사용

TypeORM의 특징과 이점

  • 모델을 기반으로 데이터베이스 테이블 체계를 자동으로 생성한다.
  • 데이터베이스에서 개체를 쉽게 삽입 , 업데이트 및 삭제할 수 있다.
  • 테이블 간의 맵핑( 일대일, 일대 다 다대다)을 만들 수 있다.
  • 간단한 CLI 명령을 제공한다.
  • TypeORM은 간단한 코딩으로 ORM 프레임워크를 사용하기 쉽다.
  • TypeORM은 다른 모듈과 쉽게 통합된다.
  • 데이터 베이스의 변화에도 코드 수정이 적어진다.

4. TypeORM 을 사용하기 위해서 설치해야하는 모듈들

  1. @nestjs/typeorm : nestjs에서 typeORM을 연동하기 시켜주는 모듈
  2. typeorm : TypeORM 모듈
  3. pg : Postgre 모듈
npm install pg typeorm @nestjs/typeorm --save

PostgreSQL 뿐만 아니라, MySQL 등도 연결할 수 있다.

5. TypeORM 설정하기

먼저 TypeORM 설정 파일을 생성해주어야 한다.

src/configs/typeorm.config.ts 를 만들어주도록 하자

다음처럼 만들어주면 된다.

이제 typeorm.config.ts에 다음의 코드를 넣어주도록 하자

import { TypeOrmModuleOptions } from "@nestjs/typeorm"

export const typeORMConfig : TypeOrmModuleOptions = {
    type: 'postgres',
    host: 'localhost',
    port: 1234,
    username: 'postgres',
    password: 'password',
    database: 'board-app',
    entities: [__dirname + '../**/*.entity.{js,ts}'],
    synchronize : true
}

각 항목에 맞는 자신의 설정을 넣어주면 된다. 참고로 entities는 데이터베이스의 entity가 저장되는 위치로 아직 만들지 않았다.

synchromize는 어플리케이션을 다시 실행할 때 , 엔티티안에서 수정된 컬럼의 길이, 타입 변경값등을 해당 테이블을 drop 한 후 다시 생성해준다. 실제 서비스에서는 위험하지만 test니까 상관없다.

다음으로 config 파일을 우리의 application과 연결시켜보도록 하자, 루트 모듈에서 연결시켣주면 되므로, app.module.ts 로 가도록 하자

app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BoardsModule } from './boards/boards.module';
import { BoardsService } from './boards/boards.service';
import { typeORMConfig } from './configs/typeorm.config'

@Module({
  imports: [TypeOrmModule.forRoot(typeORMConfig), BoardsModule],
  providers: [BoardsService],
})
export class AppModule {}

다음과 같이 TypeOrmModule이라는 Nestjs API에 우리의 config를 넣어주면 된다.

6. 게시물 엔티티 생성하기

왜 Entity를 생성해야 할까??

기존 방식을 사용한다면 CREATE TABLE board() 이런 식으로 entity를 만들어야 했다.

그러나, 해당 방식은 복잡할 뿐더러 실수할 여지가 많고 수정이 어렵다.

하지만 TypeORM을 사용한다면, 데이터베이스 테이블로 변환되는 class를 생성하기 때문에 위에 처럼하지 않고 클래스를 생성한 후에 그 안에 컬럼들을 정의해주면 된다.

필요한 데코레이터는 다음과 같다.

@Entity

해당 클래스가 엔티티임을 나태는데 사용된다. 이는 테이블에 해당되는 부분이다.

@PrimaryGeneratedColum()

해당 클래스의 PK를 나타내는 부분으로, 해당 column이 PK로 사용될 것을 나타낸다.

@Column

해당 클래스의 어떤 property가 컬럼으로 쓰여서 DB에 저장될지 알려주는 엔티티이다.

이제 entity를 만들어보자

src/board/board.entity.ts

import { BaseEntity, Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
import { BoardStatus } from "./boards.model";

@Entity()
export class Board extends BaseEntity {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title : string;

    @Column()
    description : string;

    @Column()
    status : BoardStatus;
}

다음과 같이 board.entity.ts 를 만들어주면 된다.

7. Repository 생성하기

Repository는 엔티티 개체와 같이 작동하며, 엔티티 찾기, 삽입, 업데이트, 삭제 등을 처리한다. (CRUD를 처리한다.)

즉, Repository로 마치 DBMS에서 DB를 다루듯이 Entity를 다루는 것이다. 우리가 아는 DB의 기능, count(), avg() 등도 가능하고 데이터를 삽입 ,삭제하는 것도 가능하다. Repository가 DB와 관련된 모든 일을 맡는 것이다.

다음과 같은 시스템 구성도를 갖게 되는 것이다.
이러한, Controller, Service, Repository 구조를 가지는 것이 Nestjs의 가장 기본적인 구조이다.

Repository 생성하기

  1. repository 생성하기
    board.repository.ts 생성

  2. 생성한 파일에 repository를 위한 클래스 생성
    생성 시에 Repository<> 클래스를 Extends 시켜준다. 이를 통해서 Find, Insert, Delete 등 엔티티를 컨트롤 해줄 수 있는 것이다.

    그리고 repository 클래스 위에 @EntityRepository() 데코레이터를 달아줌으로서 해당 클래스가 사용자 정의 저장소임을 선언해주도록 한다. 사용자 정의 저장소는 일부 특정 엔티티를 관리하거나, 일반 저장소일 수 있다.

  3. 생성한 Repository를 다른 곳에서도 사용할 수 있도록 (Injectable) board.module에서 import 해주도록 한다.

먼저 repository 파일을 생성해보도록 하자

/src/boards/board.repository.ts

import { EntityRepository, Repository } from 'typeorm'
import { Board } from './board.entity'

@EntityRepository(Board)
export class BoardRepository extends Repository<Board> {
    
}

이제 해당 repository가 injectable할 수 있도록 board 모듈에서 묶어주도록 하자, app.module에 넣어주지 않고 baord.module에 넣어주는 이유는 board에서만 사용할 것이기 때문이다.

/src/boards/boards.modules.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { BoardRepository } from './board.repository';
import { BoardsController } from './boards.controller';
import { BoardsService } from './boards.service';

@Module({
  imports : [
    TypeOrmModule.forFeature([BoardRepository])
  ],
  controllers: [BoardsController],
  providers: [BoardsService]
})
export class BoardsModule {}

entity나 repository는 위의 그림대로 TypeORM에서 나오는 개념이다. 따라서, TypeORM에서 제공하는 API를 사용한 것이고, 이를 Nestjs 위에서 동작하기 위해 사용하는 API들이 바로 @nestjs/typeorm 이 되는 것이다.

실제로 @nestjs/typeorm 에서는 모듈과 typeorm의 repository를 연결해주는 TypeOrmModule말고는 다른게 잘 사용되지 않는다.

@nestjs/typeorm은 typeorm와 nestjs를 연결해주기만 하는 역할을 하지, 이를 통해 조작하는 것을 제공하진 않는다. 즉, 연결만 끝냈다면 우리는 온전히 typeorm에서 제공하는 api들을 사용하기만 하면되는 것이다.

0개의 댓글