로그인게임하기
현장 강의록

[현장 강의록 3] 엑셀 데이터 가공과 데이터베이스 설계

2026.10.11

현장 강의록 · 애니메이션고 2022 · 3편

게임 데이터는 대부분 엑셀에서 태어납니다. 이 수업에서는 엑셀로 밸런스 점수를 계산하고, CSV 로 내보내 데이터베이스로 옮기고, 캐릭터 · 장비 · 아이템 · 몬스터 · 무기 · 퀘스트 표를 설계해 게임 콘텐츠를 SQL 로 다뤘습니다.

수업 정보

2022년 1학기 한국애니메이션고등학교 2학년 「게임 개발과 미들웨어」 3강 「게임 데이터 처리 #2」에서 가르친 내용입니다.

SHEET

원본 시트와 더미 시트

엑셀 파일에는 시트를 두 장 둡니다. 원본 시트는 기획자가 보고 고치는 시트라서 머리글(ID, 이름, 공격력…)과 계산 칸이 있습니다. 더미 시트는 데이터베이스로 내보내기 위한 시트라서 머리글 없이 값만 원본 시트를 참조해 채웁니다.

원본 시트

  • 머리글이 있습니다
  • 종합 밸런스 같은 계산 칸이 있습니다
  • 기획자가 직접 고칩니다

더미 시트

  • 머리글이 없습니다
  • 데이터베이스 칸 순서와 똑같습니다
  • 원본 시트를 참조하므로 손대지 않습니다

이렇게 나누면 기획자는 보기 좋은 시트에서 일하고, 내보내기는 언제나 같은 모양으로 나옵니다.

BALANCE

실습: 종합 밸런스 점수

문제
  1. 공격력 1배, 생명력 1.2배, 방어력 1배를 더한 종합 밸런스 점수를 계산합니다.
  2. 종합 밸런스 점수가 낮은 순으로 정렬합니다.

엑셀 수식: =C2*1 + D2*1.2 + E2*1 (C 공격력, D 생명력, E 방어력)

ID이름공격력생명력방어력종합 밸런스
3스미스4206.40
2레온3306.60
4소피아5117.20
5마이클65012.00
1루시아27212.40
6헬룬77217.40

숫자로 늘어놓으면 스미스와 레온이 가장 약하고 헬룬이 가장 강하다는 것이 보입니다. 게임을 고치기 전에 엑셀에서 먼저 비교해 보는 습관이 기획자와 프로그래머 모두에게 필요합니다. 생명력에 1.2 를 곱한 것은 이 게임에서 오래 버티는 힘을 조금 더 높게 친다는 기획 판단입니다.

CSV

CSV 로 내보내고 UTF-8 로 바꾸기

  1. 엑셀원본 시트에서 값을 고칩니다
  2. CSV 내보내기더미 시트를 CSV 로 저장
  3. UTF-8 변환Notepad++ 에서 인코딩 변경
  4. 가져오기SQLite 콘솔의 .import

CSV 는 값을 쉼표로 나눈 텍스트 파일입니다. 한국어 Windows 의 엑셀은 CSV 를 ANSI(CP949) 로 저장하는데, SQLite Browser 와 Unity 는 UTF-8 로 읽습니다. 그래서 가져오기 전에 Notepad++ 같은 편집기로 인코딩을 UTF-8 로 바꿉니다.

SQLite3 Console3강 13쪽
C:\sqlite3> sqlite3 ClientGameData.db
sqlite> .separator ","
sqlite> DELETE FROM Characters;
sqlite> .import Characters.csv Characters
sqlite> SELECT * FROM Characters;
1,루시아,2,7,2,0,0
2,레온,3,3,0,0,0
3,스미스,4,2,0,0,0
4,소피아,5,1,1,0,0
5,마이클,6,5,0,0,0
6,헬룬,7,7,2,0,0
명령하는 일
.separator ","값을 나누는 글자를 쉼표로 정합니다
DELETE FROM Characters표의 행을 모두 지웁니다. 다시 가져올 때 같은 ID 가 겹치지 않게 합니다
.import 파일 표CSV 의 줄마다 표에 행을 넣습니다
콘솔에서 한글이 깨져 보일 때

SQLite 콘솔은 ANSI 로 읽고, SQLite Browser 와 Unity 는 UTF-8 로 읽습니다. UTF-8 로 바꿔 가져온 뒤 콘솔에서 한글이 깨져 보이는 것은 정상입니다. Browser 나 Unity 에서 바르게 보이면 성공입니다.

실습: 엑셀 데이터를 고쳐 다시 가져오기
  1. 엑셀 데이터 시트에 캐릭터를 10행까지 늘립니다.
  2. 더미 시트에서 데이터를 받아 CSV 로 내보냅니다.
  3. Notepad++ 로 인코딩을 UTF-8 로 바꿉니다.
  4. SQLite 콘솔로 데이터를 가져와 SELECT 로 확인합니다.
MODEL

여러 표를 설계하기

캐릭터, 장비 칸, 아이템 상자, 몬스터, 퀘스트를 그린 나무판들이 색 끈으로 이어지고 각 판 위에 금색 열쇠 자리가 있는 그림
표마다 기본 키(금색 열쇠)가 있고, 끈은 다른 표를 가리키는 외래 키입니다.

게임에는 캐릭터 표 하나로 담을 수 없는 정보가 많습니다. 수업에서는 MMORPG 를 떠올리며 표를 여섯 개로 나눴습니다.

표역할주요 칸기본 키
Characters캐릭터 정보기본 정보, 전투 능력치, 실시간 정보(위치 등)ID
Equipment장착하고 있는 장비장착 칸 4개 (ItemList 의 ID 를 가리킴)CharacterID
ItemList게임에서 얻은 모든 아이템아이템 ID, 종류, 수량, 주인 IDID, 자동 증가
Monster몬스터 정보기본 정보, 전투 능력치, 스폰 시간, 스폰 확률, 대기 위치ID
Weapon무기 정보이름, 공격력, 방어력ID
Quest퀘스트 정보제목, 대사, 임무, 보상 ID, 보상 수량, 선행 퀘스트 IDID
게임 데이터베이스 표 설계CharactersID (PK)NameAttackPointHealthPointDefensePointPosX · PosYEquipmentCharacterID (PK, FK)Slot1 (FK)Slot2 (FK)Slot3 (FK)Slot4 (FK)ItemListID (PK, 자동 증가)ItemTypeAmountOwnerID (FK)MonsterID (PK)Name전투 능력치SpawnTimeSpawnRatePosX · PosYWeaponID (PK)NameAttackPointDefensePointQuestID (PK)Title · DialogueMissionRewardID (FK)RewardAmountPrevQuestID노란 칸: 기본 키(PK) 주황 화살표: 외래 키(FK) 가 가리키는 표
여섯 표의 설계. 칸 이름은 예시입니다.
말뜻
기본 키 (Primary Key)행을 구별하는 칸입니다. 같은 값이 두 번 나올 수 없습니다
외래 키 (Foreign Key)다른 표의 기본 키를 가리키는 칸입니다. 장비 칸이 아이템을 가리키는 식입니다
자동 증가 (Auto Increment)행을 넣을 때 기본 키를 데이터베이스가 1 씩 늘려 정합니다. 아이템처럼 계속 새로 생기는 행에 씁니다

Equipment 표의 기본 키가 CharacterID 라는 점이 재미있습니다. 캐릭터마다 장비 줄이 하나씩 있으니 캐릭터 ID 가 곧 장비 줄의 이름이 됩니다.

실습: 표 만들고 채우기
  1. SQLite Browser 로 여섯 표를 만듭니다.
  2. 표마다 엑셀 시트를 원본 · 더미 두 장씩 만들고 데이터를 1~3행 넣습니다.
  3. 인코딩을 바꾸고 SQLite 콘솔로 데이터를 가져옵니다.
  4. CharacterRow 를 참고해 표마다 스키마 클래스(WeaponRow 등)를 만듭니다.
WEAPON

실습: 캐릭터에 무기 쥐여 주기

문제
  1. GameDB 에 public List<WeaponRow> GetWeapon(int id) 를 만듭니다.
  2. Weapon 클래스에 Init(int id) 를 만들고 안에서 GetWeapon 을 부릅니다.
  3. Character 의 Init 에서 myWeapon.Init() 을 부릅니다.
  4. Weapon 에 Text 를 붙이고 공격력을 띄웁니다.
Weapon.cs설명용 예시 — 위 실습의 답
public class Weapon : MonoBehaviour
{
    public Text attackText;
    public int AttackPoint { get; private set; }

    public void Init(int id)
    {
        List<GameDB.WeaponRow> rows = GameDB.GetSingleton().GetWeapon(id);   // SELECT * FROM Weapons WHERE ID={id}
        if (rows == null || rows.Count == 0) return;
        AttackPoint = rows[0].AttackPoint;
        attackText.text = AttackPoint.ToString();
    }
}

캐릭터 → 무기 → GameDB 로 이어지는 호출이 생겼습니다. 이 관계는 7편의 클래스 다이어그램과 시퀀스 다이어그램에 다시 나옵니다.

QUERY

게임 콘텐츠를 위한 쿼리

게임 콘텐츠를 위한 Query3강 22쪽
# 캐릭터 강화
UPDATE Characters SET AttackPoint = AttackPoint + 1, HealthPoint = HealthPoint + 1 WHERE ID={0};
# 새 아이템 획득 (자동 증가 키 주의)
INSERT INTO ItemList (ItemType, Amount, OwnerID) VALUES ({0}, {1}, {2});
# 가진 아이템 조회
SELECT * FROM ItemList WHERE OwnerID={0};

아이템을 넣을 때 ID 를 적지 않는 이유가 자동 증가입니다. ID 는 데이터베이스가 정하므로 INSERT 에서 ID 칸을 빼야 합니다.

실습: 캐릭터 강화
  1. GameDB 에 AddAttackPoint(int id, int point) 를 만듭니다.
  2. GameDB 에 AddHealthPoint(int id, int point) 를 만듭니다.
  3. Character.cs 에 EnchantAttackPoint(int point), EnchantHealthPoint(int point) 를 만듭니다.
  4. Character.cs 에 RefreshCharacterInfo() 를 만들어 이름 · 공격력 · 방어력 · 생명력 글자를 새 값으로 바꿉니다.
지금이라면

수업에서는 값을 {0} 자리에 끼워 SQL 을 만들었습니다. 실제 서비스라면 값을 SQL 문자열과 따로 넘기는 파라미터 바인딩을 씁니다. 이유는 ElServer 리뷰에 정리했습니다.

NOW

지금 100턴에서는

「졸업까지 100턴」의 엑셀은 58개이고, 사람이 손으로 CSV 를 옮기지 않습니다. 도구가 엑셀을 읽어 JSON 과 DB 로 함께 내보냅니다. 수업에서 손으로 했던 "엑셀 → CSV → 인코딩 → import" 가 어떻게 자동화되었는지는 구조 읽기 1편에서 볼 수 있습니다.

정리

  1. 원본 시트와 더미 시트를 나눕니다. 사람은 보기 좋은 시트에서, 내보내기는 같은 모양의 시트에서.
  2. CSV 는 UTF-8 로. 인코딩이 다르면 한글이 깨집니다.
  3. 표를 나누고 키로 잇습니다. 기본 키로 행을 구별하고, 외래 키로 다른 표를 가리킵니다.

다음 편에서는 네트워크의 기초, 통신 규약과 직렬화와 패킷을 다룹니다.

← 개발 노트 목록