프로젝트를 진행하면서 TypeORM을 사용하고 있다. 이유는? 그냥 좋다고 하길래...😅 확실하게 ORM이 뭐고, 왜 쓰는지 이해하고 사용해보려고 글을 작성한다.
객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것이라는 의미로, 어플리케이션과 데이터베이스 연결 시 SQL 언어가 아닌 어플리케이션 개발언어로 데이터베이스를 접근할 수 있게 해주는 툴이다.
쉽게 설명하자면, 원래 관계형 DB를 사용하기 위해선 SQL을 사용해야했다. 하지만 어플리케이션 코드를 짜는 것도 머리가 아픈데 DB 쿼리까지 신경쓰려면 슬프다. 그래서 ORM을 사용한다고 한다.
예를 들어 파이썬(장고)에서 작성한 파이썬 코드를 관계형 DB의 SQL 쿼리로 자동 변환 시켜서 개발자가 따로 SQL 쿼리를 작성할 필요 없이 파이썬 코드 작성만으로 DB를 조작할 수 있게 해주는 것이다.
객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다. 여기서 객체 모델과 관계형 모델 간의 불일치가 존재하는데 이를 객체 간의 관계를 바탕으로 SQL을 자동생성하여 불일치를 해결해준다.
MySQL, PostgreSQL, MariaDB 등 많은 RDBMS를 지원하고 Promise 기반으로 구현되어 있기 때문에 비동기 로직을 편리하게 작성할 수 있다.
아직 제대로 써본 적이 없어서 잘 모르겠다.
공식문서에는 다음과 같이 정의되어 있다.
TypeORM은 Node.js, Browser, React Native 플랫폼 등에서 JS, TS와 함께 사용할 수 있는 ORM이다. 소규모 데이터베이스부터 대규모 엔터프라이즈 어플리케이션을 개발하는데 도움이 되는 추가 기능을 제공하는 것을 목표로 합니다. 다른 ORM과 달리 Active Record Pattern
과 Data Mapper Pattern
을 모두 지원하여 확장 가능하며 유지보수가 가능한 어플리케이션을 가장 생산적인 방법으로 작성할 수 있다.
Active Record Patter은 모델 자체 내에서 모든 쿼리 메서드를 정의하고 모델 메서드를 사용하여 오브젝트를 생성, 삭제, 조회, 수정할 수 있게 하는 방식을 의미한다.
아래와 같이 User 모델의 프로퍼티와 메서드를 정의할 수 있다.
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()
}
}
위 User 모델을 이용하여 user 객체를 이미 구현된 메서드로 간단하게 생성, 삭제, 조회, 수정할 수 있다.
또한 위에서 User 모델에 직접 커스텀하여 구현한 메서드 또한 아래처럼 사용할 수 있다.
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await user.save()
await user.remove()
const users = await User.find({ skip: 2, take: 5 })
const newUsers = await User.findBy({ isActive: true })
const timber = await User.findOneBy({ firstName: "Timber", lastName: "Saw" })
//구현한 메서드
const timber = await User.findByName("Timber", "Saw")
Data Mapper Patter은 레포지토리라는 별도의 클래스에서 모든 쿼리 메서드를 정의하고 이 레포지토리를 사용하여 오브젝트를 생성, 삭제, 조회, 수정할 수 있게 하는 방식을 의미한다.
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
@Column()
isActive: boolean
}
아래처럼 User의 레포지토리를 가져와 User 레포지토리에 생성, 삭제, 조회, 수정할 수 있다.
const userRepository = dataSource.getRepository(User)
const user = new User()
user.firstName = "Timber"
user.lastName = "Saw"
user.isActive = true
await userRepository.save(user)
참고
[DB] ORM이란
ORM(Object Relational Mapping)이 뭘까? 🤔
[Node.js] TypeORM이란? (feat. ORM Library)