ORM (Object Relational Mapping) 이란?
객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것을 말합니다.
일종의 번역기라 보면 되는데, 자바스크립트(타입스크립트) 코드와 DB 사이를 연결해주는 것입니다.
schema.prisma 는 데이터베이스에 대한 모든 설명을 담은 파일입니다.
Prisma
extension 을 설치해줍니다.npm i prisma -D
: prisma 설치npx prisma init
: prisma 초기 세팅// prisma/schema.prisma
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql" //
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement()) // id로 구분할수 있으며 디폴트로 증가하는 값이다.
phone Int? @unique // 옵셔널한 Int값이며 유니크하다
email String? @unique
name String
avatar String?
createdAt DateTime @default(now()) // 현재날자를 디폴트로한다
updatedAt DateTime @updatedAt // 업데이트마다 이 필드가 변한다
}
brew install planetscale/tap/pscale
brew install mysql-client
brew upgrade pscale
: 최신버전으로 업데이트pscale auth login
: 계정로그인명령어 | --- |
---|---|
pscale region list | 서버 목록을 보여준다 |
pscale database create <DB이름> | DB를 생성한다 |
pscale database create <DB이름> -region <SLUG명> | 해당 지역 서버에 DB를 생성한다. |
pscale connect <DB명> | PlanetScale서버의 DB와 연결한다. |
npx prisma db push | DB정보를 push한다 |
npx prisma studio | prisma studio 열기 |
pscale database create <DB이름> -region ap-northeast
로 도쿄 서버에 DB를 생성합니다.보통 DB 플랫폼에서는 DB를 만들면 암호를 생성하고 관리해야 하는데 보안에 취약할 수 있기 때문에, 진짜DB 대신 서버를 작동시킬수 있는 가짜DB 를 사용합니다. 이 후 실제 배포할 때 AWS 나 Heroku를 이용하면 됩니다.
planetscale 에서는 보안 tunnel 을 사용할 수 있습니다(가짜 DB를 다운받고 설치하고 실행할 필요가 없고, .env 에 정보를 보관할 이유도 없습니다.)
pscale connect <DB명>
를 하면 PlanetScale 서버의 DB와 연결됩니다..env
의 DATABASE_URL 에 넣어줍니다.// .env
DATABASE_URL = "mysql://127.0.0.1:3306/<DB명>";
planetscale
은mysql
과 '호환'되는 플랫폼입니다. 이 호환을 위해서 몇가지 처리해줄 것이 있습니다.
foreign key
제약
>planetscale
은mysql
과 달리foreign
키로 DB에 해당 데이터가 있는지 체크하는 기능이 없기 때문에 안정성을 보완해줘야 합니다.
schema.prisma
파일의 datasource db
에다가 relationMode ="prisma"
를 추가해줍니다.// schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
npx prisma db push
를 하면 schema.prisma 를 읽고 해당 정보를 push 합니다.Prisma Client 가 생성됨
npx prisma studio
npm i @prisma/client
client.ts
파일을 만듭니다client.ts
파일에 다음을 작성합니다.import { PrismaClient } from "@prisma/client";
export default new PrismaClient();
npx prisma generate
를 하면 node_modules/.prisma/client/index.d.ts 에 우리의 스키마에 해당하는 type 이 생성된 걸 알 수 있습니다.6. 또한 PrismaClient 의 인스턴스로 자동완성으로 user모델을 찾을 수 있는 걸 알 수 있습니다.
사용예시
// libs/client.ts
import { PrismaClient } from "@prisma/client";
const client = new PrismaClient();
client.user.create({
data: {
id: 12,
name: "helo",
},
});
export default client;
PrismaClient 는 브라우저에서 작동하진 않습니다. 왜냐면 db에 접근할수 있는 파일을 프론트엔드인 브라우저에 추가하기 때문
// pages/indes.tsx
import "../libs/client"; // 에러발생
react
는 프론트엔드를, node.js
는 백엔드를 다뤄야 합니다.NextJS
는 API 를 만들기 위해 반드시 서버를 따로 구축할 필요가 없습니다!pages/api
폴더를 생성하면 NextJS 서버에 API 가 생성됩니다.api 폴더 내의 파일은
export default
로 함수를 내보내야 합니다.
pages/api
폴더에서 connection 핸들러
인 함수를 export default
합니다.// pages/api/client-test.tsx
import { NextApiRequest, NextApiResponse } from "next";
export default function handler(req: NextApiRequest, res: NextApiResponse) {
res.json({
ok: true,
data: "abc",
});
}
NextApiRequest
NextApiResponse
json
이 나옵니다client-test 에 PrismaClient 를 import 해보자
// pages/api/client-test.tsx
import { NextApiRequest, NextApiResponse } from "next";
import client from "../../libs/client";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
await client.user.create({
data: {
email: "abc@naver.com",
name: "hello",
},
});
// res.status(200).end(); 로 하면 항상 200 신호를 보냅니다
res.json({
ok: true,
});
}
(브라우저) 핸들러가 실행되면 DB를 업데이트하고 다음 json을 리턴합니다.
(PrismaStudio) DB가 업데이트 된 모습
유효한 form 에서 submit
// enter.tsx
const [submitting, setSubmitting] = useState(false);
const { register, handleSubmit, reset } = useForm<EnterForm>();
const onValid = (data: EnterForm) => { // submit 이 유효할 경우 작동
setSubmitting(true);
fetch("/api/users/enter", {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
}).then(() => {
setSubmitting(false);
});
};
// return (
<form
onSubmit={handleSubmit(onValid)}
className='flex flex-col mt-8 space-y-4'>
// pages/api/users/enter.tsx
import { NextApiRequest, NextApiResponse } from "next";
import client from "../../../libs/client";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
res.status(401).end(); // POST 가 아닌 메소드로 보내면 에러발생
}
console.log(req.body.email); // undefined 나올수 있음
console.log(req.body); // {"email":"abc@naver.com"}
res.status(200).end();
}
req.body
는 'req의 인코딩'을 기준으로 parse
하기 때문에 req.body.email
로 접근하면 undefined
가 나옵니다프론트
에서 요청할 때 headers
를 설정해줘야만 합니다 : header : { "Content-Type" : "application/json" }
tsconfig.json
파일에서 baseUrl: "."
를 추가합니다 : 프로젝트의 baseUrl 을 tsconfig.json
파일의 위치로 함paths
추가합니다 : 파일과 컴포넌트들을 어떻게 import 할지 정합니다.{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@libs/*": ["libs/*"], // "@libs/*" 라는 경로는 libs폴더를 의미한다.
"@components/*": ["components/*"]
}
}
}