Node 강의/주특기 플러스

2-8 DB 마이그레이

kagan-draca 2024. 11. 1. 11:12

먼저, 

DB2_NAME = USER_DB
DB1_NAME = GAME_DB

 

우리가 USER_DB와 GAME_DB를 사용하겠다고 작성해놨기 때문에

위와 같이 GAME_DB와 USER_DB를 만들어줘야 합니다.

 

 GAME_DB와 USER_DB에 테이블을 생성하기 위해서

db/sql 폴더를 만들고 user_db.sql 파일을 생성해줍니다.

 

user_db.sql에는

CREATE TABLE IF NOT EXISTS user
(
    id         VARCHAR(36) PRIMARY KEY,
    device_id  VARCHAR(255) UNIQUE NOT NULL,
    last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

위와 같이 user 테이블을 생성해줄건데 만약 user 테이블이 존재하지 않을 경우에만 생성해줄 겁니다.

 

user 테이블 안에 Colum으로는 PK(Primary Key)가 될 id(유저를 구분 및 빠른 조회를 위한 id가 될 겁니다.), 유저가 게임에 접속한 device_id(실제 Id가 될 예정입니다.), last_login으로 유저가 로그인 할 때 마다 현재 시간을 기록해 놓을 컬럼, 마지막으로 생성된 날짜와 시간을 기록할 컬럼을 생성해줍니다.

 

CREATE TABLE IF NOT EXISTS game_end
(
    id    VARCHAR(36) PRIMARY KEY,
    user_id    VARCHAR(36) NOT NULL,
    start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    end_time   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    score      INT       DEFAULT 0,
    FOREIGN KEY (user_id) REFERENCES user (id)
);

GAME_DB에는 game_end 테이블로 게임이 끝났을 경우 기록할 테이블을 만들어줍니다.

 

user 테이블과 마찬가지로 PK(Primary Key)가 될 id(종료된 게임을 구분하기 위한 id), user_id (게임을 끝 마친 유저 id), 시작 시간, 끝 시간, 점수를 Colum으로 담아줍니다.

 

이렇게 정의한 테이블과 Colum을 생성해주기 위해

 

db/migration 폴더를 만들어주고 createSchemas.js 파일을 생성해줍니다.

import fs from 'fs';
import path from 'path';
import pools from '../database.js';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

위의 코드로 현재 파일이 존재하는 상위 폴더를 가져와 줍니다. 그 후,

const createSchemas = async () => {
  const sqlDir = path.join(__dirname, '../sql');
  try {
    // USER_DB SQL 파일 실행
    await executeSqlFile(pools.USER_DB, path.join(sqlDir, 'user_db.sql'));

    console.log('데이터베이스 테이블이 성공적으로 생성되었습니다.');
  } catch (error) {
    console.error('데이터베이스 테이블 생성 중 오류가 발생했습니다:', error);
  }
};

해당 폴더에서 '../sql'으로 폴더의 상위 폴더로 이동하고 sql 폴더로 이동해줍니다.

 

그리고 awit executeSqlFile(pools.USER_DB, path.join(sqlDir,'user_db.sql'));로

sql 폴더에 있는 user_db.sql이라는 파일에 접근해 USER_DB안에 생성할 테이블과 Colum이 생성될 수 있도록 해줍니다.

 

executeSqlFile 함수는

const executeSqlFile = async (pool, filePath) => {
  const sql = fs.readFileSync(filePath, 'utf8');
  const queries = sql
    .split(';')
    .map((query) => query.trim())
    .filter((query) => query.length > 0);

  for (const query of queries) {
    await pool.query(query);
  }
};

위와 같이 filePath에 작성된 경로의 파일을 사람이 인식하고 읽을 수 있는 utf8형식으로 fs.readFileSync로 파일을 읽어오고, 

const queries = sql.split(',').map((query)=> query.trim()).filter((query)=> query.length > 0)

으로 

CREATE TABLE IF NOT EXISTS user
(
    id         VARCHAR(36) PRIMARY KEY,
    device_id  VARCHAR(255) UNIQUE NOT NULL,
    last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS game_end
(
    id    VARCHAR(36) PRIMARY KEY,
    user_id    VARCHAR(36) NOT NULL,
    start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    end_time   TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    score      INT       DEFAULT 0,
    FOREIGN KEY (user_id) REFERENCES user (id)
);

; 클론을 기준으로 두 테이블을 나눠 읽어오면서 공백이 없게 파일에서 읽어온 내용을 sql 변수에 넣어줍니다.

 

그 후,

pool.query(query)로 지정한 DB에 query로 작성한 query를 실행시켜 줍니다.

 

이제 전역으로, createSchemas()함수를 호출해주면

createSchemas()
  .then(() => {
    console.log('마이그레이션이 완료되었습니다.');
    process.exit(0); // 마이그레이션 완료 후 프로세스 종료
  })
  .catch((error) => {
    console.error('마이그레이션 중 오류가 발생했습니다:', error);
    process.exit(1); // 오류 발생 시 프로세스 종료
  });

테이블이 생성될 것인데 이때, 예상치 못 한 오류가 발생할 수 있기 때문에 오류 처리 및 강제 종료 해줍니다.

 

테이블 생성 및 컬럼 생성을 시키기 위해 package.json의 기존 내용에서

{
  "name": "TcpJsOnlyServer",
  "version": "1.0.0",
  "main": "src/server.js",
  "license": "MIT",
  "scripts": {
    "start": "node src/server.js",
    "dev": "nodemon src/server.js",
  },
  "type": "module",
  "dependencies": {
    "dotenv": "^16.4.5",
    "lodash": "^4.17.21",
    "mysql2": "^3.11.3",
    "protobufjs": "^7.4.0",
    "uuid": "^10.0.0"
  },
  "devDependencies": {
    "nodemon": "^3.1.7",
    "prettier": "^3.3.3"
  }
}

 

  "scripts": {
    "start": "node src/server.js",
    "dev": "nodemon src/server.js",
  },

해당 부분에

 

  "scripts": {
    "start": "node src/server.js",
    "dev": "nodemon src/server.js",
    "migrate": "node src/db/migration/createSchemas.js"
  },

"migrate" : "node src/db/migration/createSchemas.js" 를 추가해줍니다. 

 

이제 터미널에서 migrate를 실행시켜보겠습니다.

실행 시킨 결과 위와 같이 테이블이 정상적으로 생성된 것을 확인할 수 있습니다.

 

DB에서 확인을 해보면

Table에 game_end와 user 테이블이 정상적으로 생성된 것을 볼 수 있고

game_end 테이블 안에 컬럼으로는

user 테이블 안에 컬럼으로는

으로 모든 colum이 정상적으로 생성된 것을 확인할 수 있습니다.

'Node 강의 > 주특기 플러스' 카테고리의 다른 글

2-9 유저 데이터 저장  (0) 2024.11.01
2-7 DB 연동  (0) 2024.10.31
2-6 세션, 핸들러 추가  (0) 2024.10.31
2-5 패킷 파싱  (0) 2024.10.28
2-4 프로토 파일 로드  (0) 2024.10.22