먼저,
우리가 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이 정상적으로 생성된 것을 확인할 수 있습니다.