express에 대해 배워가는 중이기에, 좋은 해결법이라고 보기에는 힘듭니다.
얕은 지식 + 바닐라js의 대환장 파티이므로, 더 좋은 해결책을 아시는 분은 댓글 달아주시면 감사하겠습니다..!
spring에서는 특정 인터페이스로 구성되어 있는 빈들을 만들어 두고, profile 구분을 통해 동작될 빈을 선택하여 실행할 수 있습니다.
그러나 자유도가 높은 express에서는 개발자가 직접 이를 제어해야 하는 것으로 보입니다.
아주 간단하게, 개발 환경과 데모 환경을 구분하여 data access를 진행해 보도록 하겠습니다.
package.json의 스크립트에 개발 환경과 데모 환경을 구분지어 봅시다.
...
"scripts": {
"dev": "NODE_ENV=dev node main.js --watch",
"demo": "NODE_ENV=demo node main.js --watch",
...
},
...
바닐라js에는 인터페이스가 존재하지 않으므로 테이블 데이터 획득(selectRecords), 데이터 작성(insertRecord)에 대한 함수들을 양쪽 모두에 동일한 시그니처로 구현하였습니다.
import mysql from "mysql2/promise";
export default class MysqlDao {
#connection;
constructor() {
this.#connection = mysql.createConnection({
host: "localhost",
user: "eora21",
database: "dev",
connectTimeout: 500,
});
}
async selectRecords(tableName) {
const connection = await this.#connection;
const [results, fields] = await connection.execute(
`SELECT *
FROM ${tableName}`,
);
return results;
}
async insertRecord(tableName, record) {
const valuesQuery = Object.values(record)
.map(value => typeof value === "string" ? `"${value}"` : value)
.join(",");
const connection = await this.#connection;
return connection.execute(
`INSERT INTO ${tableName}
VALUES (NULL, ${valuesQuery})`,
);
}
}
import {LowSync} from "lowdb";
import {JSONFileSync} from "lowdb/node";
export default class LowdbDao {
#connectTable(tableName) {
const table = new LowSync(new JSONFileSync(`DB/table/${tableName}.json`), {});
table.read();
return table;
}
async selectRecords(tableName) {
const table = this.#connectTable(tableName);
return table.data["records"];
}
async insertRecord(tableName, record) {
const table = this.#connectTable(tableName);
const data = table.data;
const nextId = data["nextId"]++;
record = {id: nextId, ...record};
data["records"].push(record);
await table.write();
return [{insertId: nextId}];
}
}
import MysqlDao from "./MysqlDao.js";
import LowdbDao from "./LowdbDao.js";
const ENV_DAO = {
dev: () => new MysqlDao(),
demo: () => new LowdbDao(),
}
export function getDao() {
const daoCallback = ENV_DAO[process.env.NODE_ENV] ?? wrongEnv;
return daoCallback();
}
function wrongEnv() {
throw new Error("허용되지 않는 ENV입니다.");
}
객체 생성을 콜백으로 지정한 이유는, demo 환경인 경우 MysqlDao를 생성조차 하지 않기 위해서입니다.
import {getDao} from "../../DB/dao/dao.js";
const dao = getDao();
class Repository {
#tableName;
constructor(tableName) {
this.#tableName = tableName;
}
async getRecords() {
return await dao.selectRecords(this.#tableName);
}
async addRecord(record) {
return await dao.insertRecord(this.#tableName, record);
}
}
아무래도 스프링만큼의 명확성은 지니지 못 한 상태입니다.
조금이라도 더 명확한 코드를 위해서는 ts를 사용하는 게 낫지 않을까 하는 고민이 있습니다.
그러나 express 환경에서도 분명 이와 같은 고민이 이뤄졌을 것이라 생각합니다.
좋은 예시를 읽어보고 싶다는 마음이 큽니다. 혹시나 잘 알고 계시는 분이 있다면 댓글로 알려주시면 감사하겠습니다.