Conectando un backend PostgreSQL a Next.js

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

Implementé un backend simple para el registro de usuarios, pero curiosamente no pasé de ahí.

Probablemente el problema fue que, aunque había usado Prisma y PostgreSQL, lo hice de forma pasiva leyendo el artículo de otra persona, así que no lo aprendí bien.

Por eso decidí implementarlo yo mismo una vez.

1. Instalar PostgreSQL

Primero instalamos PostgreSQL con homebrew.

En el caso de Windows, se puede instalar choco y hacerlo fácilmente.

Y luego configuramos el inicio automático con services start.

# En caso de MacBook
brew install postgresql
brew services start postgresql

Si puedes conectarte correctamente tras introducir el siguiente comando, la instalación está terminada.

PostgreSQL tiene una estructura cliente-servidor, por lo que el servidor de PostgreSQL debe estar en ejecución para poder conectarse a la base de datos.

psql postgres
Conectando un backend PostgreSQL a Next.js-1

Ahora configuremos el usuario y la base de datos.

Yo configuré el nombre de usuario como testuser y la contraseña también como testuser.

CREATE USER testuser WITH PASSWORD 'testuser';
\du
Conectando un backend PostgreSQL a Next.js-2

El usuario no se creaba repetidamente, y al comprobarlo, vi que hay que añadir obligatoriamente el punto y coma al final para terminar el comando.

Luego, creemos también una base de datos.

CREATE DATABASE testdb;

Después, comprobamos las bases de datos con \l o \list.

Conectando un backend PostgreSQL a Next.js-3

Las 3 bases de datos de la parte superior son las que se crean por defecto.

Es mejor dejarlas tal cual, ya que podrían causar problemas si se borran.

2. Instalar Prisma

Ahora instalemos Prisma.

Yo creé una carpeta llamada prismaTest.

Se puede usar npm, pero yo simplemente inicialicé con yarn.

yarn

Y luego instalé Prisma.

Con el comando npx creamos la configuración inicial de Prisma.

Al ejecutar prisma init, se genera una carpeta con los archivos de configuración de Prisma.

Por cierto, npx es una herramienta de línea de comandos que permite ejecutar paquetes de npm sin instalarlos globalmente.

yarn add prisma
npx prisma init

3. Configurar la conexión a PostgreSQL

Ahora entra en prisma/schema.prisma.env y modifica la configuración del entorno.

Dentro del archivo, solo hay que cambiar la configuración como se muestra abajo.

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

4. Configurar schema.prisma

Ahora configuremos el esquema de la base de datos.

Por defecto, el esquema aparece como abajo.

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

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

Ahora puedes modificar esto libremente.

El problema es que hay que aprender un poco sobre cómo definir el esquema.

Por ejemplo, supongamos que tenemos el siguiente esquema.

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

➡️ model User { ... } es el nombre de la tabla de la base de datos.

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

  • Este campo es la clave primaria y los números se rellenan automáticamente como 1, 2, 3…

Elemento

Significado

id

Nombre del campo (columna)

Int

Tipo de dato = entero

@id

Este campo es la Primary Key

@default(autoincrement())

El valor por defecto es un número autoincremental

➡️ email String @unique

  • El valor de email debe ser único, no puede existir más de un usuario con el mismo email.

Elemento

Significado

email

Nombre del campo

String

Tipo cadena de texto

@unique

No admite duplicados (restricción Unique)

➡️ name String?

  • name puede existir o puede ser null (es decir, puede no existir).

    Elemento

    Significado

    name

    Nombre del campo

    String?

    Tipo cadena de texto, y el ? significa nullable (permite null)

Así que, resumiendo, los decoradores de Prisma son los siguientes.

Decorador

Significado

@id

Define la clave primaria

@default(...)

Define el valor por defecto

@unique

Restricción de valor único

@relation(...)

Define relaciones (clave foránea, tabla relacionada)

@map("db_column")

Define el nombre real de la columna en la BD

?

Ese campo es nullable (puede no tener valor)

[]

Arreglo (ej: String[] = arreglo de cadenas)

@필드명

Cuando el tipo del campo es datetime, al modificar la fecha se actualiza automáticamente con la fecha actual

5. Ejecutar la migración

Para reflejar el modelo en la BD, ejecutamos una migración.

El nombre al final se puede poner libremente.

npx prisma migrate dev --name testMyDB
## Escribe el nombre de la migración después de --name

6. Ejemplo de uso de Prisma Client

Ahora vamos a crear un servidor sencillo para probar el CRUD en el backend.

Crearemos el servidor con Express.

yarn add @prisma/client express

Primero instálalo con el comando anterior.

Crea un archivo index.js e introduce el siguiente código.

Y si ejecutas node index.js en la terminal, el servidor se iniciará.

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 funciona con la forma prisma.NombreDeTabla.comando.

Con el servidor en marcha, probemos a introducir el email y el nombre mediante query string.

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

Después de introducirlo y comprobar en /users, podrás ver que los datos se muestran correctamente.

Conectando un backend PostgreSQL a Next.js-4

De la misma forma, también se pueden hacer operaciones de actualización y borrado.

Añade el código siguiente.

...
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>`)
})
...

Y si haces una petición como la de abajo, se borrará.

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

La actualización tampoco es difícil.

Indicas los datos en where y luego modificas el contenido en el campo 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>`)
})
...

Luego, si añades el query string y lo compruebas, verás que el nombre se ha modificado como se muestra a continuación.

Conectando un backend PostgreSQL a Next.js-5

7. Uso en Next.js

Para usar Prisma fácilmente en Next.js, hace falta una preparación previa.

Yo creé un archivo prisma.ts dentro de la carpeta src/lib.

Escribí el código encargado de todas las operaciones de entrada y salida relacionadas con user.

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

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

let prisma: PrismaClient;

// Cuando no es modo desarrollo, se intenta una nueva conexión cada vez
if (process.env.NODE_ENV === "production") {
  prisma = new PrismaClient();
} else {
  if (!globalWithPrisma.prisma) {
    globalWithPrisma.prisma = new PrismaClient();
  }
    // En modo desarrollo, para evitar pérdidas de memoria se reutiliza la conexión existente.
  prisma = globalWithPrisma.prisma;
}

export default prisma;

Después de esto, dentro de /src/db definí funciones para gestionar 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; // Devuelve el usuario creado
    } 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 - Consultar un usuario específico
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. Conclusión

Siempre había pensado que el backend en sí era difícil, pero con herramientas que ayudan, resulta mucho más sencillo.

Hay muchas librerías distintas, pero entre ellas Prisma parece la más intuitiva y la mejor.

En el futuro quiero usar esto para mi sitio web y también para algún proyecto.

관련 글

공문서 완전 자동화 해보기 - ChatGPT, Claude, kordoc + python-hwpx
공문서 완전 자동화 해보기 - ChatGPT, Claude, kordoc + python-hwpx
대한민국 공공기관은 여전히 .hwp 확장자를 가진 파일을 많이 사용한다.이 파일은 한글과컴퓨터에서 만든 독자 규격 문서다.문제는 이 형식이 다른 프로그램과 완전히 호환되지 않는다는 데 있다.문서를 열어보는 것은 가능하다.하지만 그 내용을 구조적으로 읽고, 데이터처럼 활...
Relato del desarrollo de un blog full‑stack con Next.js
Relato del desarrollo de un blog full‑stack con Next.js
Alrededor de un año después de empezar con el desarrollo web, empecé a pensar que quería tener mi propio blog.Así que estuve dedicado a esto durante u...
Despliegue sin interrupciones de Nextjs (servidor local) usando Caddy
Despliegue sin interrupciones de Nextjs (servidor local) usando Caddy
Cada vez que me entraban ganas de seguir añadiendo cosas a la página web, hacía un build, y en ese intervalo parece que había gente que se conectaba d...
Automatización de la indexación de búsqueda de Google - Web Search Indexing API
Automatización de la indexación de búsqueda de Google - Web Search Indexing API
Después de IndexNow, decidí probar también la automatización con Google.Buscando un poco, vi que Google ofrecía algo llamado Web Search Indexing a tra...
Automatizar la creación de índices de búsqueda - IndexNow
Automatizar la creación de índices de búsqueda - IndexNow
Mientras estaba registrando el sitio en Bing, me enteré de que Bing ofrece una función llamada IndexNow.Lo esencial es que, usando una clave de API, p...
Experiencia de que hackearan mi servidor Nextjs y React
Experiencia de que hackearan mi servidor Nextjs y React
La primera vez que me encontré con este problema de seguridad fue la madrugada del 5 de diciembre.Que en React era posible ejecutar código de forma re...

댓글을 불러오는 중...