개발 환경용 시작 시 데이터베이스를 스키마와 데이터로 사전 시딩(Pre-seeding)하기
개발 환경용 시작 시 데이터베이스를 스키마와 데이터로 사전 시딩(Pre-seeding)하기
로컬 개발 중 데이터베이스를 스키마와 데이터로 사전 시딩하는 방법을 배워볼게요.
출처: 문서
본문
로컬 개발 중 데이터베이스를 필수 데이터와 스키마로 사전 시딩하는 것은 개발·테스트 워크플로를 향상시키는 일반적인 관행이에요. 실제 시나리오를 시뮬레이션함으로써 이 관행은 프론트엔드 문제를 조기에 잡아내고, 데이터베이스 관리자(DBA)와 소프트웨어 엔지니어 사이의 정렬을 보장하며, 더 원활한 협업을 촉진해요. 사전 시딩은 자신 있는 배포, 환경 전체의 일관성, 조기 문제 탐지 같은 이점을 제공해 전반적인 개발 과정을 개선해요.
이 가이드에서 배울 내용:
- Docker로 Postgres 컨테이너 실행하기
- SQL 스크립트로 Postgres 사전 시딩하기
- SQL 파일을 Docker 이미지로 복사해 Postgres 사전 시딩하기
- JavaScript 코드로 Postgres 사전 시딩하기
Docker로 Postgres 사용하기
Postgres 의 공식 Docker 이미지 는 개발 머신에서 Postgres 데이터베이스를 실행하는 편리한 방법을 제공해요. Postgres Docker 이미지는 PostgreSQL 데이터베이스 시스템을 캡슐화한 사전 구성된 환경이에요. Docker 컨테이너에서 실행할 준비가 된 자족형(自足的) 단위예요. 이 이미지를 사용하면 수동 구성 없이 Postgres 인스턴스를 빠르고 쉽게 설정할 수 있어요.
사전 요구사항
이 how-to 가이드를 따라 하려면 다음 전제조건이 필요해요:
- Docker Desktop
Postgres 실행
다음 단계로 Postgres의 빠른 데모를 실행해주세요:
터미널을 열고 다음 명령으로 Postgres 컨테이너를 시작해주세요. 이 예제는 Postgres 컨테이너를 시작하고, 포트 5432 를 호스트에 노출해 네이티브로 실행되는 어플리케이션이 mysecretpassword 라는 비밀번호로 연결할 수 있게 해요.
$ docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword postgres
Docker Dashboard에서 컨테이너를 선택하고 로그를 확인해 Postgres가 실행 중인지 검증해주세요.
PostgreSQL Database directory appears to contain a database; Skipping initialization
2024-09-08 09:09:47.136 UTC [1] LOG: starting PostgreSQL 16.4 (Debian 16.4-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
2024-09-08 09:09:47.137 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2024-09-08 09:09:47.137 UTC [1] LOG: listening on IPv6 address "::", port 5432
2024-09-08 09:09:47.139 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2024-09-08 09:09:47.142 UTC [29] LOG: database system was shut down at 2024-09-08 09:07:09 UTC
2024-09-08 09:09:47.148 UTC [1] LOG: database system is ready to accept connections
로컬 시스템에서 Postgres에 연결해주세요. psql 은 Postgres 데이터베이스에 연결해 SQL 명령 실행을 시작할 수 있게 해주는 PostgreSQL 대화형 셸이에요. 로컬 시스템에 psql 유틸리티가 이미 설치되어 있다고 가정하고 Postgres 데이터베이스에 연결할 차례예요. 로컬 터미널에서 다음 명령을 실행해주세요:
$ docker exec -it postgres psql -h localhost -U postgres
이제 psql 프롬프트 안에서 필요한 SQL 쿼리나 명령을 실행할 수 있어요.
Postgres 대화형 셸에서 나가려면 \q 또는 \quit 를 사용하세요.
SQL 스크립트로 Postgres 데이터베이스 사전 시딩하기
이제 Postgres에 익숙해졌으니 샘플 데이터로 사전 시딩하는 방법을 볼 차례예요. 이 데모에서는 먼저 SQL 명령을 담는 스크립트를 만들 거예요. 스크립트는 데이터베이스와 테이블 구조를 정의하고 샘플 데이터를 삽입해요. 그런 다음 데이터베이스에 연결해 데이터를 검증해요.
실행 중인 기존 Postgres 데이터베이스 인스턴스가 있다고 가정하고 다음 단계로 데이터베이스를 시딩해주세요.
seed.sql 이라는 빈 파일을 만들고 다음 내용을 추가해주세요:
CREATE DATABASE sampledb;
\c sampledb
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100) UNIQUE
);
INSERT INTO users (name, email)
VALUES ('Alpha', '[email protected]'),
('Beta', '[email protected]'),
('Gamma', '[email protected]');
SQL 스크립트는 sampledb 라는 새 데이터베이스를 만들고 연결한 다음 users 테이블을 만들어요. 테이블에는 자동 증가하는 기본 키인 id , 최대 50자의 name 필드, 최대 100자의 고유 email 필드가 포함돼요.
테이블을 만든 후 INSERT 명령은 users 테이블에 각각의 이름과 이메일이 있는 사용자 세 명을 삽입해요. 이 설정은 고유한 이메일 주소로 사용자 정보를 저장하는 기본 데이터베이스 구조를 형성해요.
데이터베이스를 시딩해주세요. 이제 seed.sql 의 내용을 < 연산자를 사용해 데이터베이스에 직접 넣을 차례예요. 이 명령은 sampledb 라는 Postgres 데이터베이스에 대해 seed.sql 이라는 SQL 스크립트를 실행하는 데 사용돼요.
$ cat seed.sql | docker exec -i postgres psql -h localhost -U postgres -f-
쿼리가 실행되면 다음 결과가 보일 거예요:
CREATE DATABASE
You are now connected to database "sampledb" as user "postgres".
CREATE TABLE
INSERT 0 3
sampledb 데이터베이스에 users 라는 테이블이 채워졌는지 확인하려면 다음 psql 명령을 실행해주세요.
$ docker exec -it postgres psql -h localhost -U postgres sampledb
이제 psql 셸에서 \l 을 실행해 Postgres 서버의 모든 데이터베이스를 나열할 수 있어요.
sampledb=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
-----------+---------+----------+------------+------------+------------+-----------------+---------------------
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc |
sampledb | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc |
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres +
| | | | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres +
| | | | | | | postgres=CTc/postgres
(4 rows)
users 테이블의 모든 데이터를 가져오려면 다음 쿼리를 입력해주세요:
sampledb=# SELECT * FROM users;
id | name | email
----+-------+------------------
1 | Alpha | [email protected]
2 | Beta | [email protected]
3 | Gamma | [email protected]
(3 rows)
Postgres 대화형 셸에서 나가려면 \q 또는 \quit 를 사용하세요.
SQL 스크립트를 바인드 마운트해 데이터베이스 사전 시딩하기
Docker에서 마운팅이란 호스트 시스템의 파일이나 디렉터리를 컨테이너 안에서 접근 가능하게 만드는 것을 의미해요. 이렇게 하면 호스트와 컨테이너 사이에 데이터나 구성 파일을 공유해 더 큰 유연성과 영속성을 가능하게 해요.
Postgres를 시작하고 SQL 스크립트로 데이터베이스를 사전 시딩하는 방법을 배웠으니, 이제 SQL 파일을 Postgres 컨테이너의 초기화 디렉터리( /docker-entrypoint-initdb.d )에 직접 마운트하는 방법을 배울 차례예요. /docker-entrypoint-initdb.d 는 PostgreSQL Docker 컨테이너의 특수 디렉터리로, 컨테이너가 처음 시작될 때 데이터베이스를 초기화하는 데 사용돼요.
아래 단계를 따르기 전에 포트 충돌을 방지하기 위해 실행 중인 Postgres 컨테이너(볼륨 포함)를 중지했는지 확인해주세요:
$ docker container stop postgres
seed.sql 을 다음 내용으로 수정해주세요:
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100) UNIQUE
);
INSERT INTO users (name, email)
VALUES ('Alpha', '[email protected]'),
('Beta', '[email protected]'),
('Gamma', '[email protected]')
ON CONFLICT (email) DO NOTHING;
Dockerfile 이라는 텍스트 파일을 만들고 다음 내용을 복사해주세요.
# syntax=docker/dockerfile:1
FROM postgres:18
COPY seed.sql /docker-entrypoint-initdb.d/
이 Dockerfile은 seed.sql 스크립트를 PostgreSQL 컨테이너의 초기화 디렉터리로 직접 복사해요.
Docker Compose를 사용하세요. Docker Compose를 사용하면 시딩된 데이터베이스로 PostgreSQL 컨테이너를 관리·배포하는 것이 훨씬 쉬워져요. 이 compose.yml 파일은 최신 Postgres 이미지를 사용하는 db 라는 Postgres 서비스를 정의하며, sampledb 라는 이름의 데이터베이스와 postgres 사용자, mysecretpassword 비밀번호를 설정해요.
services:
db:
build:
context: .
dockerfile: Dockerfile
container_name: my_postgres_db
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_DB: sampledb
ports:
- "5432:5432"
volumes:
- data_sql:/var/lib/postgresql # Persistent data storage
volumes:
data_sql:
호스트의 포트 5432 를 컨테이너의 5432 에 매핑해 컨테이너 밖에서 Postgres 데이터베이스에 접근할 수 있게 해요. 또한 data_sql 을 정의해 데이터베이스 데이터를 영속화하고, 컨테이너가 중지될 때 데이터가 손실되지 않게 보장해요.
호스트로의 포트 매핑은 비컨테이너화 프로그램에서 데이터베이스에 연결하려는 경우에만 필요하다는 점에 유의하세요. DB에 연결하는 서비스를 컨테이너화했다면 커스텀 브리지 네트워크를 통해 데이터베이스에 연결해야 해요.
Compose 서비스를 띄우세요. seed.sql 파일을 Dockerfile 과 같은 디렉터리에 두었다고 가정하고 다음 명령을 실행해주세요:
$ docker compose up -d --build
이제 users 테이블이 데이터로 채워졌는지 확인할 차례예요.
$ docker exec -it my_postgres_db psql -h localhost -U postgres sampledb
sampledb=# SELECT * FROM users;
id | name | email
----+-------+------------------
1 | Alpha | [email protected]
2 | Beta | [email protected]
3 | Gamma | [email protected]
(3 rows)
sampledb=#
JavaScript 코드로 데이터베이스 사전 시딩하기
SQL 스크립트, 볼륨 마운트 등 다양한 방법으로 데이터베이스를 시딩하는 방법을 배웠으니, 이제 JavaScript 코드로 이를 달성해볼 차례예요.
다음 내용으로 .env 파일을 만들어주세요:
POSTGRES_USER=postgres
POSTGRES_DB_HOST=localhost
POSTGRES_DB=sampledb
POSTGRES_PASSWORD=mysecretpassword
POSTGRES_PORT=5432
다음 내용으로 seed.js 라는 새 JavaScript 파일을 만들어주세요:
다음 JavaScript 코드는 .env 파일에서 환경 변수를 로드하는 데 사용되는 dotenv 패키지를 임포트해요. .config() 메서드는 .env 파일을 읽고 환경 변수를 process.env 객체의 속성으로 설정해요. 이렇게 하면 데이터베이스 자격 증명 같은 민감한 정보를 코드 밖에 안전하게 저장할 수 있어요.
그런 다음 효율적인 데이터베이스 상호작용을 위한 연결 풀을 제공하는 pg 라이브러리에서 새 Pool 인스턴스를 만들어요. seedData 함수는 데이터베이스 시딩 작업을 수행하도록 정의돼요. 시딩 과정을 시작하기 위해 스크립트 끝에서 호출돼요. 오류 처리를 위해 try...catch...finally 블록이 사용돼요.
require('dotenv').config(); // Load environment variables from .env file
const { Pool } = require('pg');
// Create a new pool using environment variables
const pool = new Pool({
user: process.env.POSTGRES_USER,
host: process.env.POSTGRES_DB_HOST,
database: process.env.POSTGRES_DB,
port: process.env.POSTGRES_PORT,
password: process.env.POSTGRES_PASSWORD,
});
const seedData = async () => {
try {
// Drop the table if it already exists (optional)
await pool.query(`DROP TABLE IF EXISTS todos;`);
// Create the table with the correct structure
await pool.query(`
CREATE TABLE todos (
id SERIAL PRIMARY KEY,
task VARCHAR(255) NOT NULL,
completed BOOLEAN DEFAULT false
);
`);
// Insert seed data
await pool.query(`
INSERT INTO todos (task, completed) VALUES
('Watch netflix', false),
('Finish podcast', false),
('Pick up kid', false);
`);
console.log('Database seeded successfully!');
} catch (err) {
console.error('Error seeding the database', err);
} finally {
pool.end();
}
};
// Call the seedData function to run the script
seedData();
시딩 과정을 시작해주세요.
$ node seed.js
다음 명령이 보여야 해요:
Database seeded successfully!
데이터베이스가 올바르게 시딩됐는지 확인해주세요:
$ docker exec -it postgres psql -h localhost -U postgres sampledb
sampledb=# SELECT * FROM todos;
id | task | completed
----+---------------+----------
1 | Watch netflix | f
2 | Finish podcast| f
3 | Pick up kid | f
(3 rows)
요약
시작 시 스키마와 데이터로 데이터베이스를 사전 시딩하는 것은 일관되고 현실적인 테스트 환경을 만드는 데 필수적이며, 개발 초기에 문제를 식별하고 프론트엔드·백엔드 작업을 정렬하는 데 도움이 돼요. 이 가이드는 SQL 스크립트, Docker 통합, JavaScript 코드를 포함한 다양한 방법으로 사전 시딩을 달성하는 지식과 실용적 단계를 제공했어요.
더 알아보기 (Learn more)
- PostgreSQL 가이드
- Docker Compose
- Postgres 공식 이미지