2023. 9. 16. 20:59ใ0. TiL ( Today I Learned )
์ฃผํน๊ธฐ์์ ๋ฐฐ์ด API์์ฑ, ๊ทธ๋ฆฌ๊ณ ERD๋ฅผ ์ ์ํ๋ค.
๊ต์ก๋ฐ์ ๋๋ณด๋ค ํ๋ก์ ํธ์ ์ค์ฝํ๊ฐ ์กฐ๊ธ ์ปค์ก๋ค๊ณ ๊ทธ๋งํผ ์์ฑ์๋ ์ด๋ ค์์ ๋๊ผ๋ค.
ERD๋ ์ปฌ๋ผ์ด ๋ช ๊ฐ ๋ ์๊ธฐ๋, ์ ๋ฆฌ๊ฐ ๋์ง ์๊ณ ์ฐ๊ฒฐ์ด ์ด๋๋ก ๋์ด์ผ ํ ์ง ๋ณต์กํด์ง๊ธฐ ์์ํ๋ค.
๊ทธ๋ฌ๋ค ๋ณด๋, API์์ฑ๊ณผ, schema๋ฅผ ์์ฑํ๋๋ฐ๋ ๊ณ์ ๋น ๊ณณ์ด ๋ฐ๊ฒฌ๋์๋ค.
ํ์ ์ ๊ฐ๋ฉด ์ด๊ฒ๋ณด๋ค ๋ช ๋ฐฐ๋ ๋ ํฐ ํ๋ก์ ํธ๋ฅผ ํ๊ฒ ๋ ๊ฑด๋ฐ, ๊พธ์คํ ๊ณต๋ถํด์ผ๊ฒ ๋ค!
ERD๋ง๋ค๊ธฐ : https://drawsql.app/teams/no-55/diagrams/prisma-community-hub
Prisma-Community-Hub | DrawSQL
Database schema diagram for Prisma-Community-Hub.
drawsql.app
[ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์ ]
# ํ๋ก์ ํธ๋ฅผ ์ด๊ธฐํํฉ๋๋ค.
yarn init -y
# ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํฉ๋๋ค.
yarn add express prisma @prisma/client cookie-parser jsonwebtoken
# nodemon ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ DevDependency๋ก ์ค์นํฉ๋๋ค.
yarn add -D nodemon
# ์ค์นํ Prisma๋ฅผ ์ด๊ธฐํ ํ์ฌ, Prisma๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ์์ฑํฉ๋๋ค.
npx prisma init
]Prisma model 1:1 ๊ด๊ณ ์ดํด๋ณด๊ธฐ
// schema.prisma
model Users {
userId Int @id @default(autoincrement()) @map("userId")
email String @unique @map("email")
password String @map("password")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
UserInfos UserInfos? // ์ฌ์ฉ์(Users) ํ
์ด๋ธ๊ณผ ์ฌ์ฉ์ ์ ๋ณด(UserInfos) ํ
์ด๋ธ์ด 1:1 ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
// ๋ฌผ์ํ๋ก ๋ํ๋๋ฉด ํด๋น ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ์ง ์์์๋ ์๋ค๋๊ฒ์ ๋ํ๋.
// ์ฆ userinfos์ด๊ธด ํ์ง๋ง, ํด๋น ๋ฐ์ดํฐ๊ฐ ์กด์ฌ ํ์ง ์์์๋ ์๋ค ๋ผ๋๊ฒ์ ๋ํ๋.
// ์ฌ์ฉ์์ ์ฌ์ฉ์์ ๋ณด๊ฐ ๊ด๊ณ๋ฅผ ๋งบ๊ณ ์๋ค๋๊ฒ์ ๋ํ๋
// model Users๋ ์ฐ๊ด๊ด๊ณ์ ์์ ์ปฌ๋ผ์ผ๋ฟ, ์ปฌ๋ผ์ ์๊ธฐ์ง์์!!!!!!
@@map("Users")
}
model UserInfos {
userInfoId Int @id @default(autoincrement()) @map("userInfoId")
UserId Int @unique @map("UserId") // ์ฌ์ฉ์(Users) ํ
์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค
name String @map("name")
age Int? @map("age")
gender String @map("gender")
profileImage String? @map("profileImage")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
// Users ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
// model user/info user์ userid๊ด๊ณ์ค์
// ๋๋ ์ฌ์ฉ์์ ๋ณดํ
์ด๋ธ์์๋ UserId ์ปฌ๋ผ์ ์ ์ ์คํ
์ด๋ธ์์๋ ์ ์ ์์ด๋ ์ปฌ๋ผ์ ์ฐธ์กฐํ ๊ฑฐ๋ค.
onDelete: Cascade -> ์ฌ์ฉ์์ ๋ณด๊ฐ ์ญ์ ๋๋ฉด ์ ๋ณด๋ ์ญ์ ๋๋ค.
@@map("UserInfos")
}
์ฌ์ฉ์(Users) ๋ชจ๋ธ์ ์ฌ์ฉ์ ์ ๋ณด(UserInfos) ๋ชจ๋ธ๊ณผ 1:1 ๊ด๊ณ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ฌ๊ธฐ์, 1:1 ๊ด๊ณ๋ ํ ์ฌ์ฉ์๊ฐ ํ๋์ ์ฌ์ฉ์ ์ ๋ณด๋ง ๊ฐ์ง ์ ์๊ณ , ํ ์ฌ์ฉ์ ์ ๋ณด๋ ํ ์ฌ์ฉ์์๊ฒ๋ง ์ํ ์ ์๋ค.
1:1 ๊ด๊ณ๋ฅผ ๋งบ์ ๋๋ ์๋์ ๊ฐ์ ๋ด์ฉ์ ํฌํจํด์ผ ํ๋ค.
๊ด๊ณ๋ฅผ ์ค์ ํ๋ ค๋ ๋ชจ๋ธ(UserInfos)์์ ์ด๋ค ๋ชจ๋ธ๊ณผ ๊ด๊ณ๋ฅผ ๋งบ์์ง(Users) ์ค์ ํด์ผ ํ๋ค.
๊ด๊ณ๋ฅผ ๋งบ๊ฒ ๋๋ ๋ชจ๋ธ(Users)์์ ์ด๋ค ๋ชจ๋ธ์ด ๊ด๊ณ๋ฅผ ๋งบ๋์ง(UserInfos) ์ค์ ํด์ผ ํ๋ค.
๊ด๊ณ๋ฅผ ๋งบ๊ฒ ๋๋ ๋ชจ๋ธ(Users)์์, ํ์ ์ ์ง์ ํ ๋, Optional Parameter(?) ์ง์ ํด์ค์ผ ํ๋ค.
→ ์ฌ์ฉ์๋ ์ฌ์ฉ์ ์ ๋ณด๊ฐ ์กด์ฌํ์ง ์์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฌ์ฉ์ ์ ๋ณด(UserInfos) ๋ชจ๋ธ์์๋,
Users
์ผ๋ฐ์ ์ธ Int, String๊ณผ ๊ฐ์ ํ์ ์ด ์๋, ์ฐธ์กฐํ ๋ค๋ฅธ ๋ชจ๋ธ์ ์ง์ ํ๋ค.
์ฌ์ฉ์(Users) ๋ชจ๋ธ์ ์ฐธ์กฐํ๋ฏ๋ก Users๋ก ์์ฑ๋์ด ์๋ค.
fields
์ฌ์ฉ์ ์ ๋ณด(UserInfos) ๋ชจ๋ธ์์ ์ฌ์ฉํ ์ธ๋ํค(Forien Key) ์นผ๋ผ์ ์ง์ ํ๋ค.
์ฌ๊ธฐ์ , UserId ์นผ๋ผ์ผ๋ก ์ธ๋ํค๋ฅผ ์ง์ ํ๋ค.
references
key: ์ฐธ์กฐํ๋ ๋ค๋ฅธ ๋ชจ๋ธ์ Column๋ฅผ ์ง์ ํ๋.
์ฌ๊ธฐ์ , ์ฌ์ฉ์(Users) ๋ชจ๋ธ์ userId ์นผ๋ผ์ ์ฐธ์กฐํ๋ค.
onDelete | onUpdate
์ฐธ์กฐํ๋ ๋ชจ๋ธ์ด ์ญ์ or ์์ ๋ ๊ฒฝ์ฐ ์ด๋ค ํ์๋ฅผ ํ ์ง ์ค์ ํ๋ค.
Cascade ์ต์ ์ ์ ํํ์ฌ ์ฌ์ฉ์๊ฐ ์ญ์ ๋ ๊ฒฝ์ฐ ๊ทธ์ ์ฐ๊ฒฐ๋ ์ฌ์ฉ์ ์ ๋ณด๋ ํจ๊ป ์ญ์ ๋๋๋ก ์ค์ ํ๋ค.
Prisma 1:N ์ฐ๊ด ๊ด๊ณ
// schema.prisma
model Users {
userId Int @id @default(autoincrement()) @map("userId")
email String @unique @map("email")
password String @map("password")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
UserInfos UserInfos? // ์ฌ์ฉ์(Users) ํ
์ด๋ธ๊ณผ ์ฌ์ฉ์ ์ ๋ณด(UserInfos) ํ
์ด๋ธ์ด 1:1 ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
Posts Posts[] // ์ฌ์ฉ์(Users) ํ
์ด๋ธ๊ณผ ๊ฒ์๊ธ(Posts) ํ
์ด๋ธ์ด 1:N ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
-> [] ๋ฐฐ์ด์ ์ฐ๋ฉด ํฌ์คํธ๋ฅผ ์ฌ๋ฌ๊ฐ ๊ฐ์ง๊ณ ์์์ ์๋ค๋๊ฒ์ ์ ์ถํ๋ฉด๋จ !!!
@@map("Users")
}
model Posts {
postId Int @id @default(autoincrement()) @map("postId")
UserId Int @map("UserId") // ์ฌ์ฉ์(Users) ํ
์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค
title String @map("title")
content String @map("content") @db.Text
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
// Users ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
@@map("Posts")
}
์ด๋ฐ 1:N ๊ด๊ณ๋ฅผ ์ค์ ํ ๋๋ ๋ค์๊ณผ ๊ฐ์ ๋ด์ฉ์ ํฌํจํด์ผ ํฉ๋๋ค.
๊ด๊ณ๋ฅผ ์ค์ ํ๋ ค๋ ๋ชจ๋ธ(Posts)์์ ์ด๋ค ๋ชจ๋ธ๊ณผ ๊ด๊ณ๋ฅผ ๋งบ์์ง(Users) ์ค์ ํด์ผ ํ๋ค.
๊ด๊ณ๋ฅผ ๋งบ๊ฒ ๋๋ ๋ชจ๋ธ(Users)์์ ์ด๋ค ๋ชจ๋ธ์ด ๊ด๊ณ๋ฅผ ๋งบ๋์ง(Posts) ์ค์ ํด์ผ ํ๋ค.
๊ด๊ณ๋ฅผ ๋งบ๊ฒ ๋๋ ๋ชจ๋ธ(Users)์์, ํ์
์ ์ง์ ํ ๋, ๋ฐฐ์ด ์ฐ์ฐ์([])๋ฅผ ์์ฑํด์ค์ผ ํ๋ค.
→ ์ฌ์ฉ์๋, ์ฌ๋ฌ ๊ฐ์ ๊ฒ์๊ธ์ ๊ฐ์ง ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ฌ ๊ฒ์๊ธ ๋ชจ๋ธ์ ๊ฒฝ์ฐ ์์ฑํ ์ฌ์ฉ์๊ฐ ํ์ ํํด(onDelete)ํ๊ฒ ๋ ๊ฒฝ์ฐ ์์ฑํ ๋ชจ๋ ๊ฒ์๊ธ์ด ์ญ์ ๋๋๋ก ๊ตฌํ๋์ด ์๋ค. ์ด๋ฐ ์ค์ ์ @relation ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ ์ง์ ํฉ๋๋ค.
// Users ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
์ฌ๊ธฐ์ `User`๋ ๊ฒ์๊ธ(`Posts`)์ด ์ฐธ์กฐํ๋ ๋ค๋ฅธ ๋ชจ๋ธ์ ์ง์ ํ๊ณ , `fields`๋ ๊ฒ์๊ธ(`Posts`) ๋ชจ๋ธ์์ ์ฌ์ฉํ ์ธ๋ํค ์นผ๋ผ์ ์ง์ ํ๋ค. `references`๋ ์ฐธ์กฐํ๋ ๋ค๋ฅธ ๋ชจ๋ธ์ ์ปฌ๋ผ์ ์ง์ ํ๊ณ , `onDelete`๋ ์ ์กฐํ๋ ๋ชจ๋ธ์ด ์ญ์ ๋ ๊ฒฝ์ฐ ์ด๋ค ํ์๋ฅผ ํ ์ง ์ค์ ํ๋ค.
`onDelete`์ ๊ฒฝ์ฐ, `Cascade` ์ต์
์ผ๋ก ์ฌ์ฉ์๊ฐ ์ญ์ ๋ ๊ฒฝ์ฐ ์ฐ๊ด๋ ๊ฒ์๊ธ ๋ํ ์ญ์ ๋๋๋ก ์ค์ ํ์์ต๋๋ค.
๋๊ธ(Comments) ๋ํ, **๊ฒ์๊ธ(Posts)**๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ์ฉ์(Users) ๋ชจ๋ธ๊ณผ 1:N ๊ด๊ณ๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์ต์ข ์ ์ผ๋ก ์์ฑ๋ Prisma model์ ์๋์ ๊ฐ๋ค.
// schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Users {
userId Int @id @default(autoincrement()) @map("userId")
email String @unique @map("email")
password String @map("password")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
UserInfos UserInfos? // ์ฌ์ฉ์(Users) ํ
์ด๋ธ๊ณผ ์ฌ์ฉ์ ์ ๋ณด(UserInfos) ํ
์ด๋ธ์ด 1:1 ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
Posts Posts[] // ์ฌ์ฉ์(Users) ํ
์ด๋ธ๊ณผ ๊ฒ์๊ธ(Posts) ํ
์ด๋ธ์ด 1:N ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
Comments Comments[] // ์ฌ์ฉ์(Users) ํ
์ด๋ธ๊ณผ ๋๊ธ(Comments) ํ
์ด๋ธ์ด 1:N ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
@@map("Users")
}
model Posts {
postId Int @id @default(autoincrement()) @map("postId")
UserId Int @map("UserId") // ์ฌ์ฉ์(Users) ํ
์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค
title String @map("title")
content String @map("content") @db.Text
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
// Users ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
Comments Comments[] // ๊ฒ์๊ธ(Posts) ํ
์ด๋ธ๊ณผ ๋๊ธ(Comments) ํ
์ด๋ธ์ด 1:N ๊ด๊ณ๋ฅผ ๋งบ์ต๋๋ค.
@@map("Posts")
}
model UserInfos {
userInfoId Int @id @default(autoincrement()) @map("userInfoId")
UserId Int @unique @map("UserId") // ์ฌ์ฉ์(Users) ํ
์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค
name String @map("name")
age Int? @map("age")
gender String @map("gender")
profileImage String? @map("profileImage")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
// Users ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
@@map("UserInfos")
}
model Comments {
commentId Int @id @default(autoincrement()) @map("commentId")
PostId Int @map("PostId") // ๊ฒ์๊ธ(Posts) ํ
์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค
UserId Int @map("UserId") // ์ฌ์ฉ์(Users) ํ
์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค
content String @map("content")
createdAt DateTime @default(now()) @map("createdAt")
updatedAt DateTime @updatedAt @map("updatedAt")
// Posts ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
Post Posts @relation(fields: [PostId], references: [postId], onDelete: Cascade)
// Users ํ
์ด๋ธ๊ณผ ๊ด๊ณ๋ฅผ ์ค์ ํฉ๋๋ค.
User Users @relation(fields: [UserId], references: [userId], onDelete: Cascade)
@@map("Comments")
}

ํ๋ด์ผํ๋๊น
ํ๋๋ ์งค๋ก ๋ง๋ฌด๋ฆฌ ํด๋ณธ๋น...
2์ฃผ ํ๋ก์ ํธ ํ์ดํ ...