fs - node.js 파일시스템 접근할 수 있는 모듈이며 파일 읽기 쓰기 기능을 제공한다. 동기적 및 비동기적 방식 모두 호환이 가능하다.
데이터베이스에서 데이터를 구조화된 형태로 저장하는 방식으로 각각의 열이 특정한 유형의 데이터를 나타내고 행은 실제 데이터를 포함한다.
클라이언트에서 어느정도 정보를 알고 있어야 서버에 보낼 내용을 정의할 수 있기 때문에 설정한다고 볼 수 있다.
방식은 파일, CDN, DB 로 구성할 수 있으며 서버와 클라이언트는 각각의 데이터 테이블을 갖는 것이 아닌, 같은 테이블을 참조한다.
let gameAssets = {};
export const getGameAssets = ()=>{
return gameAssets;
}
위처럼 코드를 설계하는 이유는 보안적인 이유때문이다. 데이터 캡슐화를 통해 직접적으로 gameAssets 객체에 접근할 수 없기 때문에 외부에서 데이터를 수정하거나 변경하는 것을 방지할 수 있다.
getGameAssets 함수를 통하여 데이터에 접근하면 읽기전용으로 접근하게 되어 직접적인 객체 변경을 할 수 없어 안전하게 사용이 가능하다.
또 데이터에 직접 접근하지 않고 함수를 통해 접근하면 데이터를 반환하기 전 검증이나 로그 작업을 추가할 수 있기 때문에 유지보수에 용이하다.
return {...gameAssets}
로 바꿔서 사용하면 얕은 복사로 데이터를 반환해주기 때문에 원본 데이터 조작 위험을 방지할 수 있다.
Promise는 비동기 작업을 처리할 때 사용한다.
const test = new Promise((resolve,reject) => {
let success = true;
if(success) {
resolve("매우 성공적");
}else{
reject("실패 ㅋ");
}
});
test
.then(성공 시 이거 처리)
.catch(실패 시 이거 처리)
resolve는 성공을 의미하고, reject는 실패를 의미한다.
ES6 이전 dirname, filename 이 있었지만, 이후에는 없어져서 새로 만들어 주어야 한다.
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
const __filename = fileURLToPath(import.meta.url); // 현재 파일의 절대경로를 구해준다.
const __dirname = path.dirname(__filename); // 파일 이름을 빼고 디렉토리만 구해준다.
const basePath = path.join(__dirname, '../../assets'); // 현재 디렉토리에서 두번 뒤로 간 후 assets 디렉토리를 지정
const readFileAsync = (filename) => {
return new Promise((resolve,reject) => {
fs.readFile(path.join(basePath, filename), 'uft8', (err,data)=>{
if(err) {
reject(err);
return;
}
resolve(JSON.parse(data));
});
});
};
export const loadGameAssets = async () => {
try {
// 각각의 파일을 동기처리하고 최종 Promise.all은 비동기처리한다.
const [stages, items, itemUnlocks] = await Promise.all([
readFileAsync("stage.json"),
readFileAsync("item.json"),
readFileAsync("item_unlock.json"),
]);
// 불러온 에셋을 객체에 담아 리턴한다.
gameAssets = { stages, items, itemUnlocks };
return gameAssets;
} catch (error) {
throw new Error("Failed to load game assets" + error.message);
}
};
export const loadGameAssets = async () => {
try{
// 디렉토리 내 파일을 불러옴
const files = await fs.readdir(basePath); // basePath는 위에서 assets 디렉토리를 선언한 변수이다.
// 파일 중 json 파일만 걸러냄
const jsonFiles = files.filter((file)=>file.endsWith(".json")); // endsWith(찾을 문자열(필수),길이(선택))
// 읽어온 json 파일을 readFileAsync에 씌움
const jsonReadFileAsync = jsonFiles.map((file)=>readFileAsync(file));
// Promise.all 처리
const results = await Promise.all(jsonReadFileAsync);
// 내보낼 객체 생성
const gameAssets = jsonFiles.reduce((assets, fileName, idx)=>{
const key = fileName.replace(".json","");
assets[key] = results[idx];
return assets;
},{})
// 최종적으로 불러온 json 객체 내보냄
return gameAssets;
} catch (error) {
throw new Error("Failed to load game assets" + error.message);
}
}