본문으로 건너뛰기
SheetForge

시작하기

요구 사항

  • Unity 6 (6000.0.79f1, URP 템플릿에서 개발 및 테스트됨).
  • Addressables 패키지(com.unity.addressables) — 필수다. 주소 기반 로드가 런타임 경로이며 AssetRef@Group 타입에 Addressables가 필요하다.
    • 패키지가 없어도 에셋은 여전히 컴파일된다. Addressables를 사용하는 모든 코드는 SHEETFORGE_ADDRESSABLES 버전 정의 뒤에 있기 때문이다.
    • 하지만 파이프라인 — 임포트 · export · push · 작성 반영 — 은 잠긴 채로 남는다. 각 진입점은 설치 안내를 표시하며, 시작하기 창이 설치를 안내한다.

Addressables 설치하기

  • 기본 경로: Asset Store에서 에셋을 임포트하면, 컴파일 이전에 "Package Manager dependencies" 프롬프트가 나타난다 — Install을 선택하면 Addressables가 함께 설치된다.
  • 안전장치: Skip을 눌렀거나(또는 수동으로 임포트한) 경우, 파이프라인은 잠긴 상태로 유지되며 시작하기 창이 자신의 Addressables 상태 행에서 설치를 안내한다. 그 창은 Addressables 없이도 실행된다 — Editor가 여전히 컴파일되기 때문이다.
    • 의존성 없는 SheetForge.Setup 부트스트랩 창도 에디터 로드 시 누락된 패키지를 감지해 세션당 한 번 안내를 표시한다. 의존성이 없기 때문에, 다른 컴파일 에러가 본체 어셈블리를 막더라도 계속 동작한다.
  • 원클릭 프로그래밍 방식 설치는 없다: Asset Store 제출 규정이 프로그래밍 방식의 패키지 설치를 제한하므로, 안내 창이 대신 사용자를 안내한다.
  • 이 안내는 실제 설치 상태를 반영하며, 제품은 컴파일되지만 패키지가 설치되기 전까지는 기능이 잠긴 상태로 유지된다는 것을 설명하고, 이후 시작하기 창으로 안내한다. Tools ▸ SheetForge ▸ Addressables Setup에서 언제든 다시 열 수 있다(이 메뉴는 다른 이유로 본체 어셈블리의 컴파일이 실패하더라도 살아남는다).

이전 버전에서 업그레이드하기

.unitypackage 임포트는 파일을 추가하고 갱신할 뿐, 결코 삭제하지 않는다. 그래서 최신 버전에서 폐지된 파일이 Assets/SheetForge에 그대로 남아, 더 이상 존재하지 않는 API를 계속 참조할 수 있다 — 컴파일이 깨지고, 마치 업그레이드가 프로젝트를 망가뜨린 것처럼 보인다. 이를 막는 두 가지 안전장치가 있다:

  • 자동 감지. 에디터 로드 시, 의존성 없는 SheetForge.Setup 부트스트랩이 이 제품에서 폐지된 경로들을 확인하고, 발견되면 삭제를 제안한다 — 대화상자에 모든 경로를 먼저 나열하며, 승인하기 전까지는 아무것도 건드리지 않는다. 이것이 자신만의 어셈블리에 있는 이유는 정확히, 자신이 고치려는 그 컴파일 에러 속에서도 살아남기 위해서다.
  • 클린 슬레이트. 확실히 깨끗한 업그레이드를 원한다면, 기존 Assets/SheetForge 폴더를 삭제하고, 새 패키지를 임포트한 다음, 임포트 실행을 한 번 실행해 삭제와 함께 사라진 것을 다시 만든다. 설정 에셋과 베이크된 SO(Assets/SheetForgeBaked)는 이 폴더 밖에 있어 그대로 남고, 생성된 코드도 기본 위치인 Assets/SheetForgeGenerated에 자리 잡은 이후로는 마찬가지다. 프로젝트가 여전히 예전의 제품 내부 위치(Assets/SheetForge/Runtime/Generated)에 생성하고 있었다면, 폴더를 삭제하면 그 코드도 함께 사라지고 재임포트가 대신 Assets/SheetForgeGenerated에 그것을 기록한다. 이것이 기존 프로젝트를 새 위치로 옮기는 지원되는 방법이다. 어떤 재임포트로도 되살릴 수 없는 것은 사용자가 Assets/SheetForge 안에 직접 넣은 것(그곳에 저장한 설정 에셋, 자신의 플러그인 스크립트, 시트 파일)뿐이므로, 그것들만 먼저 밖으로 옮겨 둔다.

분명히 짚어둘 경계가 하나 있다: 자동 정리는 SheetForge 자신의 폐지된 파일만 삭제할 뿐, 사용자의 파일은 결코 건드리지 않는다. 자신의 플러그인 코드가 그사이 폐지된 계약을 구현하고 있다면, 이는 직접 손으로 포팅해야 한다. 요약하면:

  • 탭별 그래프 빌더(IGraphShapeBuilder / GraphSpecBuilder)는 레코드 캔버스의 augmenter(IRecordCanvasAugmenter / CanvasAugmentBuilder)가 되며, 이는 전체 그림을 새로 짓는 대신 캔버스가 이미 구축한 closure에 추가한다.
  • GraphMode는 사라졌다. 방향은 이제 캔버스 자신의 통제 사항이기 때문이다.
  • StudioGraphContext.ShapeId / ModeId는 여전히 컴파일되지만 각각 상수를 반환하므로, 이를 대상으로 한 AppliesTo 비교는 그냥 삭제하면 된다.
  • IAuthorableGraphShape.CreatableTabs는 변경되지 않았다.

폐지된 각 계약이 무엇이 되었는지에 대한 전체 표는 소스 저장소에 있는 CHANGELOG.mdUpgrade notes 절에 있다(릴리스 패키지에는 포함되지 않는다). 여전히 컴파일되는 폐지된 멤버는 제거되는 대신 [Obsolete]로 표시되므로, 업그레이드 시 빌드가 깨지는 대신 경고로 드러난다.

시작하기 창 (여기서 시작하세요)

Addressables가 설치되면, 시작하기 창에디터 세션당 한 번 자동으로 열린다 — 에디터를 시작할 때마다 열리지만, 도메인 리로드 후에는 다시 열리지 않는다. 이는 하단의 "에디터 시작 시 이 창 표시" 토글이 켜져 있는 동안에만 그렇고, 기본값은 켜짐이다.

이는 권장 진입점이다. Tools ▸ SheetForge ▸ 시작하기에서 언제든 다시 열 수 있으며, 하단의 그 토글로 자동 표시를 끌 수 있다(이 선택은 프로젝트별·사용자별로 저장된다).

이 창은 첫 실행 흐름 전체를 한곳에 모아 놓는다:

  1. 상태 대시보드 — 세 개 행으로 이루어진 신호등: Addressables 설치 여부, 활성 임포트 설정 에셋, 첫 임포트 완료 여부. 각 행은 ✓ 또는 ✗를 보여주며, 아직 조치가 필요한 항목에는 바로 옆에 조작 버튼이 있다(New settings asset, 또는 Run Import).
  2. Import settings — 모든 SheetForgeSettings 에셋을 나열하며, 라디오 버튼으로 활성 에셋을 선택할 수 있다. 여기에 New settings asset 버튼과 각 에셋의 위치를 찾는 Reveal 버튼이 함께 있다.
  3. Examples — 클릭 한 번으로 플러그인 데모 또는 코어 데모 패키지를 임포트한다.
  4. Start from a template — 두 가지 내장 템플릿 중 하나를 고르거나, 직접 필드를 정의하려면 "from scratch"를 선택하거나, 플러그인이 등록한 템플릿을 사용한다. "Use"를 누르면 데이터 스튜디오의 생성 패널이 그 내용으로 미리 채워져 열린다. 이는 쓰기 가능한 소스를 가진 활성 설정 에셋을 필요로 한다. 아직 없다면 그 요구 사항이 표시된다.
    • 내장 템플릿은 코어 타입만 사용하는 *아이템 예시 (코어 타입만)*와 @enum 시트를 배치하는 Enum 정의다.
    • skill 데모 탭은 Plugin Demo처럼 템플릿을 등록하는 플러그인이 있을 때만 표시된다.
  5. RunRun Import(활성 설정을 사용)와 데이터 스튜디오 열기.
  6. Open Full Guide — 이 문서 사이트로의 링크.

아래 절들은 각 단계를 자세히 설명한다. 창에서 모든 것을 할 수도 있고, 설명된 대로 메뉴와 Project 창을 통해 할 수도 있다.

더 빠른 방법 — 드래그 앤 드롭. 이미 시트 파일이 담긴 폴더가 있다면, 데이터 스튜디오를 연 다음 그 폴더 — 또는 단일 .tsv/.csv/.xlsx 파일 — 를 그 위로 끌어다 놓는다. 그 폴더로부터 읽어오는 임포트 설정 에셋을 생성하고 이를 활성화할지 제안한다 — 수동 설정이 필요 없다.

활성 설정 없이 열리면, 스튜디오는 빈 테이블 대신 동일한 생성 / 데모 임포트 / 시작하기 버튼이 있는 "Get started" 패널을 보여준다.

Health check. 언제든 데이터 스튜디오를 열고 툴바에서 ⋯ ▸ 상태 점검을 선택하면, 네트워크 호출 없이 빠른 진단을 받을 수 있다. 각각 ✓ 또는 ✗로, 제안된 수정 방법과 함께 다음을 보고한다:

  • 활성 설정
  • 소스에 접근 가능한지(존재하는 로컬 폴더인지, 또는 Google id + 키 경로인지)
  • 임포트 baseline이 존재하는지
  • 생성된 코드·베이크된 SO·addressables가 최신 상태인지

UI 언어. 프로젝트를 처음 열면, SheetForge는 에디터의 시스템 언어로부터 UI 언어를 설정한다(아홉 개 언어가 직접 매핑되며, 그 외에는 영어로 남는다). 이미 선택한 언어를 결코 덮어쓰지 않는다. Preferences ▸ SheetForge에서 언제든 변경할 수 있다(현지화 참고).

1. 임포트 설정 에셋 선택하기

시작하기 창의 New settings asset 버튼에서 하나를 생성하거나, Project 창에서 우클릭 → Create ▸ SheetForge ▸ Import Settings를 선택한다(메뉴 라벨은 언어 설정을 따른다 — 현지화 참고).

여러 개의 설정 에셋(예: 데이터 소스별로 하나씩)을 유지하면서 어느 것을 활성으로 할지 선택할 수 있다. 메뉴, 데이터 스튜디오, 임포트 모두 활성 에셋을 사용한다. 이 선택은 프로젝트별·사용자별로 저장되며(EditorPrefs 포인터 — VCS 변경 이력 없음, 팀원마다 독립적), 활성 에셋이 삭제되면 포인터가 자가 치유된다.

설정 에셋이 하나뿐이라면 첫 임포트가 자동으로 그것을 선택한다 — 명시적인 선택이 필요 없다. 여러 개가 존재하면, 시작하기 창이나 데이터 스튜디오 툴바에 나타나는 드롭다운에서 활성 에셋을 선택한다.

SheetForgeSettings 에셋을 구성한다:

필드의미
Source (드롭다운)내장 LocalFile(.tsv/.csv/.xlsx 파일 폴더) 또는 GoogleSheet — 둘 다 완전한 프로덕션 경로다. 등록되어 있다면 커스텀 플러그인 소스(DB/REST 등)도 여기 나타난다. sourceProviderId에 저장되며, 비어 있으면 내장 LocalFile 프로바이더가 기본값이다.
localFolderPathLocalFile 모드: 시트 파일이 있는 폴더. 폴더의 바로 아래 자식만 스캔된다.
spreadsheetIdGoogleSheet 모드: 대상 스프레드시트 ID(SheetsApi 모드에는 서비스 계정 인증이 필요).
bakeOutputFolder베이크된 Database SO가 저장될 위치. 기본값 Assets/SheetForgeBaked.
generatedCodeFolder생성된 .cs 파일이 저장될 위치. 기본값은 Assets/SheetForgeGenerated이며, 의도적으로 Assets/SheetForge 바깥에 있어 제품을 재설치하거나 옮겨도 생성된 코드가 삭제되지 않는다. 이미 예전의 제품 내부 위치(Assets/SheetForge/Runtime/Generated)에 생성하고 있던 프로젝트는 그 위치가 비워질 때까지 그 자리를 유지한다. 이동 방법은 이전 버전에서 업그레이드하기에서 다룬다. 어떤 폴더든 동작한다 — 생성된 코드가 해당 폴더의 어셈블리에서 볼 수 없는 플러그인 타입을 참조한다면, 임포트는 참조를 연결하기 위해 그 위치에 동반 .asmdef를 자동으로 만들어낸다(코어 런타임 어셈블리는 깨끗하게 유지된다). 이는 오직 신규 탭의 거처일 뿐이라는 점에 유의: 생성된 타입이 이미 다른 곳(예: 플러그인 패키지에 커밋된 Generated)에 존재하는 탭은 기존 위치에서 그 자리에서 재생성되며, 오래된 중복 파일은 콘솔 로그와 함께 자동으로 정리된다.
generatedNamespace생성된 타입의 네임스페이스. 비어 있으면 SheetForge.Generated. 생성된 타입을 다른 패키지 및 번들 예제와 격리하려면 고유한 값(예: MyGame.Data)을 지정한다.
exportFolderPath / exportFormatExport 대상 및 형식(Tsv / Csv / Xlsx / MatchSource).

설정 인스펙터는 현재 소스 모드와 관련된 필드만 보여준다 — Local 모드에서는 Google 입력란이 숨겨지며, gidMap은 Google ExportUrl 모드에서만 나타난다.

2. 서비스 계정 키 보안 (Google 소스)

LocalFile 소스를 사용하는가? 이 절은 건너뛰어도 된다.

SheetsApi 모드로 Google 시트를 사용하려면 서비스 계정 JSON 키가 필요하다. 아직 하나도 생성한 적이 없다면, Google 시트 설정이 전체 과정을 단계별로 안내한다. 이 키는 Assets/ 밖, 그리고 저장소 밖에 두어야 하며 — 절대 커밋하지 않는다.

  • 권장: 환경 변수 **SHEETFORGE_SHEETS_KEY**를 키 파일의 절대 경로로 설정한다. 이는 설정 에셋의 키 경로 필드보다 우선하므로, 각 개발자가 저장소에 어떤 경로도 남기지 않고 자신의 로컬 키를 주입할 수 있다.
  • 설정 필드에 경로를 넣어야 한다면, 저장소 바깥을 가리키게 한다(예: C:/keys/service-account.json). Assets/ 아래의 키 파일은 빌드와 커밋에 유출될 것이다.

3. 첫 임포트 실행하기

Tools ▸ SheetForge ▸ 데이터 스튜디오를 연 다음, 툴바에서 ↓ 시트에서 가져오기를 누른다.

  • 파이프라인은 fetch → 검증 → (성공 시) 코드 생성 → 베이크 순으로 진행된다. 진단 정보는 사용자 언어로, 사람이 읽기 쉬운 리포트로 콘솔에 출력된다.
  • 첫 임포트는 내부적으로 두 단계로 나뉘어 자동으로 완료된다: 스키마가 새롭거나 변경된 경우, 임포트는 생성된 코드를 기록하고, 이는 컴파일/도메인 리로드를 트리거한다 — 그리고 리로드 이후 베이크를 자동으로 재개한다. 사용자의 조작은 한 번뿐이며, 수동 재트리거는 필요 없다. 컴파일이 실패하면, 자동 재개는 안전 중단되며(시도 횟수 제한 3회) 콘솔에 조치 가능한 문장을 남긴다.
  • 검증은 임포트 시점에 모든 진단 정보를 수집한다(첫 번째 에러에서 멈추지 않는다). 단 하나의 에러라도 있으면 출력은 생성되지 않는다(부분 조립 없음).
  • 임포트는 각 탭의 Database SO를 Addressables 그룹 SheetForge에 주소 "SheetForge/{tab}"으로 자동 등록한다 — 게임은 이 안정적인 주소로 로드한다(핵심 개념 참고).

4. 게임에서 데이터 로드하기

using SheetForge.Runtime;
using UnityEngine.ResourceManagement.AsyncOperations;
 
AsyncOperationHandle<DefinitionDatabase> handle = SheetForgeDatabases.LoadAsync("Items");
await handle.Task;   // or coroutine yield / handle.WaitForCompletion()
if (handle.Status == AsyncOperationStatus.Succeeded)
{
    DefinitionDatabase db = handle.Result;
    // For strong typing: SheetForgeDatabases.LoadAsync<ItemsDatabase>("Items")
}
SheetForgeDatabases.Release(handle);   // Addressables is ref-counted — release what you load

SheetForge.Runtime 어셈블리는 autoReferenced이므로, 게임 코드는 asmdef 참조 없이 이를 사용할 수 있다.

씬에서 베이크된 SO를 직접 참조하지 마라. 베이크된 SO는 커밋되지 않는, 머신별 캐시다 — 머신과 재베이크마다 GUID가 다르므로, 씬에서 직접 참조하면 팀원의 머신에서 Missing이 된다. 주소 기반 로드는 설계상 이 문제를 흡수한다.

5. 데모 씬 사용해보기

두 개의 샘플이 선택적 임포트 패키지로 제공된다. 플러그인 샘플 SheetForge.PluginDemo(커스텀 타입, enum, 검증기, 엣지)와 플러그인이 없는 SheetForge.CoreDemo(코어 내장 타입만 사용)는 각각 "열고 바로 Play"할 수 있는 데모 씬을 포함한다.

데모 임포트는 한 곳에만 있다 — 시작하기 창의 Examples 섹션 — 그래서 이를 위한 메뉴 leaf는 없다.

  • 플러그인 데모: 시작하기 창에서 플러그인 데모 임포트를 누르거나, Assets/SheetForge/Examples/SheetForgePluginDemo.unitypackage를 더블클릭한다 — 둘 다 Assets/SheetForge.PluginDemo/… 아래에 복원한다. 씬: Demo/PluginDemo.unity(메뉴 Tools ▸ SheetForge ▸ Open Plugin Demo Scene, 샘플 자신이 추가함). 이는 예제 데이터베이스를 주소로 로드하며 시트 데이터로 조립된 스킬을 보여준다(fireball 총 피해량 = Damage 10 + DamageOverTime 3×3 = 19).
  • 코어 전용 데모: 시작하기 창에서 코어 데모 임포트를 누르거나, Assets/SheetForge/Examples/SheetForgeCoreDemo.unitypackage를 더블클릭한다 — Assets/SheetForge.CoreDemo/… 아래에 복원한다. 씬: Demo/CoreDemo.unity(메뉴 Tools ▸ SheetForge ▸ Open Core Demo Scene). 이는 코어 내장 타입만을 사용해 아이템 참조로부터 조립된 장비 구성을 보여준다. 이 데모에는 현지화 시트(ExampleStrings)도 들어 있어, 아이템이 LocRef 셀로 그 키를 참조한다 — 현지화 시트 참고.

(이 샘플 메뉴들의 리프 라벨은 핵심 현지화 메뉴 파이프라인 바깥에 있으므로 영어로 표시된다.)

각 데모 패키지는 미리 구성된 설정 에셋을 함께 번들로 제공한다. 데모 패키지를 임포트하면, SheetForge는 사용자에게 자신의 활성 설정이 없는 경우에 한해 그 번들 설정 에셋을 자동으로 활성화한다(이미 있다면, 사용자의 선택을 조용히 덮어쓰는 대신 시작하기 창을 열어 전환을 제안한다). 그래서 데모 흐름은 단순히: 패키지 임포트 → (설정 자동 활성화) → 임포트 실행 → Play — 수동 설정 생성이 필요 없다.

데모는 사용자의 머신에서 임포트를 한 번 실행한 이후에만 동작한다 — 데모가 로드하는 Addressables 주소는 임포트가 한 번 실행된 이후에만 존재한다(Addressables 그룹 에셋은 커밋되지 않는, 자가 치유되는 캐시다). 그 전에는 데모 씬이 실패하는 대신 안내 메시지를 보여준다.

데모를 완성하려면(위의 샘플 패키지 임포트 이후):

  1. 데모의 번들 설정 에셋이 활성 상태인지 확인한다(시작하기 창이 이를 보여주거나, 임포트가 이를 자동 활성화했을 것이다). 이는 source = LocalFile, local folder = 샘플의 DemoSheets 폴더, 그리고 기본 SheetForge.Generated 네임스페이스를 사용하므로 재임포트는 커밋된 타입을 그 자리에서 재생성한다.
  2. 플러그인 데모의 스크립트 참조는 별도 조치가 필요 없다. ExampleEffects 탭에는 AssetRef@Scripts 예제가 포함되어 있으며, 샘플이 스스로 DemoScripts/special_effect.lua.txtScripts Addressables 그룹의 주소 special_effect로 idempotent하게 등록하므로, 첫 임포트가 참조 검증을 통과한다. 등록에 실패했다는 경고(예: 에셋 누락)가 로그에 남을 때만 그 항목을 직접 추가하면 된다 — 또는 Addressables 예제를 원하지 않는다면 해당 행을 제거하라.
  3. Tools ▸ SheetForge ▸ 데이터 스튜디오에서 ↓ 시트에서 가져오기를 한 번 누른(또는 시작하기 창의 Run Import 버튼을 누른) 다음, 데모 씬을 열고 Play를 누른다.

6. 팀 워크플로우 요약

  • 베이크된 SO(Assets/SheetForgeBaked)는 머신별 캐시다. gitignore로 제외하고, 클론 이후 각 팀원은 임포트 실행을 한 번 실행한다.
  • 생성된 코드(Assets/SheetForgeGenerated)는 프로젝트 자신의 소스이며, 커밋하는 쪽이 권장된다. 그러면 새로 클론했을 때 누군가 임포트를 실행하기도 전에 바로 컴파일되고, 스키마 변경이 리뷰에 그대로 드러난다. 이는 결정적(deterministic) 산출물이라 팀원의 임포트도 동일한 바이트를 만들어내므로 잡음이 생기지 않는다. 대신 gitignore로 제외해도 여전히 동작한다 — 그 경우 클론 이후의 임포트 실행이 컴파일을 되살리는 역할을 한다.
  • 빌드 전 최신성 훅은 — 커밋된 생성 Database 타입마다 — (i) 베이크된 SO가 존재하는지, (ii) 스키마 핑거프린트가 baseline과 일치하는지, (iii) Addressables 등록이 존재하는지 확인한다. 무엇이라도 실패하면 빌드는 조치 가능한 문장과 함께 중단되므로, 클론/CI 머신이 빈 캐시를 조용히 배포하는 일은 결코 없다.

관련 페이지