Nextjs에 PostgreSQL 백앤드 달기

힘센캥거루
2025년 10월 5일(수정됨)
6
72

백앤드를 간단하게 구현해서 회원가입을 구현해 놓았는데, 이상하게도 그 이상은 손이 가질 않았다.

아마도 Prisma와 PostgreSQL을 하긴 했으나, 누군가의 글을 읽으며 수동적으로 한 것이라 제대로 익히지 못한 것이 문제인 것 같았다.

그래서 직접 한번 구현해보기로 했다.

1. PostgreSQL 설치하기

먼저 homebrew로 postgresql을 설치해준다.

윈도우일 경우에는 choco를 설치해서 하면 쉽게 가능하다.

그리고 services start로 자동 시작하도록 만들어 준다.

# 맥북인 경우
brew install postgresql
brew services start postgresql

아래 명령어를 입력해서 정상적으로 접속이 된다면 설치가 끝난 것.

postgreSQL은 서버-클라이언트 구조라서 postgre 서버가 실행중이어야 db에 접속할 수 있다.

psql postgres
Nextjs에 PostgreSQL 백앤드 달기-1

이제 유저와 db를 설정해주자.

유저의 이름은 testuser, 비밀번호도 testuser로 설정해주었다.

CREATE USER testuser WITH PASSWORD 'testuser';
\du
Nextjs에 PostgreSQL 백앤드 달기-2

자꾸 유저가 만들어지지 않아서 확인해 봤더니, 맨 끝에 세미콜론을 꼭 붙여주어야 명령어가 끝난다.

그리고 database도 하나 만들어주자.

CREATE DATABASE testdb;

그리고 \l\list로 데이터베이스를 확인해준다.

Nextjs에 PostgreSQL 백앤드 달기-3

여기서 위쪽에 있는 db 3개는 기본적으로 생성되는 것이다.

삭제하면 문제가 될 수 있으니 그대로 두는게 좋다.

2. Prisma 설치

이제 프리즈마를 설치해주자.

나는 prismaTest라는 폴더를 하나 만들어주었다.

npm써도 되는데, 나는 그냥 yarn으로 초기화를 해주었다.

yarn

그리고 프리즈마를 설치해준다.

npx명렁으로 프리즈마 초기 세팅을 만들어준다.

prisma init 실행시 폴더 하나에 프리즈마 설정 파일들이 생성된다.

참고로 npx는 npm 패키지를 설치하지 않고도 실행하게 해주는 명령어 도구이다.

yarn add prisma
npx prisma init

3. PostgreSQL 연결 설정

이제 prisma/schema.prisma.env로 들어가서 환경설정을 수정해주자.

파일 내부에서 아래와 같이 설정을 바꾸어 주면 된다.

DATABASE_URL="postgresql://아이디:비밀번호@localhost:5432/데이터베이스이름?schema=public"

4. schema.prisma 설정

이제 데이터베이스의 스키마를 설정해주자.

기본적으로는 아래와 같이 스키마가 들어있다.

generator client {
  provider = "prisma-client-js"
  output   = "../generated/prisma" <-- 이 줄 삭제할 것!
}

datasource db {
  provider = "postgresql"
  url  = env("DATABASE_URL")
}

이제 이걸 자유롭게 바꿔주면 된다.

문제는 스키마 설정을 좀 배워야 한다는 것.

예를들어 아래와 같은 스키마가 있다고 해보자.

model User {
  id    Int @id @default(autoincrement())
  email String  @unique
  name  String?
}

➡️ model User { ... }은 데이터베이스 테이블 명이다.

➡️ id Int @id @default(autoincrement())

  • 이 필드는 기본키이고, 숫자가 1, 2, 3… 자동으로 채워진다.

요소

의미

id

필드(열, 컬럼) 이름

Int

자료형 = 정수형

@id

이 필드는 Primary Key이다

@default(autoincrement())

기본값은 자동 증가 숫자

➡️ email String @unique

  • email 값은 고유해야 하며, 같은 이메일을 가진 사용자가 두 명 이상 존재할 수 없다.

요소

의미

email

필드 이름

String

문자열 타입

@unique

중복 불가 (Unique 제약조건)

➡️ name String?

  • name은 있어도 되고 null이어도(없어도) 된다.

    요소

    의미

    name

    필드 이름

    String?

    문자열 타입인데 ?nullable(널 허용) 의미

그래서 프리즈마의 데코레이터를 정리하면 아래와 같다.

데코레이터

의미

@id

기본키 지정

@default(...)

기본값 설정

@unique

고유값 제약조건

@relation(...)

관계 설정 (외래키, 연결된 테이블)

@map("db_column")

실제 DB에서의 컬럼명을 지정

?

해당 필드는 nullable (값이 없을 수도 있음)

[]

배열 (예: String[] = 문자열 배열)

@필드명

필드의 타입이 datetime일 때, 데이트 수정시 현재의 날짜로 자동갱신

5. 마이그레이션 실행

DB에 모델을 반영하기 위해 마이그레이션을 해준다.

맨 뒤에 이름은 자유롭게 정해도 된다.

npx prisma migrate dev --name testMyDB
## --name 뒤에 마이그레이션 이름 입력

6. Prisma Client 사용 예시

이제 간단한 서를 만들어서 백앤드에서의 CRUD를 테스트 해보자.

서버는 익스프레스로 만들것이다.

yarn add @prisma/client express

위의 명령어로 먼저 설치를 해준다.

index.js파일을 생성 후 아래와 같이 입력한다.

그리고 터미널에서 node index.js를 실행하면 서버가 실행된다.

const express = require('express');
const { PrismaClient } = require('@prisma/client');

const app = express();
const prisma = new PrismaClient();

app.use(express.json());
const port = 3001;

app.get("/", (req, res)=> {
   const body = req.params;
   res.send("test");
});

app.get('/users', async (req, res) => {
  const users = await prisma.User.findMany();
  console.log(users);
  res.send(`<div>${users.map((user) => {
    return `<name:$>email : ${user.email} / name:${user.name}</p><br>`
  }).join("")}</div>`);
});

app.get('/input', async (req, res) => {
  const { email, name } = req.query;
  const result = await prisma.User.create({data:{email : email, name: name}})
  console.log(email, name);
  res.send(`<h1>${email
  }</h1>
  <h2>${name}</h2>
  `);
})

app.listen(port, () => {
    console.log("listen http://localhost:3001")
});

프리즈마는 prisma.테이블명.명령어 형식으로 작동한다.

서버가 작동 중이니 이제 쿼리스트링으로 이메일, 이름을 입력해본다.

http://localhost:3001/input?email=testur@email.com&name=힘센캥거루

를 입력후 /users에서 확인을 해보면 데이터가 잘 출력되는 것을 볼 수 있다.

Nextjs에 PostgreSQL 백앤드 달기-4

마찬가지의 방법으로 수정, 삭제도 가능하다.

아래 코드를 추가해보자.

...
app.get("/delete", async (req, res) => {
  const { email } = req.query;
  const result = await prisma.User.delete({where : {email: email}});
  console.log(email);
  res.send(`<h1>${email} 삭제 성공</h1>`)
})
...

그리고 아래 주소처럼 요청하면 삭제가 된다.

http://localhost:3001/delete?email=testur@email.com

수정도 어렵지 않다.

where로 데이터를 넣고, data 필드에서 내용을 변경해주면 된다.

...
app.get("/edit", async (req, res) => {
  const { email, name } = req.query;
  const result = await prisma.User.update({where : {email: email}, 
    data : {name : name}
  });
  console.log(email, name);
  res.send(`<h1>${email} 이름 수정 성공</h1>`)
})
...

그리고 쿼리 스트링을 넣어준 뒤 확인해보면 아래와 같이 이름이 변경되어 있는 것을 확인할 수 있다.

Nextjs에 PostgreSQL 백앤드 달기-5

7. nextjs에서 사용하기

nextjs에서 prisma를 쉽게 사용하기 위해서는 사전 준비가 필요하다.

나는 src/lib 폴더 내부에 prisma.ts 파일을 만들어 주었다.

user에 대한 모든 입출력을 담당할 코드를 짜준다.

import { PrismaClient } from "@prisma/client";

const globalWithPrisma = global as typeof globalThis & {
  prisma: PrismaClient;
};

let prisma: PrismaClient;

// 개발자 모드가 아닐 때는 매번 새로운 연결 시도
if (process.env.NODE_ENV === "production") {
  prisma = new PrismaClient();
} else {
  if (!globalWithPrisma.prisma) {
    globalWithPrisma.prisma = new PrismaClient();
  }
    // 개발자 모드일 때는 메모리 누수 방지를 위해 기존 연결 사용.
  prisma = globalWithPrisma.prisma;
}

export default prisma;

이렇게 한 뒤, /src/db 내부에서는 user을 관리하기 위한 함수를 정의해 주었다.

import { dbUserObject } from "@/types/allTypes";
import prisma from "@/lib/prisma";

export async function createUser(data: dbUserObject) {
    try {
        const user = await prisma.user.create({
            data: {
                ...
                email : data.user.email as string,
                ...
            }
        });
    
        return user; // 생성된 사용자 반환
    } catch (error) {
        console.error('Error create user', error);
        throw error;
    }
}

export async function getAllUsers() {
    try {
      const users = await prisma.user.findMany();
      return users;
    } catch (error) {
      console.error('Error fetching users:', error);
      throw error;
    }
  }

  // Read - 특정 사용자 조회
export async function getUserByEmail(email: string) {
    try {
      const user = await prisma.user.findUnique({
        where: { email },
      });
      return user;
    } catch (error) {
      console.error('Error fetching user:', error);
      throw error;
    }
  }

  export async function updateUser(email: string, data: Partial<Omit<dbUserObject, 'email'>>) {
    try {
      const updatedUser = await prisma.user.update({
        where: { email },
        data: {
          nickName : data.user?.nickName,
          ...
        },
      });
      return updatedUser;
    } catch (error) {
      console.error('Error updating user:', error);
      throw error;
    }
  }

  export async function deleteUser(email: string) {
    try {
      const deletedUser = await prisma.user.delete({
        where: { email },
      });
      return deletedUser;
    } catch (error) {
      console.error('Error deleting user:', error);
      throw error;
    }
  }

8. 후기

백엔드 자체를 어렵게만 생각했는데, 도와주는 도구가 있으니 훨씬 쉬웠다.

다양한 라이브러리가 있지만 그 중에서도 prisma가 가장 직관적이고 좋은 듯 하다.

앞으로 이걸로 내 홈페이지, 그리고 프로젝트도 한번 진행해 보고 싶다.

관련 글

Next.js 풀스택 블로그 개발기
Next.js 풀스택 블로그 개발기
웹개발을 처음 접한지 1년정도 되었을 때, 나만의 블로그를 갖고싶다는 생각을 하게 되었다.그래서 6개월 정도 여기에만 매달려서 만들어보게 되었다.프론트 앤드에서의 기능은 아래 김도형님의 블로그를 참고하는 것으로 충분할 듯하다.나도 mdx를 이용해 블로그를 만드는데는 채...
Caddy를 이용한 Nextjs 무중단 배포(로컬서버)
Caddy를 이용한 Nextjs 무중단 배포(로컬서버)
홈페이지에 뭔가 자꾸 얹고 싶은 욕심이 들 때 마다 빌드를 했더니, 그 사이에 가끔 접속하는 사람이 종종 있긴 한것 같다.그러다 보니 서치콘솔에서 점수가 점점 하락하는 현상이 발생했다.이대로는 안될 것 같아 무중단 배포를 하는 방법을 생각해 보게 되었다.1. 대표적인 ...
구글 검색 색인 자동화 - Web Search Indexing API
구글 검색 색인 자동화 - Web Search Indexing API
지난번 IndexNow에 이어, 구글도 자동화를 해보기로 했다.찾아보니 구글은 API로 Web Search Indexing이라는 걸 지원하고 있었다.1. 허용범위공식적으로 해당 API가 지원하는 범위는 채용공고와 스트리밍 영상 서비스이다.실시간이 중요한 내용에 대해 색...
검색 색인 생성 자동화 - IndexNow
검색 색인 생성 자동화 - IndexNow
Bing에 검색등록을 하다가 알게 되었는데, Bing에서는 IndexNow라는 기능을 제공한다.핵심은 API 키를 이용해서 글을 쓰자마자 바로 색인 요청을 날릴 수 있다는 것.아래와 같은 요청을 fetch로 만들고, 글쓰기에 연동해 놓으면 글을 DB에 저장함과 동시에 ...
Nextjs, React 서버 해킹당한 경험 - React2Shell
Nextjs, React 서버 해킹당한 경험 - React2Shell
맨 처음 보안 이슈를 접했던건 12월 5일 새벽이었다.리액트에서 인증 없이 원격 코드 실행이 가능하다는 것.해당 뉴스를 접하고 다른 사람에게 알렸지만, 나는 괜찮으려니 싶어 아무 생각없이 넘겼다.1. 해킹 흔적 발견그런데 블로그 코드를 업데이트 하려고 접속했더니 터미널...
블로그에 다국어 기능 추가하기(NextJS, next-intl, Vercel AI SDK)
블로그에 다국어 기능 추가하기(NextJS, next-intl, Vercel AI SDK)
최근 블로그에 다국어 기능이 필요하다는 생각이 들었다.그래서 next-intl을 이용해 다국어 서비스를 구현해보기로 했다.1.i18n먼저 다국어 서비스를 할 때는 지켜야 할 원칙들이 있다.이걸 internationalization이라고 하는데, 무척 길기에 첫글자 i와...

댓글을 불러오는 중...