개발일지/TIL(Today I Learned)

2024-11-13

프린스 알리 2024. 11. 13.

내일배움캠프 Node.js 트랙 13일차

ZEP에서 이루어진 로그라이크 게임 개발 프로젝트

json을 이용해 로컬 파일에 게임 데이터를 저장해보자

미리 고백하자면 아직 세이브 기능을 완벽하게 만들진 못했기 때문에 한 번 더 되짚어 보자는 생각으로 이 글을 적어두려고 한다. 내용을 정확히 이해한 것도 아니지만 언젠가 이해할 날이 온다면…아마 오늘 내가 괴롭게 고민했던 덕분일 것이다… : )

// 새로운 js파일을 만들었다! 이곳에서 json 관련 작업을 해보자.

import fsp from 'fs/promises'; // fs/promises에서 fs를 가져온다.

 

먼저 node.js의 내장 모듈인 fs에 대해 말해보자면, Node.js의 기본 파일 시스템 모듈이라고 설명할 수 있겠다. 파일 읽고 쓰기, 콜백 함수 데이터 전달 받기, 디렉토리 작업 등 다양한 기능을 제공한다. 내가 이 프로젝트를 하면서 사용하게 된 모듈은 바로 이 fs의 프로미스(promises) 버전이다. 쉽게 말해 fs를 비동기식으로 처리해주는 모듈이라고 볼 수 있겠다.

// JSON 파일을 로드하는 함수
let loadJson = async (filePath) => {
  try {
    const data = await fsp.readFile(filePath, 'utf8');
    return JSON.parse(data);
  } catch (err) {
    console.error('파일 읽기 오류:', err);
    return null; // 파일을 읽지 못했을 경우 null 반환
  }
};

 

json파일을 로드하는 데에 바로 이 fsp 모듈이 사용된다. filePath 경로에 있는 파일을 UTF-8 인코딩 방식으로 읽어오고 data에 그 내용이 문자열로 할당된다. JSON.parse(data)는 data 문자열을 JavaScript 객체로 파싱한 후 반환한다. try, catch 구문은 오류를 잡기 위해 쓰인 상황이다.

이를 통해서 업적 기능을 다음과 같이 만들어 보았다.

 

// 업적 완료하기

let unlockAchievement = async (filePath, index) => {
  try {
    let jsonData = await loadJson(filePath);
  
    // 업적 수정하기 (예: 첫 번째 업적의 isUnlocked를 true로 변경)
    if (jsonData && jsonData.achievements && jsonData.achievements.length > 0) {
      jsonData.achievements[index].isUnlocked = true; // 업적을 unlocked로 변경
    }
  
    // 수정된 데이터를 다시 JSON 문자열로 변환
    const updatedData = JSON.stringify(jsonData, null, 2);
  
    // 파일에 다시 쓰기
    await fsp.writeFile(filePath, updatedData, 'utf8');
  } catch (err) {
    console.error('파일 수정 오류:', err);
  }
};

 

위에서 만든 loadJson 함수를 통해 json파일에 문자열로 저장되어 있던 데이터(현재 배열 상태)를 JavaScript 객체로 변환하여 jsonData에 저장하였다. 게임 내에서 특정한 조건을 달성했을 때 해당 업적이 있는 인덱스를 매개변수로 받아온다면 그 요소의 불리언 값을 변경할 수 있을 것이다. 이를 다시 json 문자열로 변환하여 파일에 다시 쓴다면 업적 읽고→수정하고→다시 쓰기의 과정이 완료되는 것이다.

 

// 완료한 업적 불러오기
async function getAchievements() {
  let jsonData;
  if (!jsonData) {
    jsonData = await loadJson('./data.json'); // 업적 데이터 파일 경로
  }
  if (jsonData && jsonData.achievements) {
    jsonData.achievements.forEach((achievement) => {
      if (achievement.isUnlocked) {
        console.log(
          chalk.hex('#E8B86D')(`====================|**⁂**|====================
  
  업적: ${achievement.name}
  설명: ${achievement.description}
  
===============================================`),
        );
      }
    });
  } else {
    console.log('업적 데이터가 없습니다.');
  }
}

 

완료한 업적을 불러올 때는 위와 같은 함수를 사용하였다. 실제 게임을 실행한 모습은 다음과 같다.

이제 이 방법으로 세이브 기능도 완성해볼까 싶은데…당장은 해결되지 않은 문제가 있어서 내일의 과제로 남겨두기로 했다.

'개발일지 > TIL(Today I Learned)' 카테고리의 다른 글

2024-11-15  (1) 2024.11.15
2024-11-14  (1) 2024.11.14
2024-11-12  (1) 2024.11.12
2024-11-11  (5) 2024.11.11
2024-11-08  (3) 2024.11.08

댓글