๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Side project

[ํ”Œ์ ๊ธฐ๋ก] Next.js + Prisma + PlanetScale ์„ธํŒ…ํ•˜๊ธฐ (Vercel ๋ฐฐํฌ)

์ด ๊ธ€์€ ๋‹จ์ˆœํžˆ ์„ธํŒ…๋งŒ์„ ์œ„ํ•œ ๊ธ€์ด์ง€ ๋‚ด๋ถ€์ ์ธ ๋กœ์ง์ด๋‚˜ ์Šคํ‚ค๋งˆ ๋“ฑ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ์ „ํ˜€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉฐ, ์–ด๋– ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์—ญ์‹œ ๋‹ค๋ฃจ์ง€ ์•Š๋Š”๋‹ค.

PlanetScale์˜ https://planetscale.com/blog/how-to-setup-next-js-with-prisma-and-planetscale ๊ธ€์— ๊ธฐ์ดˆํ•œ ๋‚ด์šฉ์ด๋ฉฐ ํ•ด๋‹น ๊ธ€์˜ ๋™์˜์ƒ ๋ฒ„์ „(๋งํฌ) ๋„ ์ฐธ์กฐํ–ˆ๋‹ค. 

 

How to set up Next.js with Prisma and PlanetScale

A step-by-step guide for using PlanetScale and Prisma with Next.js.

planetscale.com

 

1. PlanetScale ๊ฐ€์ž… / ๋กœ๊ทธ์ธ ํ›„ Create New Database๋ฅผ ํ†ตํ•ด์„œ ์ƒˆ๋กœ์šด DB ์ƒ์„ฑ 

Organization ๋ณ„๋กœ 1๊ฐœ์˜ DB๊ฐ€ ๋ฌด๋ฃŒ๋กœ ์ œ๊ณต๋œ๋‹ค. ๋งŒ์•ฝ ์ด๋ฏธ 1๊ฐœ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด ์ƒˆ๋กœ์šด organization์„ ์ƒ์„ฑํ•œ ํ›„์— DB๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋œ๋‹ค. 

๋‚ด๊ฐ€ ์„ค์ •ํ•˜๊ณ ์ž ํ•˜๋Š” DB์˜ ์ด๋ฆ„์€ blog์ด๊ณ  ํŠœํ† ๋ฆฌ์–ผ์„ ๋“ค์„ ๋•Œ Region์˜ ๊ฒฝ์šฐ latency ๋•Œ๋ฌธ์— ๊ฐ€๊นŒ์šด ๊ณณ์œผ๋กœ ์„ค์ •ํ•˜๋ผ๊ณ  ํ•ด์„œ Tokyo๋กœ ์„ค์ •ํ•˜์˜€๋‹ค. 
์ƒ์„ฑ ์™„๋ฃŒ๋˜๋ฉด ๋Œ€์‹œ๋ณด๋“œ๊ฐ€ ๋œฌ๋‹ค. 

PlanetScale CLI๊ฐ€ ์„ค์น˜๋˜์–ด์žˆ๋‹ค๋ฉด(OS๋ณ„ ์„ค์น˜ ๋ฐฉ๋ฒ•์€ ์—ฌ๊ธฐ์„œ ํ™•์ธ) ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด์„œ๋„ DB์ƒ์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜๋กœ main ๋ธŒ๋žœ์น˜๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. 

 

2. Next.js ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

 

3. TailwindCSS ์„ค์น˜

๋จผ์ € 2๋ฒˆ์—์„œ ์ƒ์„ฑํ•œ ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™ํ•œ ๋‹ค์Œ ํ˜น์€ ์œ„์˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ž์‹ ์ด ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ ์—๋””ํ„ฐ์—์„œ ์—ด์–ด์ค€ ํ›„ ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ํ•˜๋‚˜์”ฉ ์ž…๋ ฅํ•˜์—ฌ TailwindCSS๋ฅผ ์„ค์น˜ํ•œ๋‹ค. 

 

4. Prisma ์„ค์น˜

ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด Prisma๋ฅผ ์„ค์น˜ํ•œ๋‹ค. 

 

5. Prisma ์„ค์ •

.envํŒŒ์ผ์—์„œ DATABASE_URL์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž์‹ ์ด ์ƒ์„ฑํ•œ PlanetScale DB ์ด๋ฆ„์„ ๋„ฃ์–ด ์ˆ˜์ •ํ•œ๋‹ค. 

 

6. Prisma Client ์„ค์ •

prisma > schema.prisma ํŒŒ์ผ์—์„œ client์™€ datasource๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ค€๋‹ค.
generator client์™€ datasource db๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

PlanetScale์€ ์™ธ๋ž˜ํ‚ค ์ œ์•ฝ์กฐ๊ฑด์„ ์ง€์›ํ•˜์ง€ ์•Š๊ณ  Prisma๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ด€๊ณ„ ํ‘œํ˜„ ์‹œ ์™ธ๋ž˜ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— PlanetScale๊ณผ Prisma๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ๋•Œ `referentialIntegrity` ์†์„ฑ์— ๋Œ€ํ•ด ์„ค์ •์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค. 

Because PlanetScale doesn’t support foreign key constraints and Prisma defaults to using foreign keys to express relations, we need to set this referentialIntegrity property when using Prisma with PlanetScale.

“Referential integrity is a property of a data set that states that all its references are valid. Referential integrity requires that if one record references another, then the referenced record must exist. For example, if a Post model defines an author, then the author must also exist.“ (Source: Prisma docs)

model ๋ถ€๋ถ„์€ ์ƒ˜ํ”Œ๋กœ ์ž์‹ ์ด ํ•„์š”ํ•œ ํ•ญ๋ชฉ๊ณผ ๋ฐ์ดํ„ฐ ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค. 

 

7. ๋กœ์ปฌ์—์„œ ๋Œ๋ ค๋ณด๊ธฐ

ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰์‹œ์ผœ ๊ธฐ๋ณธ ๋ธŒ๋žœ์น˜์ธ main ๋ธŒ๋žœ์น˜๋ฅผ ๋กœ์ปฌ์˜ 3309 ํฌํŠธ์™€ ์—ฐ๊ฒฐํ•œ๋‹ค. ๊ผญ 3309 ํฌํŠธ์ผ ํ•„์š”๋Š” ์—†๋‹ค. 
(๋งŒ์ผ 1๋ฒˆ์—์„œ ์ƒˆ๋กœ์šด organization์„ ์ƒ์„ฑํ•˜๊ณ  DB๋ฅผ ์ƒ์„ฑํ•˜์˜€๋‹ค๋ฉด, ์•„๋งˆ pscale์ด ์ด์ „ organization์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด ๊ฒฝ์šฐ์—๋Š” ๋จผ์ € `pscale org switch YOUR-ORGANIZATION-NAME-HERE`์„ ์ž…๋ ฅํ•˜์—ฌ ํ˜„์žฌ ์—ฐ๊ฒฐํ•  DB๊ฐ€ ์žˆ๋Š” organization์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค€๋‹ค. )

PlanetScale์˜ ์Šคํ‚ค๋งˆ๋ฅผ schema.prisma์˜ ํŒŒ์ผ์— ๋งž์ถ”๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. 

schema.prisma์— ์ž‘์„ฑํ•œ ๋‚ด์šฉ์ด PlanetScale ์Šคํ‚ค๋งˆ์— ์ž˜ ๋ฐ˜์˜์ด ๋˜์—ˆ๋Š”๊ฐ€๋Š” ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋กœ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. 

์œ„์—์„œ ์ž‘์„ฑํ•œ model์ด ์ž˜ ์ƒ์„ฑ๋œ ๊ฒƒ์„ ์•„๋ž˜์™€ ๊ฐ™์ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. (command: describe YOUR-MODEL-NAME; -- query๋Š” ์„ธ๋ฏธ์ฝœ๋ก ์œผ๋กœ ๋๋‚ด๊ธฐ!)

 

8. main ๋ธŒ๋žœ์น˜๋ฅผ production์œผ๋กœ promoteํ•˜๊ธฐ 

PlanetScale์˜ ๋ธŒ๋žœ์น˜์™€ ๊ด€๋ จ๋œ ๋‚ด์šฉ์— ๋Œ€ํ•ด ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. 

 

Branching - Documentation - PlanetScale

Create a development or staging environment for your database through branches

docs.planetscale.com

๋ธŒ๋žœ์น˜์˜ ๋‘ ์ข…๋ฅ˜์— ๋Œ€ํ•ด ์„ค๋ช…ํ•œ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์™€์„œ ๋ฒˆ์—ญํ•ด๋ณด์ž๋ฉด (๋”๋ณด๊ธฐ์—์„œ ํ™•์ธ)

๋”๋ณด๊ธฐ

PlanetScale provides two types of database branches:

  • Development branches — Development branches provide isolated copies of your production database schema where you can make changes, experiment, or run CI. Note, only the schema is copied, not the data.
  • Production branches — Production branches are highly available databases intended for production traffic. They are protected from direct schema changes by default and include automated daily backups. To make a change to a production branch, you must create a deploy request.

PlanetScale์€ ๋‘ ๊ฐ€์ง€ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ธŒ๋žœ์น˜๋ฅผ ์ œ๊ณตํ•œ๋‹ค:

  • ๊ฐœ๋ฐœ(Development) ๋ธŒ๋žœ์น˜ — ๊ฐœ๋ฐœ ๋ธŒ๋žœ์น˜๋Š” ๋ณ€๊ฒฝ, ์‹คํ—˜ ํ˜น์€ CI๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์šด์˜(production) ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ์˜ ๋…๋ฆฝ์ ์ธ ๋ณต์‚ฌ๋ณธ์„ ์ œ๊ณตํ•œ๋‹ค. ์Šคํ‚ค๋งˆ๋งŒ ๋ณต์‚ฌ๋˜๋Š” ๊ฒƒ์ด์ง€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณต์‚ฌ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹˜์„ ์œ ์˜ํ•˜๋ผ. 
  • ์šด์˜(Production) ๋ธŒ๋žœ์น˜ — ์šด์˜ ๋ธŒ๋žœ์น˜๋Š” ์šด์˜ ํŠธ๋ž˜ํ”ฝ์„ ์œ„ํ•œ ๊ณ ๊ฐ€์šฉ์„ฑ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค. ์šด์˜ ๋ธŒ๋žœ์น˜๋Š” ์ง์ ‘์ ์ธ ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์œผ๋กœ๋ถ€ํ„ฐ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณดํ˜ธ๋ฐ›์œผ๋ฉฐ ์ž๋™ํ™”๋œ ์ผ์ผ ๋ฐฑ์—…์ด ํฌํ•จ๋˜์–ด์žˆ๋‹ค. ์šด์˜ ๋ธŒ๋žœ์น˜์— ์ˆ˜์ •์‚ฌํ•ญ์ด ์ƒ๊ธฐ๋ฉด ๋ฐฐํฌ ์š”์ฒญ(deploy request)์„ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค. 

์•„๋ž˜์˜ ๋ช…๋ น์–ด๋กœ main ๋ธŒ๋žœ์น˜๋ฅผ promoteํ•  ์ˆ˜ ์žˆ๋‹ค. promote ํ›„์— main ๋ธŒ๋žœ์น˜๋Š” production์„ ์œ„ํ•œ ๋ธŒ๋žœ์น˜๊ฐ€ ๋˜๊ณ  main ๋ธŒ๋žœ์น˜์— ๋Œ€ํ•ด ์ง์ ‘์ ์ธ ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด ๊ธ€์„ ์ž‘์„ฑํ•˜๊ธฐ ์ „์— ํ…Œ์ŠคํŠธ ์‚ผ์•„ ๋งŒ๋“ค์–ด ๋ณธ DB์—์„œ ์ด ๋ธŒ๋žœ์น˜์— ๋Œ€ํ•œ ๊ฐœ๋…์„ ์ž˜ ๋ชจ๋ฅด๊ณ  promoteํ•œ ์ƒํƒœ์—์„œ ์Šคํ‚ค๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•ด์„œ ์—๋Ÿฌ๋กœ ๋‹นํ™ฉํ–ˆ๋˜ ์ ์ด ์žˆ๋‹ค. 

์ด ๊ธ€์—์„œ๋Š” ์šฐ์„  ๊ธฐ๋ณธ ์„ค์ •์„ ๋งˆ์น˜๊ณ  ๋ฐฐํฌํ•˜๋Š” ๊ฒƒ์— ์˜์˜๋ฅผ ๋‘๊ธฐ ๋•Œ๋ฌธ์— ํŠน๋ณ„ํžˆ ๊ตฌํ˜„ํ•ด๋†“์€ ๋‚ด์šฉ์ด ์—†์–ด main ๋ธŒ๋žœ์น˜๋ฅผ promoteํ•˜์ง€ ์•Š๊ณ  ๋ฐฐํฌํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ promote ํ•˜๋ ค๋ฉด ์•„๋ž˜์˜ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜๋ฉด ๋œ๋‹ค. 

๋งŒ์ผ ๋ธŒ๋žœ์น˜๋ฅผ promote ํ–ˆ๋Š”๋ฐ ์Šคํ‚ค๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผํ•œ๋‹ค๋ฉด? ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์˜ ๊ธ€์„ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค๐Ÿ‘‡

 

[ํ”Œ์ ๊ธฐ๋ก] PlanetScale branch ๋ณ€๊ฒฝ ๋ฐ deploy request (Prisma String์˜ default ๊ฐ’)

[ํ”Œ์ ๊ธฐ๋ก] Next.js + Prisma + PlanetScale ์„ธํŒ…ํ•˜๊ธฐ (Vercel ๋ฐฐํฌ) ์ด ๊ธ€์€ ๋‹จ์ˆœํžˆ ์„ธํŒ…๋งŒ์„ ์œ„ํ•œ ๊ธ€์ด์ง€ ๋‚ด๋ถ€์ ์ธ ๋กœ์ง์ด๋‚˜ ์Šคํ‚ค๋งˆ ๋“ฑ์— ๋Œ€ํ•œ ์„ค๋ช…์ด ์ „ํ˜€ ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉฐ, ์–ด๋– ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ ์ธ

birdmee.tistory.com

 

9. Production์œผ๋กœ ๋ฐฐํฌํ•˜๊ธฐ

์ฒ˜์Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ƒ์„ฑํ–ˆ๋˜ PlanetScale๋กœ ์ ‘์†ํ•˜์—ฌ ์ž์‹ ์ด ๋งŒ๋“  DB ํ”„๋กœ์ ํŠธ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๋ณด๋ฉด Connect ๋ฒ„ํŠผ์ด ๋ณด์ธ๋‹ค. ํด๋ฆญํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ™”๋ฉด์ด ๋ณด์ธ๋‹ค. 

Connect with์—์„œ Prisma๋ฅผ ์„ ํƒํ•˜๊ณ  ๊ทธ๋Ÿผ Database authentication credentials์— Username๊ณผ Password๊ฐ€ ๋ณด์—ฌ์ง€๊ณ  .env์— DATABASE_URL์ด ๋ณด์—ฌ์ง„๋‹ค. ๋ฐฐํฌ ์‹œ์— ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž˜ ๋ฉ”๋ชจํ•ด๋‘”๋‹ค. 

์—ฌ๊ธฐ๊นŒ์ง€ ์™„๋ฃŒ ํ›„์— GitHub ์ฝ”๋“œ์ €์žฅ์†Œ์— commit ํ›„ push ํ•ด์ฃผ์—ˆ๋‹ค. 

๋ฐฐํฌ๋Š” ์ž์‹ ์ด ํŽธํ•œ ๊ณณ์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” Vercel์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐํฌํ•œ๋‹ค. 

Vercel ์‚ฌ์ดํŠธ์—์„œ ๊ฐ€์ž… / ๋กœ๊ทธ์ธ ์ง„ํ–‰ ํ›„ New Project๋ฅผ ํ†ตํ•ด GitHub์— ์žˆ๋Š” ์ฝ”๋“œ์ €์žฅ์†Œ๋ฅผ import ํ•ด์ฃผ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ์ด๋ฏธ ์ฝ”๋“œ์ €์žฅ์†Œ ์ „์ฒด๊ฐ€ ๋ณด์ด๋„๋ก ๊ถŒํ•œ ์„ค์ •์„ ํ•ด๋‘” ๋ถ„๋“ค์€ ๋ฌธ์ œ ์—†๊ฒ ์ง€๋งŒ ์—๋Ÿฌ๊ฐ€ ๋œจ๊ฑฐ๋‚˜ ๋ฐฐํฌํ•˜๊ณ ์žํ•˜๋Š” ์ฝ”๋“œ์ €์žฅ์†Œ๊ฐ€ ๋ณด์ด์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋Š” GitHub์—์„œ ๊ถŒํ•œ์„ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ทธ ๋ถ€๋ถ„๊นŒ์ง€๋Š” ๋‹ค๋ฃจ์ง€ ์•Š๋Š”๋‹ค. ํ”„๋กœ์ ํŠธ(์ฝ”๋“œ์ €์žฅ์†Œ)๋ฅผ ์„ ํƒํ•˜๊ณ  Import๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํ™”๋ฉด์ด ๋œฌ๋‹ค. 

์—ฌ๊ธฐ์„œ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผํ•  ๋ถ€๋ถ„์€ Environment Variables์ด๋‹ค. ๋ฐ”๋กœ ์ „ ๋‹จ๊ณ„์—์„œ ๋ฉ”๋ชจํ•ด๋‘” ํ˜น์€ ๋ณต์‚ฌํ•ด๋‘” DATABASE_URL์˜ ๊ฐ’์„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ €์žฅํ•ด์ค€๋‹ค. ์ถ”๊ฐ€ ํ›„ Add๋ฅผ ๋ˆ„๋ฅด๋Š”๋ฐ ๊ฐ’์—๋Š” ๋”ฐ์˜ดํ‘œ๋ฅผ ์ œ๊ฑฐ ํ›„ ๋„ฃ์–ด์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  Deploy ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์™„๋ฃŒ!