-
[TIL] 아이템 시뮬레이터 2 과제 시작 - 1일 차 (관계형 DB로 전환하기)TIL-sparta 2024. 5. 23. 21:17
> 작성 개요나 특이사항 등 알아야 할 정보가 있으면 간단하게 작성, 없을 시 스킵
학습 키워드: ERD, Prisma, multiSchema, SQL, RDBMS
관계형 DB로 전환하기
1) 과제 요구사항:
이번에 발제된 과제는 지난번 아이템 시뮬레이터 과제를 기반으로 MongoDB를 빼고 RDBMS로 전환하는 과정 및 여러가지 주요 기능들의 구현이 요구사항에 추가되었다. 기능의 추가에 따라 테이블 또한 세분화되어 나뉘게 되었는데, 그 중에서 Item 테이블만 다른 DB에서 관리하도록 하라는 조건이 추가되었다. DB 구조 ER 다이어그램은 검색을 통해 구조를 익힌 뒤 아래와 같이 작성했다.
2) 발생한 문제 (Prisma와 multiSchema):
// schema.prisma generator client { provider = "prisma-client-js" previewFeatures = ["multiSchema"] } datasource db { provider = "mysql" url = env("DB_URL") schemas = ["base", "item"] } // ------------------------ model Users { userId Int @id @default(autoincrement()) @map("user_id") username String @unique @map("username") password String @map("password") characters Characters[] @@map("Users") @@schema("base") } model Characters { characterId Int @id @default(autoincrement()) @map("character_id") characterName String @unique @map("character_name") health Int @default(500) @map("health") power Int @default(100) @map("power") money Int @default(1000) @map("money") users Users @relation(fields: [userId], references: [userId], onDelete: Cascade) userId Int inventories Inventories[] equipments Equipments[] @@map("Characters") @@schema("base") } ... model Items { itemCode Int @id @map("item_code") itemName String @unique @map("name") itemHealth Int @map("item_health") itemPower Int @default(0) @map("item_power") itemPrice Int @default(0) @map("item_price") inventories Inventories[] equipments Equipments[] @@map("Items") @@schema("item") }
강의에서 다룬 내용에는 다른 데이터베이스의 테이블을 참조하는 방법이 나와있지 않아서 여기저기 찾아봤는데, Prisma 공식 문서에서 multiSchema 라는 기능을 발견해서 작성해둔 ER Diagram에 맞춰 그대로 적용해보았다. 그런데 막상 npx prisma db push를 진행해보니 MySQL을 대상으로는 multiSchema 기능을 지원하지 않는다고 하는 에러가 출력됐다. postgres 인스턴스를 하나 만들어서 테스트를 해보려 했는데, pg_hba.conf 문제로 접속이 안되기도 하고, 이게 원하는 기능이 아닐거라는 이야기를 들어서 일단 보류하고 강사님이 제시해주신 방식으로 먼저 해결하기로 했다.
3) 해결 방안 (multiple schema files):
// schema1.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DB_URL") } // ------------------------ model Users { userId Int @id @default(autoincrement()) @map("user_id") username String @unique @map("username") password String @map("password") characters Characters[] @@map("Users") } ...
// schema2.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("ITEM_DB_URL") } model Items { itemCode Int @id @map("item_code") itemName String @unique @map("name") itemHealth Int @map("item_health") itemPower Int @default(0) @map("item_power") itemPrice Int @default(0) @map("item_price") @@map("Items") }
일단 schema 파일을 두 개로 분리하여 각각 다른 database를 생성하도록 설정했다. 이렇게 해두면 두 데이터베이스의 테이블 간 참조가 불가능해지기 때문에 서버에서 작성한 코드로 무결성을 관리해줘야 한다. 현업에서는 따로 무결성 체크용 프로그램을 제작하여 별도의 위치에서 서버와 DB를 감시하는 방식으로도 구현하는 경우가 있다고 한다.
npx prisma db push --schema prisma/schema1.prisma npx prisma db push --schema prisma/schema2.prisma
이후 각각의 schema를 db에 push해주면 두 개의 DB와 그에 속한 table 들이 생성된다. 그런데 하나를 push할 때마다 이전에 push한 내용이 index.d.ts 파일에서 지워지는 문제가 있다. 해결 방법을 찾아봐야겠다.
4) multiSchema:3)번 처럼 설정하고 난 뒤 item 라우터의 post가 동작하는 것을 확인하고 다시 2) 로 돌아가서 RDS의 pg 인스턴스에서 parameter config 설정을 변경하여 접속이 안되던 문제를 해결해줬다. 이후 원래 작성해뒀던 multiSchema를 사용한 schema.prisma 파일을 push했다. 생성된 DB의 구조를 살펴보니 이름 그대로 다중 스키마로 되어있고, DB는 하나로 통일되어 있어 원래 원하던 '분리된 DB와 하나의 schema'라는 형식과는 차이가 있었다.
몇 시간 전에 열심히 찾고 있을 때는 'foreign key는 ref를 해야한다'는 강박에 사로잡혀 있었는데, 애초에 같은 데이터베이스 내의 테이블이 아니라면 ref를 설정할 수 없다(Trigger나 CDF 등을 이용하면 유사한 기능을 만들 수는 있다)고 한다. Prisma의 schema를 만들면서 검색을 해서 계속 reference와 schema 같은 키워드를 사용해서 검색한게 문제였나보다. SQL, relation 등의 키워드로 다시 검색해보니 애초에 다른 DB의 table끼리 지속적인 참조와 갱신 등이 필요한 상황이라면 두 table을 같은 DB에 두는 것이 옳다는 의견이 있었다. 과제의 케이스는 단지 현업에서 Item 테이블을 관리하는 부서가 달라 DB를 나누어 둔 특수한 상황에서 가능한 임기응변식 대처를 미리 경험해보는 느낌으로 구성하셨다고 한다.
이렇게 과제의 핵심 요구사항인 'RDBMS로 전환하기' 부분의 가장 큰 고비를 넘겼다. API 명세서 작성을 마무리한 뒤 본격적으로 과제 스크립트 작성에 집중하면 되겠다.
--
REFERENCES:
> 과제 spec
> 개발중인 개인 과제 repo
> prisma.io, "How to use Prisma ORM with multiple database schemas"
> stackoverflow.com, "Relationships between tables from different databases", 답변 참고
728x90'TIL-sparta' 카테고리의 다른 글
[TIL] 프로그래머스 - 피로도 문제 풀이 (Java, DFS) (0) 2024.05.25 [TIL] 스파르타) 아이템 시뮬레이터 2 과제 진행 - 3일 차 (bcrypt) (0) 2024.05.24 [TIL] 스파르타) Node.js 숙련주차 강의 수강 - 3일 차 (JWT) (0) 2024.05.22 [TIL] 스파르타) Node.js 숙련주차 강의 수강 - 2일 차 (Cookie, Session) (0) 2024.05.21 [TIL] 스파르타) Node.js 숙련주차 강의 수강 (AWS RDS, Prisma) (0) 2024.05.20