์๋ ํ์ธ์ Foma ์ ๋๋ค!
์ค๋์ ์ ๋ฒ ๊ธ Sequelize์ ์ด์ด์ Node.js ORM ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ TypeORM์ ๋ํด์ ๋ค๋ค๋ณด๋ ค๊ณ ํฉ๋๋ค.
ํ์์ Typescript๋ก ๊ฐ๋ฐํ๋ ๊ฒ์ ์ ํธํ๊ธฐ ๋๋ฌธ์ "Sequelize๋ฅผ Typescript๋ก ๊ฐ๋ฐํ ์ ์๋?" ํ๊ณ ์ฐพ์๋ดค๋๋
Typescript ๊ธฐ๋ฐ์ผ๋ก TypeORM ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ ๊ฐ๋๋ผ๊ตฌ์.
(๋ฌผ๋ก Sequlize๋ Typescript๋ฅผ ์ง์ํฉ๋๋ค. ์ฌ๊ธฐ ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.)
๊ทธ๋์ ์ค๋์ TypeORM์ด ๋ฌด์์ธ์ง์ ๋ํด ์ ๋ฆฌํด ๋ณด๋ ค๊ณ ํฉ๋๋ค.
๋ฐ๋ก ์์ํ ๊ฒ์~
ORM์ด๋?
๋จผ์ Sequelize๋ฅผ ์๊ธฐ ์ํด์ ORM์ ๊ฐ๋ ์ ์์์ผ ํ๋๋ฐ์.
๊ทธ ์ด์ ๋ ๋ฐ๋ก Sequelize๊ฐ Node.js์ ORM ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ด์ฃ .
ORM์ Object Relational Mapping์ ์ค์๋ง๋ก ๊ฐ์ฒด์ ๊ด๊ณ๋ฅผ ๋งคํํด์ฃผ๋ ๊ฒ ์ ๋๋ค.
์ข ๋ ๊ตฌ์ฒด์ ์ผ๋ก ๊ฐ์ฒด์ ๊ด๊ณ๋ฅผ ๋งคํํด์ค๋ค๋ ๊ฒ ์ด๋ค ๊ฒ์ผ๊น์?
์๋ฅผ ๋ค๋ฉด ๊ฐ์ฒด ์งํฅ ์ธ์ด์์๋ ๋ชจ๋ธ์ ์ ์ํ ๋ Class๋ฅผ ์ฌ์ฉํ๊ณ , ๊ด๊ณํ ๋ฐ์ดํฐ ๋ฒ ์ด์ค์์ Table์ ์ฌ์ฉํฉ๋๋ค.
๋ฐ๋ก ์ฌ๊ธฐ์ ๊ฐ์ฒด ์งํฅ ์ธ์ด๋ก ๋ Class๋ฅผ ๊ด๊ณํ ๋ฐ์ดํฐ ๋ฒ ์ด์ค์ Table์ ์ฐ๊ฒฐ์์ผ ์ค๋ค๋ ๊ฒ์ด์ฃ .
์ด๊ฒ์ ์ง์ SQL๋ฌธ์ ์์ฑํ์ง ์๊ณ , ๊ฐ์ฒด ์งํฅ์ ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋๋ก ๋์์ฃผ๋ ๊ฒ์ด์ฃ .
(ORM์ ๋ ๊น์ด ์๊ณ ์ถ์ผ์ ๋ถ๋ค์ ์ฌ๊ธฐ ์์ ํ์ธํด ์ฃผ์ธ์!)
TypeORM์ด๋?
๊ณต์ ํํ์ด์ง์์๋ ์๋์ ๊ฐ์ด ์๊ฐํ๊ณ ์์ต๋๋ค.
TypeORM is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript and JavaScript (ES5, ES6, ES7, ES8). Its goal is to always support the latest JavaScript features and provide additional features that help you to develop any kind of application that uses databases - from small applications with a few tables to large scale enterprise applications with multiple databases.
TypeORM supports both Active Record and Data Mapper patterns, unlike all other JavaScript ORMs currently in existence, which means you can write high quality, loosely coupled, scalable, maintainable applications the most productive way.
TypeORM is highly influenced by other ORMs, such as Hibernate, Doctrine and Entity Framework.
๊ฐ๋จํ๊ฒ ํด์ํ๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
" TypeORM์ Node.js, Browser, React Native ํ๋ซํผ ๋ฑ์์ JS,TS์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ ORM์ ๋๋ค. ์๊ท๋ชจ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ถํฐ ๋๊ท๋ชจ ์ํฐํ๋ผ์ด์ฆ ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๋๋ฐ ๋์์ด ๋๋ ์ถ๊ฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค. ๋ค๋ฅธ ORM๊ณผ ๋ฌ๋ฆฌ ์กํฐ๋ธ ๋ ์ฝ๋ ํจํด๊ณผ ๋ฐ์ดํฐ ๋งคํผ ํจํด์ ๋ชจ๋ ์ง์ํ์ฌ ํ์ฅ ๊ฐ๋ฅํ๋ฉฐ ์ ์ง๋ณด์๊ฐ ๊ฐ๋ฅํ ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ์ฅ ์์ฐ์ ์ธ ๋ฐฉ๋ฒ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค. "
Active Record Pattern์ด๋?
์กํฐ๋ธ ๋ ์ฝ๋ ํจํด์ ๋ชจ๋ธ ์์ฒด ๋ด์์ ๋ชจ๋ ์ฟผ๋ฆฌ ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ ๋ชจ๋ธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ธ์ ํธ๋ฅผ ์์ฑ,์ญ์ ,์กฐํ,์์ ํ ์ ์๊ฒ ํ๋ ๋ฐฉ์์ ์๋ฏธํฉ๋๋ค.
์๋์ ๊ฐ์ด 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 Pattern์ด๋?
๋ฐ์ดํฐ ๋งคํผ ํจํด์ "๋ ํฌ์งํ ๋ฆฌ" ๋ผ๋ ๋ณ๋์ ํด๋์ค์์ ๋ชจ๋ ์ฟผ๋ฆฌ ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ ์ด "๋ ํฌ์งํ ๋ฆฌ"๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ธ์ ํธ๋ฅผ ์์ฑ, ์ญ์ , ์กฐํ, ์์ ํ ์ ์์ต๋๋ค.
์กํฐ๋ธ ๋ ์ฝ๋ ํจํด๊ณผ ๊ฐ์ด User ๋ชจ๋ธ์ ์ ์ํด ์ค๋๋ค.
์ฐจ์ด์ ์ User ๋ชจ๋ธ์ BaseEntity๋ก ํ์ฅํ์ง ์์ต๋๋ค.
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)
// 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.findBy({ isActive: true })
const timber = await userRepository.findOneBy({
firstName: "Timber",
lastName: "Saw",
})
๋๋ ์
Sequelize๋ฅผ ๋ค๋ค๋ณด์์ ๋ ๋ชจ๋ธ์ ๋ง๋ค๊ณ ์ง์ ์ํ์ ์์ฑํ์ง ์๋๋ค๋ ์ ์์ ์ง์ง ํธ๋ฆฌํ๊ณ ํ๋ช ์ ์ธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๊ณ ์๊ฐํ๋ค.
๊ทผ๋ฐ TypeORM์ ๋ฐ๊ฒฌํ๊ณ ์ฌ์ฉํด ๋ณด๋๊น ๋ชจ๋ธ์ ๋ง๋๋ ๋ถ๋ถ์ด๋ , ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์ ์์ ๋ ์ง๊ด์ ์ด๊ณ , ๋ญ๊ฐ ๋ฐฑ์๋๋ฅผ ํ๋ก ํธ ์๋์ฒ๋ผ ๊ฐ๋ฐํ ์ ์๋ค๋ ๊ฑธ ๋๋ผ๊ฒ ๋์๋ค.
์ฅ๋จ์ ์ด ์๊ฒ ์ง๋ง ๋ ์ค์ ํ๋๋ฅผ ๊ณ ๋ฅธ๋ค๋ฉด TypeORM์ ์ฌ์ฉํ ๊ฒ ๊ฐ๋ค.
Reference
๋๊ธ