Back to all posts

NestJS Docker Compose PostgreSQL TypeORM 연결

NestJS Docker Compose PostgreSQL TypeORM 연결을 공부하며 이해한 흐름을 정리한 글입니다.

2026년 05월 28일4

언제 쓰는가

NestJS 프로젝트에서 Docker Compose로 PostgreSQL 컨테이너를 띄우고, @nestjs/typeorm, typeorm, pg를 사용해서 NestJS 애플리케이션과 DB를 연결할 때 본다.

현재 예시 프로젝트:

/Users/littleduck/Documents/GitHub/coding_study/Frameworks/nestjs_server

전체 흐름

  1. NestJS 프로젝트에 TypeORM 관련 패키지를 설치한다.
  2. docker-compose.yaml에 PostgreSQL 서비스를 만든다.
  3. Docker Compose로 PostgreSQL 컨테이너를 실행한다.
  4. AppModule에서 TypeOrmModule.forRoot()로 PostgreSQL 접속 정보를 등록한다.
  5. NestJS 서버를 실행해서 DB 연결 에러가 없는지 확인한다.

1. 패키지 설치

NestJS에서 TypeORM과 PostgreSQL을 쓰려면 아래 패키지가 필요하다.

npm install @nestjs/typeorm typeorm pg

현재 프로젝트의 package.json에는 아래 의존성이 들어가 있다.

{
  "@nestjs/typeorm": "^11.0.1",
  "pg": "^8.21.0",
  "typeorm": "^1.0.0"
}

역할:

  • @nestjs/typeorm: NestJS에서 TypeORM을 모듈로 연결하게 해준다.
  • typeorm: ORM 본체다.
  • pg: Node.js에서 PostgreSQL에 접속하기 위한 드라이버다.

2. Docker Compose 작성

프로젝트 루트에 docker-compose.yaml을 만든다.

services:
  postgres:
    image: postgres:15
    restart: always
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
    ports:
      - '5432:5432'
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: postgres

각 항목 의미:

  • image: postgres:15: PostgreSQL 15 버전 이미지를 사용한다.
  • restart: always: 컨테이너가 꺼지면 자동으로 다시 실행한다.
  • volumes: DB 데이터를 프로젝트의 postgres-data 폴더에 저장한다.
  • ports: 로컬 Mac의 5432 포트를 컨테이너의 5432 포트에 연결한다.
  • POSTGRES_USER: DB 사용자 이름이다.
  • POSTGRES_PASSWORD: DB 비밀번호다.
  • POSTGRES_DB: 처음 생성할 DB 이름이다.

이 설정에서는 사용자, 비밀번호, DB 이름이 모두 postgres다.

3. PostgreSQL 컨테이너 실행

프로젝트 루트에서 실행한다.

docker compose up -d

실행 상태 확인:

docker compose ps

로그 확인:

docker compose logs postgres

컨테이너 중지:

docker compose down

DB 데이터까지 완전히 지우고 새로 시작하고 싶으면 postgres-data 폴더를 삭제한 뒤 다시 실행한다.

docker compose down
rm -rf postgres-data
docker compose up -d

주의: postgres-data를 삭제하면 로컬 DB 데이터가 전부 사라진다.

4. NestJS에서 TypeORM 연결

src/app.module.ts에서 TypeOrmModule을 import한다.

import { TypeOrmModule } from '@nestjs/typeorm';

그리고 imports 배열에 TypeOrmModule.forRoot()를 추가한다.

@Module({
  imports: [
    PostsModule,
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: '127.0.0.1',
      port: 5432,
      username: 'postgres',
      password: 'postgres',
      database: 'postgres',
      entities: [],
      synchronize: true,
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

설정값은 docker-compose.yaml과 맞아야 한다.

TypeORM 설정 Docker Compose 설정 현재 값
host 로컬에서 접속하므로 127.0.0.1 127.0.0.1
port ports의 왼쪽 값 5432
username POSTGRES_USER postgres
password POSTGRES_PASSWORD postgres
database POSTGRES_DB postgres

synchronize: true는 엔티티 기준으로 DB 테이블을 자동 동기화한다.

개발 중에는 편하지만 운영 환경에서는 보통 false로 둔다.

synchronize: false

5. NestJS 서버 실행

PostgreSQL 컨테이너가 떠 있는 상태에서 NestJS 서버를 실행한다.

npm run start:dev

서버가 정상 실행되고 TypeORM 관련 접속 에러가 없으면 연결 성공이다.

빠른 재실행 순서

이미 설정이 끝난 프로젝트라면 보통 아래 순서만 기억하면 된다.

docker compose up -d
npm run start:dev

상태 확인:

docker compose ps
docker compose logs postgres

자주 나는 문제

1. 포트 5432가 이미 사용 중

증상:

Bind for 0.0.0.0:5432 failed: port is already allocated

원인:

로컬 PostgreSQL이나 다른 Docker 컨테이너가 이미 5432 포트를 쓰고 있다.

해결 방법:

docker-compose.yaml에서 왼쪽 포트를 바꾼다.

ports:
  - '5433:5432'

그리고 TypeORM 설정의 port도 같이 바꾼다.

port: 5433,

2. password authentication failed

증상:

password authentication failed for user "postgres"

원인:

TypeORM의 username, password, database 값이 Docker Compose의 환경 변수와 다르거나, 기존 postgres-data에 예전 비밀번호로 초기화된 DB가 남아 있다.

확인할 값:

POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
username: 'postgres',
password: 'postgres',
database: 'postgres',

기존 데이터를 지우고 다시 만들려면:

docker compose down
rm -rf postgres-data
docker compose up -d

주의: 로컬 DB 데이터가 삭제된다.

3. connect ECONNREFUSED 127.0.0.1:5432

증상:

connect ECONNREFUSED 127.0.0.1:5432

원인:

PostgreSQL 컨테이너가 실행 중이 아니거나 포트가 다르다.

확인:

docker compose ps
docker compose logs postgres

해결:

docker compose up -d

4. Entity를 만들었는데 테이블이 안 생김

현재 설정은 아래처럼 비어 있다.

entities: [],

엔티티 클래스를 만들었다면 entities에 추가하거나 자동 로딩을 켠다.

예시:

TypeOrmModule.forRoot({
  type: 'postgres',
  host: '127.0.0.1',
  port: 5432,
  username: 'postgres',
  password: 'postgres',
  database: 'postgres',
  autoLoadEntities: true,
  synchronize: true,
});

그리고 각 기능 모듈에서 엔티티를 등록한다.

TypeOrmModule.forFeature([PostEntity])

체크리스트

  • docker-compose.yaml이 프로젝트 루트에 있는가?
  • docker compose up -ddocker compose ps에서 postgres가 실행 중인가?
  • 로컬 접속 포트와 TypeORM의 port가 같은가?
  • POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB와 TypeORM 설정이 같은가?
  • NestJS 서버 실행 시 TypeORM 접속 에러가 없는가?
  • 엔티티를 만들었다면 entities 또는 autoLoadEntities 설정을 했는가?

관련 파일

  • /Users/littleduck/Documents/GitHub/coding_study/Frameworks/nestjs_server/docker-compose.yaml
  • /Users/littleduck/Documents/GitHub/coding_study/Frameworks/nestjs_server/src/app.module.ts
  • /Users/littleduck/Documents/GitHub/coding_study/Frameworks/nestjs_server/package.json