본문 바로가기
CS/Database

[Database] post CRUD 서버 애플리케이션 만들기(3)

by 디스코비스킷 2025. 5. 22.
반응형

film_post CRUD 서버 애플리케이션 만들기

  • 앞선실습 CASE STUDY에서 생성한 테이블 film_post 사용
  • express.js Post CRUD 애플리케이션
  • prisma로 DB와 통신
  • migration 기능 써보기

1. 준비

film_post 테이블생성

CREATE TABLE film_post (
  post_id SERIAL PRIMARY KEY,
  film_id int,
  content text,
  created_at timestamp,
  updated_at timestamp
);

ALTER TABLE "film_post" ADD FOREIGN KEY ("film_id") REFERENCES "film" ("film_id");

 

film_post 데이터 INSERT 코드

INSERT INTO public.film_post (film_id, content, created_at, updated_at) VALUES
(1, 'A fascinating insight into the making of "ACADEMY DINOSAUR". Discover the behind-the-scenes struggles and triumphs!', '2024-09-01 08:00:00', '2024-09-01 08:00:00'),
(2, 'Check out the trailer for "ACE GOLDFINGER" and see how it compares to the final cut. A must-watch for fans of action and adventure!', '2024-09-01 09:00:00', '2024-09-01 09:00:00');

조회때 사용할 2건만 있으면 될듯.

 

서버 관련 패키지 추가

npm i express morgan dotenv cors cookie-parser
npm i -D nodemon

 

파일구조

src
├── feature
│   ├── post
│   │   ├── controller.mjs
│   │   ├── model.mjs
│   │   └── router.mjs
├── index.mjs

javascript를 commonJS가 아닌 ES module로 사용하기위해 mjs로 확장자를 설정한다.

 

package.json에 script 추가

  "scripts": {
    "start": "node src/index.mjs",
    "dev": "nodemon src/index.mjs"
  },

2. 서버 설정

src/index.mjs

import cookieParser from "cookie-parser";
import cors from "cors";
import dotenv from "dotenv";
import express from "express";
import morgan from "morgan";
import { postRouter } from "./feature/post/router.mjs";

// .env 파일 불러오기
dotenv.config();

// HTTP 서버 생성
const app = express();

// CORS 설정
const corsOrigin = ["http://localhost:5173", "http://localhost:3000"];

app.use(
  cors({
    origin: corsOrigin,
    methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
    preflightContinue: false,
    optionsSuccessStatus: 204,
    credentials: true,
  })
);

// 쿠키, body 파싱
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// HTTP 요청 로깅
app.use(
  morgan(":method :url :status :res[content-length] - :response-time ms")
);

app.use("/post", postRouter);

// Health Check
app.get("/health", (_, res) => {
  return res.status(200).json({
    message: "health check",
  });
});

// 나머지 요청은 모두 404
app.use((_, res) => {
  return res.status(404).json({
    error: "Not Found",
  });
});

app.listen(8090, () => console.log("Listening to 8090..."));

 

 

서버실행 npm run start 하자,
PrismaClient not found 에러가 뜸

import { PrismaClient } from "@prisma/client";
         ^^^^^^^^^^^^
SyntaxError: PrismaClient. The requested module '@prisma/client' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@prisma/client';
const { PrismaClient } = pkg;

이 에러는 ESM(ECMAScript Module) 환경에서 @prisma/client를 CommonJS 방식으로 import하려 해서 생기는 문제이다.

 

해결방법은,

schema.prisma에서 client에 output추가 후 npx prisma generate한다.

generator client {
  provider = "prisma-client-js"
  output = "../node_modules/.prisma/client"
}

서버가 잘 돌아감!

 

관련글1: stackoverflow
관련글2: velog @danceintherain

3. Post CRUD 서버 개발하기

src/feature/model.mjs

import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();

export const postFindMany = async () => prisma.film_post.findMany({});
export const postFindOne = async (post_id) => prisma.film_post.findUnique({
  where: {
    post_id
  }
});
export const postCreateOne = async (post) =>  prisma.film_post.create({
  data: post
});
export const postUpdateOne = async (id, post) =>  prisma.film_post.update({
  where: {
    post_id: id
  },
  data: post
});
export const postDeleteOne = async (post_id) => prisma.film_post.delete({
  where: {
    post_id
  }
});

src/feature/router.mjs

import express from "express";
import { createOne, deleteOne, getAll, getOne, updateOne } from "./controller.mjs";

const router = express.Router();
router.get("/", getAll);
router.get("/:id", getOne);
router.post("/", createOne);
router.put("/:id", updateOne);
router.delete("/:id", deleteOne);

export const postRouter = router;

src/feature/controller.mjs

import { postCreateOne, postDeleteOne, postFindMany, postFindOne, postUpdateOne } from "./model.mjs";

export const getAll = async (req, res) => {
  try {
    const result = await postFindMany();
    if (!result) return res.status(404).json({ error: "Not Found " });
    return res.json({ data: result });
  } catch (e) {
    return res.status(500).json({ error: e.stack });
  }
};

export const getOne = async (req, res) => {
  const id = Number(req.params.id);
  if (!id) return res.status(404).json({ error: "Not Found" });

  try {
    const result = await postFindOne(id);
    return res.json({ data: result });
  } catch (e) {
    return res.json({ error: e.stack });
  }
};

export const createOne = async (req, res) => {
  const body = req.body
  if (!body) return res.status(400).json({ error: "Bad Request" });

  try {
    const result = await postCreateOne(body);
    return res.json({ data: result });
  } catch (e) {
    return res.json({ error: e.stack });
  }
}

export const updateOne = async (req, res) => {
  const body = req.body
  const id = req.params.id
  if (!body) return res.status(400).json({ error: "Bad Request" });

  try {
    const result = await postUpdateOne(Number(id), body);
    return res.json({ data: result });
  } catch (e) {
    return res.json({ error: e.stack });
  }
}


export const deleteOne = async (req, res) => {
  const id = Number(req.params.id);
  if (!id) return res.status(404).json({ error: "Not Found" });

  try {
    const result = await postDeleteOne(id);
    return res.json({ data: result });
  } catch (e) {
    return res.json({ error: e.stack });
  }
};

4. Postman으로 데이터 CRUD 해보기

먼서 서버실행을 npm run dev("nodemon src/index.mjs")로 nodemon으로 실행한다.
file이 변경될때마다 서버가 재실행된다.

 

브라우저로는 get요청밖에 못보내서(클라이언트 개발X)
postman을 사용해본다.

 

왼쪽 메뉴에서 첫번째 collection을 눌러 컬렉션과 폴더를 추가하고
각 요청별로 Add request로 추가한다.

Create

 

Read


getAll, getOne요청

잘 읽어온다.

Update

updated_at?를 실수로 지웠더니 not null설정이 돼서
다시 붙여주고 npx prisma migrate 했다.

다시 새글을 작성하고 post요청 보냈는데 성공.

Delete

잘 지워진다.

 

반응형

최근댓글

최근글

© Copyright 2024 ttutta