데이터 기반 프로그래밍(Data-Driven Programming)의 기본 이해

데이터 기반 프로그래밍(Data-Driven Programming) 은 프로그램의 동작을 코드에 직접 고정하기보다, 데이터에 따라 결정되도록 설계하는 프로그래밍 방식이다.

핵심은 로직과 데이터를 분리하는 것이다.

예를 들어 게임에서 적의 체력을 코드에 직접 작성하면 적의 종류마다 코드를 수정해야 할 수 있다. 반면 적의 체력을 데이터로 관리하면 데이터를 변경하는 것만으로 적의 능력치를 조정할 수 있다.

게임 개발에서는 밸런스 조정, 콘텐츠 확장, 유지보수 비용 절감에 특히 유용하다.

일반적인 방식과 데이터 기반 방식의 차이

적 캐릭터 세 종류를 구현한다고 가정하자.

일반적인 프로그래밍

값과 동작이 코드에 직접 작성되어 있다.

public int GetEnemyHealth(string type)
{
    if (type == "Slime")
        return 30;

    if (type == "Goblin")
        return 80;

    if (type == "Boss")
        return 1000;

    return 0;
}

적을 추가하거나 체력을 변경하려면 코드를 수정해야 한다.

데이터 기반 프로그래밍

코드는 공통 동작을 담당하고, 데이터가 개별 값을 결정한다.

[System.Serializable]
public class EnemyData
{
    public string id;
    public int maxHealth;
    public int attackPower;
}

적마다 다른 능력치를 데이터로 정의하고, 공통 코드는 해당 데이터를 읽어 사용한다.

차이는 단순히 데이터를 파일로 옮겼다는 데 있지 않다. 새로운 콘텐츠를 추가하거나 기존 콘텐츠를 변경할 때 기존 로직을 수정할 필요가 얼마나 줄어드는가가 핵심이다.

데이터 기반 프로그래밍의 구조

일반적인 데이터 기반 시스템은 다음과 같은 구조로 설계할 수 있다.

데이터 계층

JSON · CSV · ScriptableObject · 데이터베이스

데이터 로딩 및 검증

파싱 · 유효성 검사 · 캐싱

게임 로직

전투 · 이동 · 성장 · 보상 처리

실행 결과

캐릭터 생성 · 전투 결과 · 게임 밸런스

예를 들어 전투 로직은 적의 종류를 일일이 구분하지 않고, 전달받은 maxHealth와 attackPower를 사용해 동작할 수 있다.

이렇게 하면 콘텐츠 데이터와 전투 시스템을 독립적으로 관리하기 쉬워진다.

Unity에서 구현하는 데이터 기반 프로그래밍

Unity에서는 ScriptableObject, JSON, CSV 등을 활용해 데이터 기반 시스템을 구현할 수 있다.

ScriptableObject 활용

ScriptableObject는 Unity에서 데이터를 에셋 형태로 저장하고 관리할 수 있도록 제공하는 클래스다.

using UnityEngine;

[CreateAssetMenu(
    fileName = "EnemyData",
    menuName = "Game/Enemy Data"
)]
public class EnemyData : ScriptableObject
{
    public string enemyName;
    public int maxHealth = 100;
    public int attackPower = 10;
    public float moveSpeed = 3f;
}

이 클래스를 작성하면 Unity 에디터에서 적의 데이터를 저장하는 에셋을 생성할 수 있다.

예를 들어 다음과 같이 데이터를 구성할 수 있다.

적 종류체력공격력이동 속도
슬라임3052.0
고블린80123.5
보스1,000501.5

이 값들은 코드 변경 없이 Unity 에디터에서 수정할 수 있다.

데이터에 따라 동작하는 캐릭터

using UnityEngine;

public class Enemy : MonoBehaviour
{
    [SerializeField]
    private EnemyData data;

    private int currentHealth;

    private void Awake()
    {
        currentHealth = data.maxHealth;
    }

    public void TakeDamage(int damage)
    {
        currentHealth = Mathf.Max(
            0,
            currentHealth - damage
        );
    }

    public int GetAttackPower()
    {
        return data.attackPower;
    }
}

Enemy는 슬라임인지 고블린인지 직접 판단하지 않는다. 연결된 EnemyData에 따라 초기 체력과 공격력이 결정된다.

새로운 적을 추가하려면 새로운 데이터 에셋을 만들고 해당 적 프리팹에 연결하면 된다. 공통 규칙이 바뀌지 않는 한 기존 코드를 수정할 필요가 없다.

단, 이 예제는 구조를 설명하기 위한 기본 형태다. 실제 프로젝트에서는 데이터 참조 누락, 잘못된 능력치, 체력 초기화, 런타임 데이터 변경 정책 등을 추가로 처리해야 한다.

데이터 기반 프로그래밍에 사용되는 기술

14장. 레벨업 시스템

ScriptableObject

Unity 에디터에서 게임 데이터를 생성하고 관리할 때 적합하다. 캐릭터 능력치, 아이템 정의, 스킬 설정 등에 활용할 수 있다.

GitHub - hrsetyono/pacific-atom: Simple theme for Atom that blend well with One Dark UI. · GitHub

JSON

설정 파일이나 외부 시스템과 데이터를 교환할 때 유용하다. 서버 응답, 이벤트 설정, 원격 밸런스 데이터 등에 활용할 수 있다.

Handling Spreadsheets in Godot: Save & Load Game Data | by Michael McGuire | Godot Dev Digest | Medium

CSV 및 스프레드시트

대량의 아이템, 스테이지, 퀘스트, 밸런스 데이터를 표 형태로 관리하기 좋다. 다만 실제 게임에서 사용하려면 파싱, 검증, 데이터 변환 과정이 필요할 수 있다.

Database schema design 101 for relational databases — PlanetScale

데이터베이스

사용자 진행 정보, 게임 경제 데이터, 서버 측 설정처럼 지속적인 저장과 조회가 필요한 데이터에 적합하다. 정적 콘텐츠 데이터와 플레이어의 변경 가능한 상태 데이터는 구분해서 설계하는 것이 좋다.

데이터 기반 프로그래밍의 장점

유지보수성 향상

능력치나 콘텐츠를 변경할 때 코드 수정 범위를 줄일 수 있다. 로직과 데이터가 분리되어 있으면 밸런스 변경이 전투 시스템 전체에 영향을 주는 상황도 줄일 수 있다.

확장성 향상

공통 로직을 재사용하면서 새로운 캐릭터, 아이템, 스테이지 등을 추가할 수 있다. 콘텐츠의 종류가 늘어나도 로직이 동일하다면 데이터 추가만으로 확장할 수 있다.

협업 효율 향상

기획자와 개발자가 서로 다른 작업 영역에서 일하기 쉬워진다. 기획자는 정해진 데이터 구조에 맞춰 수치를 조정하고, 개발자는 해당 데이터를 처리하는 로직을 구현할 수 있다.

밸런스 조정 비용 감소

게임의 체력, 공격력, 보상량 등을 데이터로 관리하면 반복적인 밸런스 조정 과정에서 코드를 수정하고 다시 빌드해야 하는 부담을 줄일 수 있다. 단, 데이터의 배포 방식과 변경 적용 시점은 프로젝트 구조에 따라 달라진다.

데이터 기반 프로그래밍의 단점과 주의사항

데이터 기반 프로그래밍이 항상 더 좋은 설계인 것은 아니다.

  • 데이터 검증 필요: 잘못된 값이나 누락된 참조가 런타임 오류를 발생시킬 수 있다.
  • 추적 난이도 증가: 동작이 코드뿐 아니라 여러 데이터 파일과 설정에 의해 결정되므로 문제의 원인을 추적하기 어려워질 수 있다.
  • 복잡성 증가: 데이터 로딩, 파싱, 버전 관리, 캐싱 등의 관리 비용이 발생한다.
  • 과도한 일반화 위험: 단순한 기능까지 지나치게 데이터화하면 오히려 설계와 디버깅이 복잡해질 수 있다.
  • 보안 고려: 클라이언트가 수정할 수 있는 데이터에 중요한 보상 규칙이나 권한 검증을 의존해서는 안 된다. 중요한 게임 규칙은 신뢰할 수 있는 서버에서 검증해야 한다.

특히 데이터와 로직을 분리했다고 해서 모든 동작을 데이터만으로 표현해야 하는 것은 아니다. 데이터로 표현하기 적합한 것은 변경 가능한 설정과 규칙의 매개변수이며, 복잡한 동작 자체는 코드로 유지하는 편이 더 합리적일 수 있다.

데이터 기반 프로그래밍과 데이터 지향 설계의 차이

두 개념은 이름이 비슷하지만 초점이 다르다.

구분데이터 기반 프로그래밍데이터 지향 설계(Data-Oriented Design)
핵심 목적데이터를 통해 동작과 콘텐츠를 설정데이터의 배치와 처리 방식을 최적화
주요 관심사유연성, 확장성, 유지보수메모리 접근, 캐시 효율, 성능
대표 사례ScriptableObject 기반 적 데이터연속된 배열을 활용한 대량 개체 처리
주된 효과콘텐츠 변경 및 추가 비용 감소특정 작업의 처리 효율 향상

데이터 기반 프로그래밍은 데이터가 프로그램의 동작을 결정하는 방식에 초점을 둔다. 반면 데이터 지향 설계는 데이터를 어떤 구조로 배치하고 처리해야 하드웨어를 효율적으로 활용할 수 있는지에 초점을 둔다.

두 접근법은 함께 사용할 수도 있지만 같은 개념은 아니다.

정리

데이터 기반 프로그래밍은 변경이 잦은 데이터와 안정적으로 유지해야 하는 로직을 분리해 개발 비용을 줄이는 설계 방식이다.

게임 개발에서는 캐릭터 능력치, 아이템, 스킬, 퀘스트, 스테이지와 같은 콘텐츠를 데이터로 관리하고, 공통 로직이 이를 처리하도록 설계할 때 특히 유용하다.

중요한 것은 모든 것을 데이터화하는 것이 아니라, 무엇이 자주 변경되는지 판단하고 변경 비용이 큰 영역부터 데이터와 로직을 분리하는 것이다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다