본문으로 건너뛰기
SheetForge

FAQ 및 문제 해결

증상을 기준으로 한 답변이다. 모든 임포트 에러는 콘솔 리포트에 자신만의 어디서/무엇이/왜/어떻게 문장을 담고 있다 — 거기서부터 시작하라.

설정 및 첫 실행

"Addressables 없이 에셋을 임포트했습니다 — 컴파일되나요? 왜 임포트가 잠겨 있나요?"

에셋은 Addressables 없이도 컴파일된다(Addressables를 사용하는 코드는 SHEETFORGE_ADDRESSABLES 버전 정의 뒤에 가드되어 있다). 주소 기반 로드와 AssetRef@Group 타입에는 com.unity.addressables가 정말로 필요하므로, 파이프라인 전체(임포트 · export · push · 작성 반영)는 설치할 때까지 잠긴다 — 각 진입점은 설치 안내를 표시하고 멈춘다(부분 실행 없음).

Package Manager를 통해 com.unity.addressables를 설치하라. 시작하기 창의 Addressables 행에는 Open Package Manager 버튼이 있으며 — Editor가 패키지 없이도 컴파일되므로 — 그 창은 세이프 모드에 막히지 않고 정상적으로 실행된다.

설치 이후에도 컴파일 에러가 남아 있다면, 이는 프로젝트의 다른 코드에서 비롯된 것이다 — SheetForge는 패키지가 있든 없든 컴파일된다.

"업데이트했더니 새 버전에서 프로젝트가 컴파일되지 않습니다."

.unitypackage 임포트는 파일을 추가하고 갱신할 뿐, 결코 삭제하지 않으므로, 이 제품이 이후 버전에서 폐지한 파일이 그대로 남아 더 이상 존재하지 않는 API를 참조할 수 있다.

에디터 로드 시 의존성 없는 SheetForge.Setup 부트스트랩이 알려진 폐지 경로를 감지하고 삭제를 제안하며, 무엇이든 건드리기 전에 모든 경로를 나열한다 — 대화상자를 승인하면 컴파일이 회복된다. 자신만의 어셈블리에 있으므로, 본체 어셈블리가 실패하는 동안에도 계속 동작한다. 프롬프트를 아예 건너뛰려면, 새 패키지를 임포트하기 전에 Assets/SheetForge 폴더를 삭제하라.

이것이 다루지 않는 것은 그사이 폐지된 계약을 대상으로 작성된 사용자 자신의 코드다 — 소스 저장소에 있는 CHANGELOG.mdUpgrade notes 표를 이용해 직접 포팅하라(릴리스 패키지에는 그 파일이 없다) — 시작하기가 그 내용을 요약한다.

"Create Sheet에는 내장 템플릿만 보입니다 — skills 데모 템플릿은 어디 있나요? / 제 템플릿은 어떻게 추가하나요?"

내장 Create Sheet 목록은 두 가지 템플릿 — *아이템 예시 (코어 타입만)*과, @enum 시트를 배치하는 Enum 정의 — 그리고 "처음부터"를 기본 제공한다.

플러그인이 필요한 도메인 템플릿(예: skills 데모)은 그 플러그인 자신이 등록하므로, 플러그인이 존재할 때만 나타난다. Plugin Demo 패키지를 임포트하면 그 Skill demo 템플릿이 나타난다. 자신만의 템플릿을 제공하려면 ISheetForgeTemplatePlugin을 구현하라 — 플러그인 작성 §4.6 참고.

"어디서 시작해야 하나요? / 에디터를 열 때마다 창이 계속 뜹니다."

그것이 시작하기 창이다. 에디터가 처음 로드될 때 자동으로 열리며 권장 진입점이다 — Addressables 상태, 활성 설정 에셋 선택, 예제 임포트, 첫 임포트 실행까지 모두 한곳에 모여 있다.

하단의 "에디터 시작 시 이 창 표시" 토글로 자동 열림을 끌 수 있으며, Tools ▸ SheetForge ▸ 시작하기에서 언제든 다시 열 수 있다.

"데모 패키지를 임포트했는데 아무 일도 일어나지 않습니다 — 설정 에셋도 addressable 그룹도 없습니다."

각 데모 패키지는 미리 구성된 설정 에셋을 함께 번들로 제공하며, 패키지를 임포트하면 이를 자동으로 활성화한다(단, 사용자에게 자신의 활성 설정이 없을 때만 그렇다 — 이미 있다면, 설정을 조용히 바꾸는 대신 시작하기 창이 열려 전환을 제안한다).

그런 다음 Tools ▸ SheetForge ▸ 데이터 스튜디오에서 ↓ 시트에서 가져오기를 한 번 누르면: addressable 그룹과 탭별 주소가 자동으로 생성된다. 흐름: 패키지 임포트 → (설정 자동 활성화) → 임포트 실행 → Play.

"데모 씬이 데모 대신 텍스트 메시지만 보여줍니다."

데모는 Addressables 주소로 로드되며, 그 주소는 사용자의 머신에서 임포트를 한 번 실행한 이후에만 존재한다(그룹 에셋은 커밋되지 않는, 자가 치유되는 캐시다). 데모 패키지를 임포트하고(설정이 자동으로 활성화된다) Run Import를 한 번 실행하라 — 시작하기 §5 참고.

(데모의 커밋된 타입은 기본 SheetForge.Generated 네임스페이스를 사용하므로, generatedNamespace 설정이 필요 없다 — 재임포트하면 그 자리에서 재생성된다.)

"플러그인 데모의 첫 임포트가 UnknownAssetGroup 'Scripts'로 실패합니다."

플러그인 데모에는 List<AssetRef@Scripts> 타입의 script 컬럼이 있으며, 이는 Scripts라는 이름의 Addressables 그룹을 필요로 한다. Addressables 그룹은 머신별이며(커밋되지 않는다), 방금 임포트한 데모에는 아직 이 그룹이 없다.

데모는 임포트 시 그 그룹을 자동으로 구성한다(PluginDemoAddressableSetup, 도메인 리로드 시와 데모 씬을 열 때 실행됨). 그래서 정상적인 임포트라면 그대로 동작한다. 그래도 에러가 보인다면, 데모 씬을 다시 열어(Tools ▸ SheetForge ▸ Open Plugin Demo Scene) 설정을 트리거한 다음 재임포트하라.

이는 플러그인 데모에만 해당한다 — 사용자 자신의 AssetRef@… 그룹은 직접 등록하는 것이다.

"설정 에셋이 여러 개 있으면 어떤 것이 사용되나요?"

활성 에셋이다. 메뉴, 데이터 스튜디오, 임포트 모두 활성 설정 에셋을 사용한다. 시작하기 창이나 데이터 스튜디오 툴바 드롭다운(여러 개가 있을 때만 표시됨)에서 선택한다.

설정 에셋이 하나뿐이면 첫 임포트가 자동으로 그것을 선택한다. 이 선택은 프로젝트별·사용자별로 저장되며(EditorPrefs 포인터 — VCS 변경 이력 없음), 활성 에셋이 삭제되면 자가 치유된다.

"이미 시트 파일이 담긴 폴더가 있습니다 — SheetForge가 이를 가리키게 하는 가장 빠른 방법은?"

데이터 스튜디오를 열고 그 폴더(또는 단일 .tsv/.csv/.xlsx 파일)를 그 위로 드래그한다.

그 폴더로부터 읽어오는 임포트 설정 에셋을 생성하고 활성화할지 제안한다 — 수동으로 필드를 입력할 필요가 없다. 이미 활성 설정이 있다면, 대화상자가 이를 알려주고 전환할지 제안한다.

"제 프로젝트가 올바르게 설정되었는지 어떻게 확인하나요 / 왜 임포트가 실행되지 않나요?"

데이터 스튜디오 툴바에서 ⋯ ▸ Health Check를 선택한다. 다음 항목에 대해 ✓/✗와 제안된 수정 방법을 보고한다:

  • 활성 설정;
  • 소스 접근 가능 여부 — 존재하는 로컬 폴더인지, 또는 Google id + 서비스 계정 키 경로인지 — 네트워크 호출 없음;
  • 임포트 baseline;
  • 생성된 코드/베이크/addressable의 최신 상태.

결과는 콘솔과 요약 대화상자에 함께 표시된다.

"메뉴와 UI가 제가 선택하지 않은 언어로 열렸습니다."

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

(언어를 변경하면 메뉴 라벨이 재생성되므로 짧은 재컴파일이 한 번 트리거된다.)

"저장소를 클론했는데 베이크된 SO에 대한 씬 참조가 Missing입니다."

예상된 동작이다: 베이크된 SO는 머신별 GUID를 갖는 머신별 캐시다. 씬에서 결코 직접 참조하지 마라 — 주소로 로드하라(SheetForgeDatabases.LoadAsync("Tab")). 임포트를 한 번 실행하여 로컬 캐시를 재구축하라.

"SheetForge 메시지와 함께 빌드가 중단되었습니다."

이는 빈 캐시 또는 오래된 캐시를 배포하지 않도록 보호하는 빌드 전 최신성 훅이다. 문장이 알려주는 대로 하라 — Tools ▸ SheetForge ▸ 데이터 스튜디오에서 ↓ 시트에서 가져오기를 누르고 — 다시 빌드하라.

임포트 및 검증

"임포트가 실행되어 에러를 발견했는데, 아무것도 생성되지 않았습니다."

설계상 그렇다: 에러 하나 ⇒ 출력 없음(부분 조립 없음). 리포트는 좌표와 제안된 수정 사항과 함께 모든 문제를 나열한다 — 한 번에 고치고 재임포트하라. 이로 인해 작업을 잃는 일은 결코 없다. 시트는 손대지 않은 채로 남는다.

"에러가 발생한 셀로 바로 이동할 수 있나요?"

가능하다. 사람이 읽기 쉬운 콘솔 리포트의 각 에러에는 클릭 가능한 "Open in Data Studio" 링크가 있다. 클릭하면 데이터 스튜디오가 열리고, 해당 탭으로 전환되며, 셀이 강조 표시된다(파일/탭 수준 에러는 탭만 강조). 머신이 읽는 좌표 줄은 변하지 않으므로 CI/로그 스크래핑에는 영향이 없다.

"임포트가 코드를 기록하고 재컴파일했는데… 끝난 건가요?"

그렇다 — 스키마가 새롭거나 변경된 경우, 임포트는 내부적으로 두 단계다(코드젠 → 컴파일/리로드 → 베이크). 그리고 베이크는 리로드 이후 자동으로 재개된다. 최종 리포트를 보려면 콘솔을 지켜보라.

게임 코드가 더 이상 컴파일되지 않는다면(예: 컬럼 이름 변경 이후), 체인은 조치 가능한 문장과 함께 안전 중단된다. 코드를 고치고 다시 임포트하라.

"빈 셀 에러가 났는데, 저는 그 셀을 선택 사항으로 만들고 싶었습니다."

마커가 없는 타입은 필수다(조용한 오염 가드). 셀을 선택 사항으로 만들려면:

  • float?로 선언한다 — 타입 기본값;
  • int=1로 선언한다 — 명시적 기본값;
  • 또는 List<T>를 사용한다 — 빈 셀은 빈 리스트가 된다.

시트 문법 참고.

"1.5는 임포트가 잘 되는데, 1,5는 에러가 납니다."

의도된 것이다: 숫자는 로케일 독립적이다 — 항상 . 소수점을 사용한다. 콤마 소수, NaN, Infinity는 입구에서 차단된다.

"임포트가 갑자기 아주 느려졌습니다."

임포트 시간은 데이터 크기에 대해 선형적이다(에디터에서 50k행 × 20컬럼 ≈ 628 ms). 참조가 한 번에 대량으로 깨지는 경우에도 선형을 유지한다 — 최근접 일치 탐색은 필드당 예산이 정해져 있고 길이로 사전 필터링된다(깨진 참조 4,000건 기준, 헤드리스에서 ≈ 45 ms).

임포트가 갑자기 이보다 훨씬 오래 걸린다면, 살펴봐야 할 것은 에러 개수가 아니라 시트 크기다.

"'혹시 이거 아닌가요' 힌트와 함께 알 수 없는 마커 / 알 수 없는 타입 에러가 발생합니다."

@marker 이름, 타입 이름, enum 멤버의 오타는 최근접 일치 제안과 함께 에러가 된다 — 그 제안을 적용하라. 등록되지 않은 타입 이름에 붙은 알 수 없는 @도 에러다(RecordId@Tab 형식 참조에 대한 오타 안전성).

Google 시트

"Google 임포트가 PERMISSION_DENIED(403)로 실패합니다."

스프레드시트가 서비스 계정의 client_email 주소와 공유되지 않은 것이다 — 키만으로는 아무 권한도 주어지지 않는다. JSON 키를 열어 client_email을 복사하고, 그 주소와 시트를 공유하라(임포트는 Viewer, Push는 Editor). 전체 안내는 Google 시트 설정에 있다.

"Push가 SheetsApi가 필요하다고 합니다."

읽기 전용(인증 없음)인 ExportUrl 모드에 있는 것이다. 어떤 형태의 쓰기 반영이든 서비스 계정 키를 가진 SheetsApi 모드가 필요하다. 소스, 내보내기 및 Push 참고. 서비스 계정과 키를 생성하는 방법은 Google 시트 설정에서 다룬다.

"ExportUrl 임포트가 gid 맵을 요구하며 실패합니다."

필요한 것이다: gid가 없는 export URL은 조용히 첫 번째 탭만 반환하므로, 맵(탭 이름 → #gid=)이 강제된다. 또는 맵이 필요 없는 SheetsApi 모드로 전환하라.

"Push가 건너뛴 셀이 있다고 보고했습니다."

전송 전 라이브 재조회가 충돌을 발견한 것이다(팀원이 셀을 편집했거나, 행이 이동/사라졌거나, 키가 중복되었거나). 건너뛰어진 셀은 실패가 아니라 보호다 — 리포트는 적용/건너뜀 개수를 보여준다. 재임포트로 조정한 다음 다시 Push하라.

"로컬에서 행을 삭제했는데 Push 이후에도 Google 시트에 여전히 남아 있습니다."

행 삭제는 결코 Push되지 않는다(라이브 시트를 대상으로 한 위치 기반 삭제는 안전하지 않다) — 대신 알림을 받게 된다. 시트에서 행을 삭제한 다음 재임포트하라.

작성

"Ctrl+Z가 스테이징된 변경을 되돌리지 않습니다."

두 가지 경계가 있다:

  • 포커스된 텍스트 필드가 Ctrl+Z를 먼저 소비한다 — 다른 곳을 클릭한 다음 undo하라;
  • "시트로 반영"이 성공한 이후에는 스테이징 기록이 지워지므로, undo는 반영 이전 세션 내에서만 동작한다.

반영 이후에는 시트를 편집하라(시트가 정본이다).

"스테이징된 편집 중 일부에 'isolated' 배지가 표시되며 반영되지 않았습니다."

스테이징과 반영 사이에 시트가 외부에서 변경되어 그 편집들의 논리적 주소가 깨진 것이다(행의 키가 외부에서 이름 변경됨 / 행이 삭제됨 / 키 충돌). 이들은 제외된다 — 조용히 사라지지도, 나머지를 막지도 않는다. 개별적으로 버리고 새로운 baseline에 대해 다시 스테이징하라.

"컬럼/탭 이름을 변경했더니 이제 제 게임 코드가 컴파일되지 않습니다."

예상된 동작이며 확인 대화상자에서 이미 알려준 내용이다: 이름 변경은 생성된 필드/클래스 이름을 변경한다. 게임 코드를 업데이트하라. 그러면 임포트 체인이 다음 실행에서 완료된다. 컬럼의 데이터 값은 완전히 보존되었다.

"탭 이름 두 개를 교환(A↔B)하거나, 순환으로 탭 이름을 변경하는 것을 한 배치로 할 수 있나요?"

가능하다 — 상호 교환과 순환(A→B→C→A)은 한 배치로 스테이징되고 반영된다(UI는 오직 진짜 충돌 — 두 개의 이름 변경이 같은 이름을 대상으로 하는 경우 — 만 거부한다). 참조는 데이터를 따라가며 원자적으로 재작성된다.

Google에는 한 가지 예외 사례가 남아 있다: 서로를 참조하는 두 교환된 탭은 다시 연결되지 않는다(로컬은 완전히 올바르게 처리한다) — 상호 참조를 제삼의 탭을 경유하도록 하거나, 중간 이름을 거쳐 반영하라. 데이터 스튜디오기능 및 제한 참고.

"제 키 이름 변경이 같은 배치에서 입력한 참조를 업데이트하지 않았습니다."

전파는 baseline 셀만을 재작성한다 — 방금 입력한 텍스트는 결코 재작성하지 않는다(새 입력을 조용히 재작성하는 일은 없다). 사전 검증이 매달린 참조를 표시한다 — 직접 고쳐야 한다.

"xlsx 탭 때문에 반영이 거부되었습니다."

알려진 두 가지 경우가 있다:

  • xlsx 원본 탭은 탭 이름을 변경할 수 없다(워크북 보호);
  • xlsx 탭에 영향을 미치는 키 이름 변경 전파는 전체 배치를 차단한다(부분 반영 없음).

워크북을 직접 편집한 다음 재임포트하라.

"인스펙터에서 베이크된 SO를 편집했는데 재임포트가 이를 지워버렸습니다."

설계상 그렇다 — 시트가 단일 진실 공급원이며 SO는 캐시다. 인스펙터의 "테스트 편집" 토글은 명시적으로 임시적이다. 실제 변경은 시트나 데이터 스튜디오를 통해 하라.

Export 및 기타

"Export가 스키마 불일치로 실패합니다."

스키마 변경에 비해 베이크가 오래된 것이다(ExportSchemaMismatch — 핑거프린트 확인). 임포트를 실행하여 코드젠 + 베이크를 완료한 다음, Export/Push하라.

"제가 export한 float가 시트에서는 1.0이었는데 1로 나옵니다."

의미적 라운드트립이다: 값은 정확히 보존되며, 표기는 가장 짧은 라운드트립 형태로 정규화된다. 구조(마커, 컬럼 순서, 주석, 사용자의 텍스트)는 100% 보존된다.

"xlsx 임포트가 일부 셀을 거부했습니다."

내장 OOXML 리더는 의도적으로 최소한으로 만들어졌다. 세 가지가 지원되지 않는다:

  • 캐시된 값이 없는 수식 셀;
  • 에러 셀;
  • 셀 안의 탭/개행.

수식을 값으로 구체화하고, 리스트에는 ;를 사용하라.

"지금 당장 에디터 언어를 바꿀 수 없습니다."

임포트/Export/Push가 실행되는 동안에는 언어 변경이 잠긴다(변경은 메뉴 파일 재생성 + 짧은 재컴파일을 트리거한다). 파이프라인이 끝날 때까지 기다려라.

"제 언어가 한국어/일본어/…인데도 에러 리포트의 일부가 영어로 나옵니다."

리포트 뼈대와 왜/어떻게 문장은 현지화되어 있다. 런타임에 보간되는 세부 사항(문제가 된 값, 제안)과 저수준 로그는 인라인 영어다 — 표준 현지화 경계다.

"클론 이후 Tools ▸ SheetForge ▸ … 메뉴 항목이 어디로 갔나요?"

현지화된 메뉴 파일은 생성되는 것이며(gitignore됨) — 에디터 로드 시 자가 치유된다. 라벨이 잘못된 언어로 되어 있다면, 다음 언어 변경 또는 에디터 시작 시 재생성된다.

관련 페이지