NestJS 개발 환경 구축: Docker와 TypeORM으로 MySQL 연결하기 + SQL 스크립트 실행

세하·2025년 10월 16일

NestJS

목록 보기
2/8
post-thumbnail

NestJS 프로젝트의 개발 환경을 구축해보자
Docker를 사용하여 데이터베이스를 독립적으로 관리하고, TypeORM을 통해 애플리케이션과 데이터베이스를 안전하게 연결하자

1. Docker 설치 및 실행

개발 환경을 담을 그릇인 Docker를 설치
https://www.docker.com/products/docker-desktop/

위의 사이트에서 도커를 설치해주고
Docker Desktop을 실행한다

Finish 버튼 누르고 회원가입하면 우선 기본 설치는 완료이다

터미널에서

docker -v

아래 명령어를 실행하여 버전이 잘 출력되는지 확인

2. Docker Compose로 DB 환경 설계

docker-compose를 사용하여 우리 프로젝트만을 위한 독립된 데이터베이스 환경을 설계하자

docker-compose.yml 작성

프로젝트 최상위 폴더에 docker-compose.yml 작성
Docker에게 이런 사양의 MySQL 데이터베이스를 만들어줘 라고 지시하는 설계도 기능이다.

비밀번호는 .env 파일로 관리하자. docker-compose.yml에 비밀번호를 직접 적는 대신, .env 파일을 이용해 민감한 정보를 안전하게 관리합시다... 최상위 폴더에 .env 파일을 만들고, 이 파일은 반드시 .gitignore에 추가해서 Git 저장소에 올라가지 않도록 하자

DB_ROOT_PASSWORD=your_root_password
DB_USER=your_db_user
DB_PASSWORD=your_db_password

루트 계정 비밀번호와 사용할 계정과 그 계정의 비밀번호를 정해서 설정해준다

# docker-compose.yml

version: '3.8'
services:
  # 이 서비스의 별명입니다 (예: mysql_db)
  mysql_db:
    # Docker Hub에 있는 공식 mysql 8.0 버전을 사용
    image: mysql:8.0
    # 컨테이너가 예기치 않게 종료되면 항상 다시 시작
    restart: always
    # .env 파일의 변수를 사용하여 환경 변수 설정
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: 'mydatabase'      # NestJS 프로젝트에서 사용할 DB 이름
      MYSQL_USER: ${DB_USER}            # NestJS 프로젝트에서 사용할 계정 이름
      MYSQL_PASSWORD: ${DB_PASSWORD}    # 해당 계정의 비밀번호
    # 포트 설정
    # 내 컴퓨터의 3306 포트와 컨테이너의 3306 포트를 연결
    ports:
      - '3306:3306'
    # 데이터베이스 데이터를 저장할 공간 설정
    # 컨테이너를 삭제해도 데이터는 보존됩니다
    # 내 컴퓨터의 ./db_data 폴더와 MySQL 컨테이너 내부의 /var/lib/mysql 폴더를 실시간으로 동기화해라
    volumes:
      - ./db_data:/var/lib/mysql

volumes: - ./db_data:/var/lib/mysql 설정 이유

  • 데이터 영속성 (Persistence) docker-compose down으로 컨테이너를 삭제했다가 나중에 다시 docker-compose up으로 실행해도, db_data 폴더에 데이터가 그대로 남아있기 때문에 기존에 작업했던 내용이 모두 복구된다.
  • 데이터 직접 확인 및 백업 컨테이너 내부에 들어가지 않고도 내 컴퓨터에서 실제 데이터 파일들을 직접 확인할 수 있다. 데이터베이스 전체를 백업하고 싶을 때 이 db_data 폴더를 복사하는 것만으로도 간단하게 처리할 수 있음.
  • .gitignore에 추가하여 Git 저장소에 올라가지 않도록 관리

docker compose up으로 컨테이너 실행

docker-compose.yml 파일이 있는 그 폴더에서 터미널을 열고 아래 명령어를 실행하면, Docker는 이 설계도를 읽어 이미지를 자동으로 다운로드하고 컨테이너를 생성하여 실행한다.

docker compose up -d

혹은

docker compose up -d mysql_db

새로운 프로젝트마다 별도의 docker-compose.yml을 만들고, 그 프로젝트만을 위한 완전히 독립된 새 컨테이너를 생성하는 것임!
Docker 컨테이너는 완벽하게 격리된 독립적인 환경.
만약 여러 프로젝트를 동시에 실행하려면, 포트가 겹치지 않도록 docker-compose.yml에서 포트 번호를 각각 다르게 설정해야 한다. (예: ports: - '3307:3306')

  • 프로젝트 독립성: A 프로젝트의 DB를 망가뜨려도 B 프로젝트에는 아무런 영향이 없다.
  • 버전 충돌 방지: A 프로젝트는 MySQL 8.0, B 프로젝트는 PostgreSQL 14를 쓰는 등, 프로젝트마다 다른 DB나 다른 버전을 충돌 없이 사용할 수 있다.
  • 쉬운 협업: 새로운 팀원은 프로젝트를 내려받고 docker-compose up 명령어 하나만 실행하면 복잡한 DB 설치 과정 없이 즉시 개발을 시작할 수 있다.

3. TypeORM으로 NestJS와 데이터베이스 연결하기

이제 NestJS 애플리케이션이 Docker로 실행된 데이터베이스와 통신할 수 있도록 TypeORM을 설정하자

TypeORM이란?

TypeORM은 ORM(Object-Relational Mapper)으로, TypeScript의 객체(Object) 와 MySQL 같은 관계형 데이터베이스의 테이블(Relation) 을 연결해주는 번역가 역할을 한다. TypeORM을 사용하면 복잡한 SQL 쿼리를 직접 작성하지 않고, 익숙한 TypeScript 코드로 데이터베이스를 안전하고 쉽게 다룰 수 있다.

필요한 패키지 설치

NestJS 프로젝트 폴더로 이동하여 TypeORM 관련 패키지들을 설치하자

npm install @nestjs/typeorm typeorm mysql2

NestJS용 .env 파일 설정

보안을 위해 NestJS 애플리케이션의 DB 연결 정보 또한 .env 파일을 통해 관리하자.
NestJS 프로젝트 폴더 내에 .env 파일을 생성하고 아래 내용을 작성.
docker-compose.yml에서 사용했던 정보와 동일하게 변수를 작성.

NestJS 프로젝트 폴더의 .gitignore에도 .env를 꼭 추가하자!

DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=<docker-compose.yml와 맞춰주기>
DB_PASSWORD=<docker-compose.yml와 맞춰주기>
DB_DATABASE=<docker-compose.yml와 맞춰주기>

ConfigModule과 TypeOrmModule 설정

@nestjs/config 공식 패키지를 사용하여 .env 파일의 값을 읽어오고, 이 값을 TypeOrmModule에 전달하여 데이터베이스 연결을 설정하자

npm install @nestjs/config
// app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
// ConfigModule과 ConfigService를 import
import { ConfigModule, ConfigService } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    // ConfigModule을 가장 먼저 임포트
    ConfigModule.forRoot({
      isGlobal: true, // 다른 모듈에서도 ConfigService를 사용할 수 있게 설정
    }),
    
    // TypeOrmModule을 비동기 방식(forRootAsync)으로 설정
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      // // useFactory에서 동적으로 설정을 생성
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        // configService.get('변수명')으로 .env 파일의 값을 가져옴
        host: configService.get('DB_HOST'),
        port: parseInt(configService.get('DB_PORT', '3306')),
        username: configService.get('DB_USERNAME'),
        password: configService.get('DB_PASSWORD'),
        database: configService.get('DB_DATABASE'),
        
        // 추후 엔티티(테이블) 클래스들을 여기에 등록
        entities: [],
        
        // synchronize: true는 개발 환경에서만 사용!
        // 코드를 기반으로 DB 스키마를 자동으로 동기화해준다
        // 프로덕션 환경에서는 데이터 손실 위험이 있어 false로 두고 마이그레이션을 사용해야 한다.
        synchronize: true,
      }),
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

모든 설정이 끝났다!
이 구조를 통해 안전하고 확장 가능하며, 협업하기 좋은 NestJS 개발 환경을 구축했다.

참고

4. Workbrench로 Docker에 띄워진 MySQL 연결하기

MySQLWorkbrench에서 Docker에 띄워진 MySQL을 연결해 본자
우선 Workbrench에서 MySQL Connections 옆의 플러스 버튼을 눌러 새로운 연결을 시도한다.

  • Connection Name : 연결의 이름. 본인이 식별할 수 있도록 자유롭게 작성한다
    -Hostname : 로컬 Ip 주소를 입력한다.
  • Port : 3306 포트(위에서 본인이 작성한 호스트 포트 번호)로 접속하면 컨테이너의 3306(MySQL)과 연결된다.
  • Username : 연결하는 MySQL에서 접속할 계정의 username을 적어준다. (위에서 생성한 계정)
  • Password : Store in Keychain... : 계정의 비밀번호를 입력한다.

Test Connection 버튼을 눌렀을때 아래처럼 Seuccessfully made~ 라고 나오면 잘 접속된 것이다!

그럼 이제 OK 버튼 눌러서 연결을 생성하면 이렇게 새로운 연결이 Workbench에 생성된다.

해당 연결에 들어가면 연결에 사용된 MySQL의 계정 권한에 따라 DB를 조회, 수정을 할 수 있다. 나는 아직 아무 테이블도 만들지 않아서 비어있음.

5. sql script 생성 및 실행

MySQL Workbench 에서 ERD 작성하고
Forward engineering을 통해 데이터베이스 생성 쿼리문을 생성하고
실행하여 테이블을 넣어보자

ERD 작성

File > New Model 클릭 후 Add Diagram 선택.


아래의 mydb가 사용할 스키마(데이터베이스) 이름인데, 더블클릭하여 변경할 수도 있다.

1:N 관계를 표현하는 선을 그을 때 먼저 클릭하는 테이블이 N이 되고, 나중에 누르는 테이블이 1이 된다.

sql 스크립트 생성

다 그렸으면 File > Export > Forward Engineer 을 클릭하여 sql 스크립트를 생성하자

Output SQL Script File을 통해 sql문을 저장할 위치를 선택할 수 있음.
SQL Options는 처음 두 개만 선택해주었다. 각자 읽고 필요한 부분 선택하면 될듯
Continue 클릭

테이블 추출할거고
Continue 클릭

그럼 이렇게 sql script가 생성된다~
Finish 누르면 아까 지정한 위치에 스크립트가 저장됨

실제 데이터베이스에 적용

데이터베이스 이름을 아까 모델 생성하는 단계에서 바꾸지 않았다면(mydb) docker-compose.yml에서 설정한 이름과 일치시켜주자

MySQL Workbench가 생성한 스크립트는 기본적으로 mydb라는 스키마(데이터베이스)를 사용하도록 되어 있다. NestJS 프로젝트와 Docker 설정은 다른 데이터베이스를 사용하도록 되어 있다면 이 둘을 맞춰줘야함

간단하게 스크립트 열어서 Cmd + F 로 찾아서 replace All 해주면 된다ㅎ
그럼 이제 진짜 스크립트를 실행해보자

방법1. MySQL Workbench 사용하기

Docker 데이터베이스에 연결

  • MySQL Workbench를 열고 새 연결(Connection)을 만든다
  • Hostname: 127.0.0.1 또는 localhost
  • Port: 3306 (위에서 설정한 대로)
  • Username: root (테이블을 생성하는 등의 초기 설정 작업은 모든 권한을 가진 root 계정으로 하는 것이 편리하다)
  • root 계정의 비밀번호를 입력하고 연결

데이터베이스나 테이블을 생성하는 초기 설정(DDL) 은 모든 권한을 가진 root 계정으로 하는 것이 일반적이다. 따로 생성한 계정은 NestJS 애플리케이션이 데이터를 읽고 쓰는(DML) 용도로 사용하는 것이 좋다.

스크립트 파일 실행

  • File > Open SQL Script... 를 선택하여 방금 수정한 SQL 파일을 연다
  • 열린 스크립트 창에서 번개 모양 아이콘(⚡️)을 클릭하여 스크립트 전체를 실행

결과 확인

  • root 말고 본인이 만든 계정으로 연결된 스키마를 열자
  • 왼쪽의 SCHEMAS 패널에서 새로고침 버튼을 누르면 방금 만든 테이블들이 보일 것!

방법 2: 터미널(CLI) 사용하기

SQL 파일 저장

  • 수정한 SQL 스크립트를 프로젝트 최상위 폴더에 init.sql 같은 이름으로 저장한다

터미널에서 명령어 실행

  • docker-compose.yml 파일이 있는 위치에서 아래 명령어를 실행한다.
  • 이 명령어는 init.sql 파일의 내용을 Docker 컨테이너 안의 mysql 클라이언트로 직접 전달하여 실행시킨다.
cat ./init.sql | docker exec -i <컨테이너_이름> mysql -u root -p<root_비밀번호> <데이터베이스 이름>
  • <컨테이너_이름>: docker ps 명령어로 확인하거나, docker-compose.yml의 서비스 이름(이 포스터에서는 mysql_db)을 기반으로 찾을 수 있다.
  • -p<root_비밀번호>: -p와 비밀번호 사이에 공백이 없어야 함.
  • <데이터베이스 이름>: NestJS 프로젝트에서 사용할 DB 이름으로 정한 것

지금처럼 SQL 스크립트로 테이블을 직접 만들었다면, TypeORM의 synchronize: true 옵션은 개발 중 엔티티가 변경될 때 스키마를 자동으로 맞춰주는 보조적인 역할로 계속 유용하게 사용할 수 있다.

0개의 댓글