본문 바로가기
BackEnd/Project

[PT Manager] Ch03. Docker MySQL 설치 및 테이블 생성

by 개발 Blog 2024. 8. 27.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

이번 장에서는 Docker를 이용해 MySQL을 설치하고, 데이터베이스와 테이블을 생성하는 과정을 다룬다. Docker는 컨테이너화된 환경을 제공하기 때문에 개발 환경을 손쉽게 관리할 수 있다. docker-compose.yml 파일을 이용해 MySQL 컨테이너를 설정하고, 이를 통해 데이터베이스를 구성할 것이다.

 

1. MySQL 설정 파일 (my.cnf)

먼저, MySQL의 기본 설정을 위해 my.cnf 파일을 작성한다. 이 파일은 MySQL의 클라이언트와 서버 설정을 정의한다.

[client]
default-character-set = utf8mb4

[mysqld]
authentication-policy = mysql_native_password
  • 위 설정에서는 클라이언트가 기본적으로 utf8mb4 캐릭터 셋을 사용하도록 하고, 서버 측에서 인증 방식을 mysql_native_password로 설정한다.
  • 이 설정을 통해 데이터의 호환성과 안정성을 높일 수 있다.

2. 데이터베이스 초기화 및 테이블 생성 SQL 파일 (create_table.sql)

다음으로, 데이터베이스 초기화 시 자동으로 실행될 SQL 파일을 작성한다. 이 파일에서는 테이블을 생성하고 초기 데이터를 삽입하는 작업을 수행한다.

 

db/initdb.d/create_table.sql

CREATE TABLE `package`
(
    `package_seq`  int         NOT NULL AUTO_INCREMENT COMMENT '패키지 순번',
    `package_name` varchar(50) NOT NULL COMMENT '패키지 이름',
    `count`        int                  DEFAULT NULL COMMENT '이용권 수, NULL인 경우 무제한',
    `period`       int                  DEFAULT NULL COMMENT '기간(일), NULL인 경우 무제한',
    `created_at`   timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 일시',
    `modified_at`  timestamp            DEFAULT NULL COMMENT '수정 일시',
    PRIMARY KEY (`package_seq`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='패키지';

CREATE TABLE `pass`
(
    `pass_seq`        int         NOT NULL AUTO_INCREMENT COMMENT '이용권 순번',
    `package_seq`     int         NOT NULL COMMENT '패키지 순번',
    `user_id`         varchar(20) NOT NULL COMMENT '사용자 ID',
    `status`          varchar(10) NOT NULL COMMENT '상태',
    `remaining_count` int                  DEFAULT NULL COMMENT '잔여 이용권 수, NULL인 경우 무제한',
    `started_at`      timestamp   NOT NULL COMMENT '시작 일시',
    `ended_at`        timestamp            DEFAULT NULL COMMENT '종료 일시, NULL인 경우 무제한',
    `expired_at`      timestamp            DEFAULT NULL COMMENT '만료 일시',
    `created_at`      timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 일시',
    `modified_at`     timestamp            DEFAULT NULL COMMENT '수정 일시',
    PRIMARY KEY (`pass_seq`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='이용권';

CREATE TABLE `booking`
(
    `booking_seq`  int         NOT NULL AUTO_INCREMENT COMMENT '예약 순번',
    `pass_seq`     int         NOT NULL COMMENT '이용권 순번',
    `user_id`      varchar(20) NOT NULL COMMENT '사용자 ID',
    `status`       varchar(10) NOT NULL COMMENT '상태',
    `used_pass`    tinyint(1) NOT NULL DEFAULT '0' COMMENT '이용권 사용 여부',
    `attended`     tinyint(1) NOT NULL DEFAULT '0' COMMENT '출석 여부',
    `started_at`   timestamp   NOT NULL COMMENT '시작 일시',
    `ended_at`     timestamp   NOT NULL COMMENT '종료 일시',
    `cancelled_at` timestamp            DEFAULT NULL COMMENT '취소 일시',
    `created_at`   timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 일시',
    `modified_at`  timestamp            DEFAULT NULL COMMENT '수정 일시',
    PRIMARY KEY (`booking_seq`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='예약';

CREATE TABLE `user`
(
    `user_id`     varchar(20) NOT NULL COMMENT '사용자 ID',
    `user_name`   varchar(50) NOT NULL COMMENT '사용자 이름',
    `status`      varchar(10) NOT NULL COMMENT '상태',
    `phone`       varchar(50)          DEFAULT NULL COMMENT '연락처',
    `meta`        TEXT                 DEFAULT NULL COMMENT '메타 정보, JSON',
    `created_at`  timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 일시',
    `modified_at` timestamp            DEFAULT NULL COMMENT '수정 일시',
    PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='사용자';
  • 위 쿼리는 package, pass, booking, user 테이블을 생성하는 내용을 담고 있다.
  • 각 테이블은 프로젝트의 핵심 데이터를 관리하며, 기본적인 필드와 관계를 정의한다. 생성된 테이블은 초기 데이터 삽입과 함께 다음 단계에서 사용된다.

다음으로, 이 테이블들에 초기 데이터를 삽입하기 위해 별도의 SQL 파일을 작성한다.

db/initdb.d/insert_data.sql

INSERT INTO package (package_name, count, period, created_at)
VALUES ('Starter PT 10회', 10, 60, '2022-08-01 00:00:00'),
       ('Starter PT 20회', 20, 120, '2022-08-01 00:00:00'),
       ('Starter PT 30회', 30, 180, '2022-08-01 00:00:00'),
       ('무료 이벤트 필라테스 1회', 1, NULL, '2022-08-01 00:00:00'),
       ('바디 챌린지 PT 4주', NULL, 28, '2022-08-01 00:00:00'),
       ('바디 챌린지 PT 8주', NULL, 48, '2022-08-01 00:00:00'),
       ('인바디 상담', NULL, NULL, '2022-08-01 00:00:00');

INSERT INTO `user` (user_id, user_name, status, phone, meta, created_at)
VALUES ('A1000000', '우영우', 'ACTIVE', '01011112222', NULL, '2022-08-01 00:00:00'),
       ('A1000001', '최수연', 'ACTIVE', '01033334444', NULL, '2022-08-01 00:00:00'),
       ('A1000002', '이준호', 'INACTIVE', '01055556666', NULL, '2022-08-01 00:00:00'),
       ('B1000010', '권민우', 'ACTIVE', '01077778888', NULL, '2022-08-01 00:00:00'),
       ('B1000011', '동그라미', 'INACTIVE', '01088889999', NULL, '2022-08-01 00:00:00'),
       ('B2000000', '한선영', 'ACTIVE', '01099990000', NULL, '2022-08-01 00:00:00'),
       ('B2000001', '태수미', 'ACTIVE', '01000001111', NULL, '2022-08-01 00:00:00');
  • 위 SQL 파일에서는 패키지와 사용자 테이블에 초기 데이터를 삽입한다.
  • 이 데이터를 통해 이후 API 개발 및 테스트를 원활히 진행할 수 있다.

3. Makefile을 이용한 명령어 관리

Docker 명령어를 간편하게 실행하기 위해 Makefile을 작성한다. Makefile을 사용하면 복잡한 명령어를 간단히 단축해 사용할 수 있다.

db-up:
	docker-compose up -d --force-recreate

db-down:
	docker-compose down -v

위 Makefile에서는 db-up과 db-down이라는 두 가지 명령어를 정의했다.

  • db-up: docker-compose up -d --force-recreate 명령어를 통해 MySQL 컨테이너를 백그라운드에서 재실행한다. 이때 컨테이너가 이미 실행 중이더라도, 강제로 다시 생성(recreate)한다.
  • db-down: docker-compose down -v 명령어를 통해 컨테이너를 종료하고, 컨테이너에 연결된 볼륨까지 모두 삭제한다.

이제 make db-up 명령어를 사용해 MySQL을 손쉽게 실행할 수 있다.

 

4. Docker Compose 파일 생성

이제 MySQL 컨테이너를 실행하기 위해 docker-compose.yml 파일을 작성한다. 이 파일에서는 MySQL 이미지를 다운로드받아 실행하고, 앞서 작성한 my.cnf 파일과 SQL 파일을 반영하여 설정을 자동화한다.

 

터미널에서 docker-compose.yml 파일을 생성한다.

touch docker-compose.yml

 

이후, 아래와 같이 docker-compose.yml 파일을 작성한다.

version: "3.8"
services:
  mysql:
    container_name: mysql_local
    image: mysql:8.0.30
    volumes:
      - ./db/conf.d:/etc/mysql/conf.d
      - ./db/initdb.d:/docker-entrypoint-initdb.d
    ports:
      - "3306:3306"
    environment:
      - MYSQL_DATABASE=pass_local
      - MYSQL_USER=pass_local_user
      - MYSQL_PASSWORD=passlocal123
      - MYSQL_ROOT_PASSWORD=passlocal123
      - TZ=Asia/Seoul

위 설정이 완료되면, make db-up 명령어로 MySQL을 컨테이너로 올린다.

make db-up

이제 MySQL이 Docker로 실행되는지 확인할 수 있다.

이미지에서 확인할 수 있듯이, MySQL 이미지가 정상적으로 다운로드되고 컨테이너가 실행된 것을 확인할 수 있다.

 

5. Docker Desktop을 통해 컨테이너 상태 확인

Docker Desktop을 열어보면, MySQL 컨테이너가 실행 중인 것을 볼 수 있다.

이 화면에서 mysql_local이라는 컨테이너가 실행 중임을 알 수 있다. 이를 통해 MySQL이 정상적으로 실행되었음을 확인할 수 있다.

 

6. 데이터베이스 테이블 구조 확인

이제 DB에 접속하면 생성된 테이블을 확인할 수 있다. DB 관리 툴로는 DBeaver를 이용하여 연결한다. 

 

각 테이블의 구조와 기능을 하나씩 살펴보자.

 

6.1 패키지 테이블

먼저, 가장 상위 단위인 package 테이블을 살펴보자.

가장 상위 단위인 패키지 테이블은 다음과 같다.

package 테이블에서는 다양한 패키지 상품의 정보를 관리한다. 주요 컬럼은 다음과 같다.

  • package_seq: 패키지의 고유 식별자(순번)로, 자동 증가(AUTO_INCREMENT) 설정이 되어 있다.
  • package_name: 패키지 이름을 저장하는 컬럼이다.
  • count: 이용권 수를 나타내며, NULL 값이 가능한데, 이는 이용권 수가 무제한인 경우를 대비한 설정이다.
  • period: 패키지의 기간(일)을 저장하며, NULL 값일 경우 무제한 기간을 의미한다.
  • created_at: 생성 일시를 저장한다.
  • modified_at: 수정 일시를 저장하는 컬럼이다.

6.2 이용권 테이블

package_seq 값을 참조하여 pass를 생성할 수 있다. pass 테이블은 다음과 같다.

pass 테이블에서는 개별 패스(이용권)에 대한 정보를 관리하며, 주요 컬럼은 다음과 같다.

  • pass_seq: 이용권의 고유 식별자(순번)로, 자동 증가(AUTO_INCREMENT) 설정이 되어 있다.
  • package_seq: 관련된 패키지의 식별자.
  • user_id: 이용권을 사용하는 사용자의 ID.
  • status: 이용권의 상태를 나타내며, 만료 여부를 확인할 수 있다.
  • remaining_count: 남은 이용권 수를 나타내며, 이는 패키지 테이블의 count 값에 대응된다.
  • started_at: 이용권 사용 시작 일시.
  • ended_at: 이용권 사용 종료 일시로, NULL인 경우 무제한을 의미한다.
  • expired_at: 이용권 만료 일시.
  • created_at: 생성 일시.

6.3 예약 테이블

pass_seq 값을 참조하여 booking을 생성할 수 있다. booking 테이블은 다음과 같다.

booking 테이블은 사용자가 특정 시간에 예약한 내역을 관리하며, 주요 컬럼은 다음과 같다.

  • booking_seq: 예약의 고유 식별자(순번)로, 자동 증가(AUTO_INCREMENT) 설정이 되어 있다.
  • pass_seq: 관련된 이용권의 식별자.
  • user_id: 예약을 진행한 사용자의 ID.
  • status: 예약 상태를 나타내며, 예약이 취소될 수 있기 때문에 이 컬럼이 추가되었다.
  • used_pass: 이용권 사용 여부를 판단하기 위해 설정된 boolean 컬럼.
  • attended: 출석 여부를 판단하기 위해 설정된 boolean 컬럼.
  • started_at: 예약 시작 일시.
  • ended_at: 예약 종료 일시.
  • cancelled_at: 예약 취소 일시.
  • created_at: 예약 생성 일시.
  • modified_at: 예약 수정 일시.

6.4 사용자 테이블

이제 모든 테이블에 사용되는 user_id 값이 정의된 user 테이블을 살펴보자.

user 테이블은 사용자에 대한 기본 정보를 관리하며, 주요 컬럼은 다음과 같다.

  • user_id: 사용자의 고유 ID.
  • user_name: 사용자의 이름.
  • status: 사용자의 상태.
  • phone: 사용자의 연락처.
  • meta: JSON 형태로 저장되는 메타 정보. 사용자와 관련된 추가 정보를 저장하는 데 사용된다.
  • created_at: 사용자 생성 일시.
  • modified_at: 사용자 수정 일시.

6.5 테이블 간의 관계도

이를 관계도로 표현하면 다음과 같다.

  • 위 관계도를 보면, package에서 여러 개의 pass를 만들 수 있고, pass는 여러 개의 booking을 가질 수 있다.
  • 각 booking은 반드시 pass와 연결되어 있으며, 모든 테이블은 user와 연관되어 있다.

이번 포스팅에서는 Docker를 이용해 MySQL 데이터베이스를 설치하고, 주요 테이블을 생성한 후 그 구조와 관계를 살펴보았다. 다음 시간에는 배치 프로젝트에서 이 데이터베이스에 접근하는 설정을 진행하고, API를 사용해 간단한 CRUD 기능을 구현해 볼 것이다.