-
Notifications
You must be signed in to change notification settings - Fork 3
๐ ORM ๊ธฐ์ ์คํ ๋น๊ต
๋ถ์ผ | ์์ฑ์ | ์์ฑ์ผ |
---|---|---|
BE | ๊น๋ฏผ์ | 24๋ 10์ 28์ผ |
- ํ ๋ ๋ง์ด ์ฌ์ฉํ๋ node ์ง์์ ORM ๊ธฐ์
- ์ค๋๋ ๋งํผ ๊ฑฐ๋ํ ์ปค๋ฎค๋ํฐ ํ์ฑ๊ณผ ๊ธฐ์ ์ ์์ ์ฑ์ด ๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ํ Model ๊ฐ์ฒด
- ๋ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ง์
- ์ฟผ๋ฆฌ์ ๋ฐ๋ฅธ ๊ธฐ๋ณธ ๋ฉ์๋ ์ง์
- validator์ ์ ์ฝ์กฐ๊ฑด ์ค์ ๊ฐ๋ฅ
- raw ์ฟผ๋ฆฌ ์ง์
- ๋ ผ๋ฆฌ์ ์ญ์ ์ง์
- Lazy Loading/Eager Loadingย ์ง์
- ๊ณต์๋ฌธ์ - ์ค๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ธฐ ๋๋ฌธ์ ๊ณต์๋ฌธ์๊ฐ ์ ์ ๋ฆฌ๋์ด์๋ค.
- ์ฝ๋ ๊ฐ๋ ์ฑ: ์ฌ์ฉํ๊ธฐ์ ๊ฐ์ฅ ํฐ ๋จ์ ์ด๋ผ๊ณ ์๊ฐ, ๋ชจ๋ธ ์ค์ ์ ์นผ๋ผ์ ํ์ ์ด๋ ํน์ง์ ์์ฑํ๋ ์ฝ๋๋, ์ฐ์ฐ ๊ด๋ จ ๋ฉ์๋์ ์ฝ๋๊ฐ ๋๋ฌ์ธ ์ ์๋ค.
- ์ฟผ๋ฆฌ๊ฐ ๋๋ฆฌ๋ค: ๋ฉ์๋์์ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ ๊ทธ์ ๋ค๋ฅธ ์ค๋ฒํค๋๊ฐ ์์ ์ ์๋ค.
- ๋์ ๋ฌ๋์ปค๋ธ: ORM ๋ฉ์๋๊ฐ sql๊ณผ ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ ์ ์๊ธฐ ๋๋ฌธ์ sql์ ์๋ค๊ณ ํด๋ ์ด๋ ค์ธ ์ ์๋ค.
- ๋ณต์กํ ์ฝ๋์ ์ทจ์ฝํ ์ ์๋ค: ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฌ๋ ๋ฉ์๋ ํ์์ด ๋งค์ฐ ๋ณต์กํ๊ณ ์ง๊ด์ ์ด์ง ์์, ์๋์น ์๊ฒ ๋๋ฆฐ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๊ฑฐ๋ ์๋ชป๋ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ค.
- ์๋ ๊น์ง ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ORM
- JPA์ ๊ฐ์ฅ ๊ทผ์ ํ ํํ์ด๋ค.
- DataMapper์ย ActiveRecordย ํํ์ ์ฝ๋ ์ง์ (๊ฐ์ธ์ ์ผ๋ก DataMapper๊ฐ ์ข๋ค๊ณ ์๊ฐ)
- Entity๊ฐ๋
์กด์ฌ
- ๋ค์ํ ๋ฐ์ฝ๋ ์ดํฐ ์ง์
- Embedded Entities ์กด์ฌ(์ํฐํฐ ๋ด๋ถ ์ ๋๋ค๋ฅธ ์ํฐํฐ)
- ๋ทฐ ์ํฐํฐ, tree ์ํฐํฐ ์กด์ฌ
- Datasource ์ฌ์ฉ (DB ์ปค๋ฅ์ ์ถ์ํ)
- ์ฐ๊ด ๊ด๊ณ ๊ด๋ จ ๋ฐ์ฝ๋ ์ดํฐ ์ ๊ณต
- Cascade ์ต์ ์ ๊ณต
- ์ฆ์/์ง์ฐ ๋ก๋ฉ ์ ๊ณต
- ์ํฐํฐ ๋งค๋์ ์ ๊ณต
- repository ์์ฑ ๋ฐ ์ํฐํฐ ๊ด๋ จ ์ฒ๋ฆฌ
- ์ฟผ๋ฆฌ ๋น๋ ์ ๊ณต
- ๋ค์ํ ๋ฐ์ฝ๋ ์ดํฐ ์ง์
- Transactional ๋ฐ์ฝ๋ ์ดํฐ ์ ๊ณต(0.3์ดํ ๋ฒ์ ์๋ ์ง์ X)
- ์ธ๋ฑ์ค ๋ฐ์ฝ๋ ์ดํฐ
- ์ํฐํฐ ์ด๋ฒคํธ ์ ๊ณต
- ์ฌ๋ฌ๊ฐ์ง ๋ฐ์ฝ๋ ์ดํฐ ์ง์ - ๋ค์ํ ๋ฐ์ฝ๋ ์ดํฐ๋ก ์ฌ์ฉ๋๋ ์ฝ๋ ์๋ ์ค์ด๊ณ ๊ฐ๋ ์ฑ๋ ๋์ผ ์ ์๋ค.
- JPA ์ฌ์ฉ์์๊ฒ ๋ฎ์ ๋ฌ๋์ปค๋ธ - ์ํฐํฐ ๊ฐ๋ ๊ณผ ๋๋ถ์ด ๊ด๋ จ ๊ธฐ๋ฅ๋ค์ด JPA์ ๊ฐ์ฅ ์ ์ฌํ์ฌ, ์ด๋ฏธ JPA๋ฅผ ๋ฐฐ์ด ์ฌ๋๋ค์ ์น์ํ๊ฒ ์ฌ์ฉ๊ฐ๋ฅ (๋จ, ์ผ๋ถ ๊ธฐ๋ฅ์ด ์์ด์ ๋ถํธํจ์ด ์์ ์ ์์)
- ๊ธํ๋ฉด ์ฟผ๋ฆฌ ๋น๋ ์ฌ์ฉ๊ฐ๋ฅ - ๊ฐ์ฅ ํฐ ์ฅ์ ์ด๋ผ๊ณ ์๊ฐ, ๋ณต์กํ ์ฟผ๋ฆฌ๋ ์ต์ ํ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋ ์ฟผ๋ฆฌ ๋น๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ์์ฑ ๊ฐ๋ฅ
- ๋ฒ์ ๋ฌธ์
- ์์ง ์ ์ ๋ฒ์ ์ด ์ถ์๋์ง ์์์ ๊ธฐ์ ์ ์์ ์ฑ์ด ๋ฎ์ ์ ์๋ค.
- 0.3 ์ดํ ๋ฒ์ ๋ฌธ์ (ํธ๋์ญ์ ๋ฐ์ฝ๋ ์ดํฐ ์ง์ X, ์ด์ ๋ฒ์ ํธํ๋ฌธ์ )
- 0.4๋ก ๋ฐ๋๊ฒ ๋ ๋ ๊ธฐ์กด์ ์ฝ๋๊ฐ ํธํ์ด ์๋ ์๋ ์์
- ํ์ ์์ ์ฑ์ ๋ฌธ์ - AnyORM์ด๋ผ๋ ๋ณ๋ช ๋ต๊ฒ ํ์ ์ ๋ํด ์ ๋๋ก ์ฒดํฌํ ์ ์๋ค.
- ํด๋จผ ์๋ฌ๋ฅผ ์ก์ง ๋ชปํจ - ์ฟผ๋ฆฌ์ ์ ๋ฌ๋๋ ํ์ ์ ์ปดํ์ผ ๋จ๊ณ์ ํ์ธํ์ง ์์ผ๋ฏ๋ก ์ด์ ์ฐ๊ด๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
- ๊ณต์๋ฌธ์๊ฐ ๋ค๋ฅธ ORM์ ๋นํด ์ค๋ช ์ด ๋ถ์คํ๋ค๊ณ ๋๋
- ์ต๊ทผ์ ํ์ํ ORM
- 2024๊ธฐ์ค์ผ๋ก ๊ฐ์ฅ ๋ง์ด ๋ค์ด๋ก๋ ํ ORM์ด๋ค.
- ํ์ ์์ ์ฑ๊ณผ schema๋ฅผ ํตํ ์ํฐํฐ ์์ฑ์ด ์ฃผ์ ๊ธฐ๋ฅ์ด๋ค.
- ๋ฐ์ดํฐ ๋ชจ๋ธ์ ์คํค๋ง ํํ๋ก ์ ์ธ
- ํ ์ด๋ธ ๋ฟ๋ง ์๋๋ผ ์ฐ๊ด๊ด๊ณ๋ ์ธ๋ฑ์ค, ๋ทฐ๋ ์ ์ธํ ์ ์๋ค.
- ์์ฑํ ์คํค๋ง๋ฅผ DB์ ๋ฐ์ํ ์ ์๋ค.
- ํน์ DB์ ์ง์๋์ง ์์ ์ ์๋ ๊ธฐ๋ฅ์ด ์์ผ๋ฏ๋ก ์ฃผ์ ํ์
- ์ฟผ๋ฆฌ ์คํ์ ์ํ Prisma Client
- ์คํค๋ง ๊ธฐ๋ฐ์ผ๋ก ์๋์ผ๋ก TypeScript ํ์ ์ ์์ฑํด์ค โ ํ์ ์์ ์ฑ์ด ๋ณด์ฅ
- ์ผ๋ฐ์ ์ธ CRUD์ ์ฐ๊ด ๊ด๊ณ ์ฟผ๋ฆฌ, ํํฐ๋ง ์ ๋ ฌ, ํ์ด์ง๋ค์ด์ ๋ฑ ๋ค์ํ ์ข ๋ฅ์ ์ฟผ๋ฆฌ์ ๋ํ ๋ฉ์๋๋ฅผ ์ ๊ณต
- Custom validation ์ ๊ณต
- logging๊ณผ metrix ๊ธฐ๋ฅ ์ ๊ณต
- ํ์ ์ ๋งค์ฐ ๊ฐ๋ ฅํจ - ๋ค๋ฅธ ORM๊ณผ ๋ฌ๋ฆฌ ์ปดํ์ผ ๋จ๊ณ์์ ํ์ ์ ๋ํ ์๋ฌ๋ฅผ ์ ๊ณตํด์ค๋ค. ์ฟผ๋ฆฌ ๊ด๋ จ ๋ฉ์๋๋ฅผ ์คํํ ๋ ํ์ ์ ์ฒดํฌํด์ฃผ๊ธฐ ๋๋ฌธ์ ํธํ๋ค.
- ๋ชจ๋ธ ์ ์ธ์ด ๊ฐ์ฅ ๋ณด๊ธฐ ํธํ๋ค. - ๋ชจ๋ธ ์ ์ธ์ sql์ create ์ฟผ๋ฆฌ ๋ฌธ๊ณผ ์ ์ฌํด์ ์ง๊ด์ ์ด๋ค.
- ๋๋ฆฌ๋ค: ๋ค๋ฅธ ORM์ ๋นํด ๋๋ฆด ์๋ ์๋ค. Typingํ๋ ๊ฒ๊ณผ ๋๋ถ์ด์ ํด๋จผ ์๋ฌ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ๋๋ค๋ฅธ ์ฟผ๋ฆฌ๊ฐ ์คํํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ex)drop์ select ์ฟผ๋ฆฌ๊ฐ ์คํ
- ๋ณต์กํ ์ฟผ๋ฆฌ์ ์ฝํ ์ ์๋ค: nested ์ฟผ๋ฆฌ๊ฐ ํฌํจ๋๋ ์ฟผ๋ฆฌ์ ๊ฐ์ด ๋ณต์กํ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋ ์ด๋ ค์ธ ์ ์๋ค.
-
Sequelize
import { Model, DataTypes } from 'sequelize'; import sequelize from './database'; class User extends Model { public id!: number; public name!: string; public email!: string; public password!: string; public readonly createdAt!: Date; public readonly updatedAt!: Date; } User.init( { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, name: { type: DataTypes.STRING(100), allowNull: false, }, email: { type: DataTypes.STRING, allowNull: false, unique: true, }, password: { type: DataTypes.STRING(100), allowNull: false, }, }, { sequelize, tableName: 'users', timestamps: true, } ); export default User;
-
TypeORM
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm'; @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column({ type: 'varchar', length: 100 }) name: string; @Column({ type: 'varchar', unique: true }) email: string; @Column({ type: 'varchar', length: 100 }) password: string; @CreateDateColumn() createdAt: Date; @UpdateDateColumn() updatedAt: Date; }
-
Prisma
Prisma๋
schema.prisma
๋ผ๋ ํ์ผ์์ ์ ์ธํ๋ค.model User { id Int @id @default(autoincrement()) name String @db.VarChar(100) email String @unique password String @db.VarChar(100) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }
โtesterโ๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง ์ ์ ์กฐํ
-
Sequelize
import User from './models/User'; const user = await User.findOne({ where: { name: "tester', }, });
-
TypeORM
import { getRepository } from 'typeorm'; import { User } from './entities/User'; const userRepository = getRepository(User); const user = await userRepository.findOne({ where: { name: 'tester' }, });
-
Prisma
import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); const user = await prisma.user.findFirst({ where: { name: 'tester', }, });
โtesterโ๋ผ๋ ์ด๋ฆ์ ๊ฐ์ก๊ณ , ๋์ด๋ 25์ธ ์ด์, ๊ฐ์
์ผ์ด 2024-10-30
์ด์์ธ ์ ์ ๋ฅผ ์กฐํํ๊ณ ๋์ด์์ผ๋ก ์ ๋ ฌํ ํ 5๋ช
์ ์ถ์ถํ๋ค.
-
Sequelize
import { Op } from 'sequelize'; import User from './models/User'; const users = await User.findAll({ where: { name: "tester", age: { [Op.gte]: 25, }, createdAt: { [Op.gte]: new Date("2024-10-30"), }, }, order: [["age", "DESC"]], limit: 5, });
-
TypeORM
import { getRepository, MoreThanOrEqual } from 'typeorm'; import { User } from './entities/User'; const userRepository = getRepository(User); const users = await userRepository.find({ where: { name: "tester", age: MoreThanOrEqual(25), createdAt: MoreThanOrEqual(new Date("2024-10-30")), }, order: { age: "DESC", }, take: 5, });
-
Prisma
import { PrismaClient } from '@prisma/client'; const users = await prisma.user.findMany({ where: { name: "๊น๋ฏผ์", age: { gte: 25, }, createdAt: { gte: new Date("2023-01-01"), }, }, orderBy: { age: "desc", }, take: 5, });
Prisma < TypeORM < Sequelize
JPA๋ฅผ ์๋ ๊ฒฝ์ฐ
TypeORM < Prisma < Sequelize
Prisma < Sequelize ? TypeORM
์ฑ๋ฅ์ TypeORM์ด ๊ฐ์ฅ ์ข๊ธด ํ์ง๋ง ๊ทน๋จ์ ์ธ ์ฐจ์ด๋ ๋ํ๋์ง ์๋๋ค.
ํนํ Sequlize์ TypeORM์ ์ํฉ์ ๋ฐ๋ผ์ ์๋ ์ฐจ์ด๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋๋ฏ๋ก ๋๊ฐ ์ฐ์ธ์ธ์ง ํ์คํ๊ฒ ์ ์ ์๋ค.
Sequelize < TypeORM โค Prisma
์ด๊ฒ๋ ๋ฌ๋ ์ปค๋ธ์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ๋๋ง๋ค ๋ค๋ฅผ ์๋ ์๋ค๊ณ ์๊ฐํ๋ค.
Typescript๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์๋ง๋ Prisma๊ฐ ๊ฐ์ฅ ์ฌ์ฉ์ฑ์ด ์ข์ ์ ์๋ค. ์๋ํ๋ฉด ์ปดํ์ผ ๋จ๊ณ์ ํ์ ์ ๊ด๋ จ๋ ์๋ฌ๋ฅผ ์ฒดํฌํ ์ ์๊ธฐ ๋๋ฌธ์ ๊ทธ์ ๋ฐ๋ผ ํ์ ๊ด๋ จ๋ ์์ ์ ์ํํ ๋ ์ํ ํ ์ ์๋ค.
TypeORM์ ๋ค์ํ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ง์ํ๊ณ , ๋ณต์กํ ์ฟผ๋ฆฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ query builder ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์๋ค.
- ๐ฉ FE ๊ธฐ์ ์ ํ์ด์
- โจ ์ฐจํธ์ ๋ฐ์ํ ๊ตฌํ๊ณผ useRef ํ์ ๋ฌธ์
- ๐ฃ ๋ถ๋ชจ ์์์ ์ํ์ ๋ฐ๋ผ ์์ ์์๋ ์คํ์ผ ๋ณํ ๋ถ์ฌํ๊ธฐ
- ๐ zod ๋์ ํ๊ธฐ
- ๐ useInfiniteQuery๋ฅผ ์ฌ์ฉํ ๊ทธ๋ํ ๋ฌดํ์คํฌ๋กค ๊ตฌํ
- ๐ซ ์ฌ์ฉ์์ ์์ ๋ณํ ์๋ ๊ทธ๋ํ ์คํฌ๋กค ๊ตฌํํ๊ธฐ
- ๐งช ์๋ง์ ๊ทธ๋ํ ๋ฐ์ดํฐ ์์ฒญ์ ์ด๋ป๊ฒ ์ค์ผ๊น
- ๐ ๋คํฌ๋ชจ๋์์ ์๋ก๊ณ ์นจ ์ ๋ผ์ดํธ๋ชจ๋๊ฐ ์ ๊น ๋ณด์ด๋ ๋ฌธ์
- ๐ ์น์์ผ์ ์ฑํ ๋ฐ์ดํฐ์ REST API์ ์ฑํ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๊ด๋ฆฌํ๊ธฐ
- ๐ก BE ๊ธฐ์ ์ ํ ์ด์
- โ๏ธ Node WebSocket ํ๊ณ ๋ค๊ธฐ
- โ๏ธ TypeORM Datasource mock ๋ง๋ค๊ธฐ
- โ๏ธ oauth ID range ๋ฌธ์
- ๐ custom pipe์์ Nan์ด ๋ฐ์์ง๋ ๋ฌธ์
- ๐ช nest Websocket์ ์ธ์ ์ด ์๋๋ค๊ณ ?
- ๐ด nginx websocket ์ฐ๊ฒฐ ์ ๋ฌธ์ ๋ฐ์
- ๐ WebPush ๊ตฌํ
- ๐ง ์ฐ์ ์์ ํ๋ก ์์ฒญ ์ ์ดํ๊ธฐ
- ๐ websocket์ด ๋ฆ๊ฒ ํ ๋น๋์ด ๋ฐ์๋๋ ๋ฌธ์
- ๐ฅณ typeorm์ ์ด์ฉํ FCM ์๋ฆผ ์๋น์ค
- ๐ฆ ๋ค์ค ์ ์ ๋์์ฑ ์ ์ด โ ์ฑ๊ธํค, ๋ฎคํ ์ค
- ๐ ๊ทธ๋ํ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ ๊ณตํ๊ธฐ์ํ ์ ๋ต
- ๐ ๏ธ ์ธํ๋ผ ๊ธฐ์ ์คํ ์ ํ ์ด์
- ๐ Ncloud ์ค์ ๊ณผ์
- ๐ ORM ๊ธฐ์ ์คํ ๋น๊ต
- ๐ค RabbitMQ๋ก ๋ถ์ฐ ์๋ฒ์๊ฒ ๋ฉ์์ง๋ฅผ ๋ถ๋ฐฐํ๊ธฐ
- ๐ข private DB ์๋ฒ์ ์ ์ํ์ง ๋ชปํ๋ ํ์
- ๐ 1์ฃผ์ฐจ ๋ฐํ
- ๐ 2์ฃผ์ฐจ ๋ฐํ
- ๐ 3์ฃผ์ฐจ ๋ฐํ
- ๐ 4์ฃผ์ฐจ ๋ฐํ
- ๐ 5์ฃผ์ฐจ ๋ฐํ
- ๐ ์ต์ข ๋ฐํ