Language/JavaScript

TypeORM 이란?

nayoon030303 2021. 8. 4. 05:04

ORM이란?

Object Relation Mapping에 약자입니다. 객체와 관계형 데이터베이스의 데이터를 자동으로 Mapping(연결)해주는 것을 말합니다. 객체지향 프로그래밍은 클래스를 사용합니다. 관계형 데이터베이스는 테이블을 사용합니다. 

객체 모델과 관계형 데이터베이스 사이에는 모델 간에 불일치가 존재합니다. ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결합니다. 

데이터베이스<-메핑->객체(class)

 

 

TypeORM이란?

그럼 TypeORM이란 무엇일까요?

express와 관계형 데이터베이스를 조합할 때 같이 사용되는 ORM으로 Sequelize라는 라이브러리가 있지만, 타입스크립트의 확대와 같이 인기가 높아지는 ORM이 바로 TypeORM입니다. TypeScript에서도 사용할 수 있고JavaScript(ES5,ES6,ES7)에서도 사용할 수 있습니다. 

TypeORM을 사용하면 Data Mapper 패턴Active Record 패턴으로 개발할 수 있다고 합니다. 그리고 모델의 정의를 제대로 하면 타입을 정하는 장점을 최대한으로 얻을 수 있고, 복잡한 모델 간의 관계를 형성할 수 있다는 장점이 있습니다. 

 

Data Mapper 패턴 vs Active Record 패턴

Active Record 패턴

Active Record 패턴은 모델 자체 내에서 모든 쿼리 메서드를 정의하고 모델 메서드를 사용하여 개체에 저장, 제거 및 로드합니다. 간단하게 말해서 Active Record 패턴은 모델 내에서 데이터베이스에 액세스 하는 접근 방식입니다.

 

아래 코드는 공식문서의 예제 코드입니다. 

  • 모든 active-record 계체들은 BaseEntitiy 클래스를 반드시 상속받아야 합니다. 
  • 정적 메서드로 findByName이라는 함수를 만들 수 있습니다. 
import {BaseEntity, Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity()
export class User extends BaseEntity {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    isActive: boolean;
    
    static findByName(firstName: string, lastName: string) {
        return this.createQueryBuilder("user")
            .where("user.firstName = :firstName", { firstName })
            .andWhere("user.lastName = :lastName", { lastName })
            .getMany();
    }
}

 

아래와 같이 new 키워드를 이용하여 새로운 인스턴스를 만들어 사용하는 것이 가능합니다. 

// example how to save AR entity
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.isActive = true;
await user.save();

// example how to remove AR entity
await user.remove();

// example how to load AR entities
const users = await User.find({ skip: 2, take: 5 });
const newUsers = await User.find({ isActive: true });
const timber = await User.findOne({ firstName: "Timber", lastName: "Saw" });

 

Data Mapper 패턴

Data Mapper 패턴은 분리된 클래스에 쿼리 메서드를 정의하는 방식이며, Repository를 이용하여 객체를 save, delete, read 합니다. Active Record 패턴과의 차이점은 모델에 접근하는 방식이 아닌 Repository에서 데이터에 접근한다는 것입니다. 

 

아래 코드는 공식 문서의 예제 코드입니다. 

 

엔티디를 정의합니다. 

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

@Entity()
export class User {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    isActive: boolean;

}

 

정의한 클래스를 Generic타입을 이용하여 상속하게 합니다. 

import {EntityRepository, Repository} from "typeorm";
import {User} from "../entity/User";

@EntityRepository()
export class UserRepository extends Repository<User> {

    findByName(firstName: string, lastName: string) {
        return this.createQueryBuilder("user")
            .where("user.firstName = :firstName", { firstName })
            .andWhere("user.lastName = :lastName", { lastName })
            .getMany();
    }

}

그리고 getRepository()를 사용하여 만들어진 모델을 사용합니다. 

const userRepository = connection.getRepository(User);

// example how to save DM entity
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.isActive = true;
await userRepository.save(user);

// example how to remove DM entity
await userRepository.remove(user);

// example how to load DM entities
const users = await userRepository.find({ skip: 2, take: 5 });
const newUsers = await userRepository.find({ isActive: true });
const timber = await userRepository.findOne({ firstName: "Timber", lastName: "Saw" });

 

 

어떤 패턴으로 개발을 해야 할까요?

공식문서에서는 각각 장단점이 있다고 합니다.

  • Data Mapper 패턴은 접근 방식이 유지보수에 도움이 되며, 이는 더 큰 프로젝트에서 효과적이라고 합니다. 
  • Active Record 패턴은 규모가 작은 프로젝트에서 적합하고 간단하게 사용할 수 있다고 합니다. 

 

 

 


이번 시간에는 TypeORM이 무엇인지에 대해서 공부해봤습니다. 다음 시간에는 프로젝트 시작 방법에 대해서 설명하겠습니다. 

 

참고 사이트

https://typeorm.io/#/active-record-data-mapper TypeORM공식문서

https://velog.io/@josworks27/typeORM-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0