AEGLOSLAB 엔비디아 기술 스택

제10부 시뮬레이션·디지털트윈·피지컬 AI

10.4 OpenUSD II — 컴포지션 아크

10.4.1 이 장에서 배우는 것 / 선수 지식

10.3에서 USD 데이터 모델(Stage·Prim·Layer)과 비파괴 합성의 기초 — 서브레이어로 의견을 겹쳐 덮어쓰기 — 를 봤다. 그리고 "누가 이기는가(강도 규칙)·자산을 어떻게 재사용하는가(참조)"는 이 장으로 미뤘다. 이 장이 USD의 합성 메커니즘 전체 — 씬을 조립하는 여섯 가지 컴포지션 아크(composition arc) 와 그들의 강도 순서(LIVRPS) — 를 실습으로 판다. 자산을 재사용하는 참조(reference)·페이로드(payload), 옵션을 담는 변형(variant), 상속·특수화·서브레이어, 그리고 여러 의견이 충돌할 때 무엇이 이기는지를 정확히. 로봇을 N번 배치하고(9.13), 도메인 랜덤화로 변형을 오버레이하고(9.14), 디지털트윈에 운영 데이터를 겹치는(10.8) 실제 메커니즘이 여기 있다.

핵심 통찰: USD의 합성은 "레고 + 우선순위 규칙"이다 — 재사용 가능한 조각(참조)을 조립하고, 충돌하면 정해진 강도 순서(LIVRPS)로 승자를 정한다. 큰 씬을 한 파일에 모두 두지 않는다 — 로봇 자산은 한 번 만들고 참조로 N번 가져오며(인스턴싱), 대용량 환경은 페이로드로 지연 로드하고, 옵션은 변형으로 담는다. 그리고 한 속성에 여러 아크가 의견을 내면, LIVRPS(Local·Inherits·Variants·References·Payloads·Specializes) 라는 고정된 강도 순서로 누가 이길지 결정된다. "내 오버라이드가 왜 안 먹지?"의 답은 거의 항상 이 강도 순서에 있다 — 합성을 이해하면 USD가 비로소 도구가 된다.

배우는 것:

  • 여섯 컴포지션 아크 — sublayers·references·payloads·variants·inherits·specializes가 각각 무엇을·왜.
  • References·Payloads — 자산 재사용(인스턴싱)과 지연 로드(대규모 씬·디지털트윈).
  • Variants — 한 프림에 여러 명명된 옵션(그리퍼·LOD·구성), 별도 파일 없이.
  • Inherits·Specializes·Sublayers — 클래스 브로드캐스트·폴백·로컬 스택.
  • LIVRPS — 의견 충돌 시 강도 순서, "왜 이 값이 이기나"의 디버깅(usdview 합성 뷰).

선수 지식: 10.3(Stage·Prim·Layer·비파괴 오버라이드·.usda·edit target)·9.13(cloner — 참조/인스턴싱)·9.14(도메인 랜덤화 — 오버라이드 레이어)·10.2(협업 — 레이어). usdview·.usda 읽기는 10.3. 합성데이터는 10.5, 디지털트윈은 10.8. 이 장은 10.3의 직접 연속(데이터 모델 → 합성 작동).

정직: 컴포지션 아크·LIVRPS는 USD의 핵심이자 가장 까다로운 부분이다. 이 장은 "각 아크가 무엇을·언제, 강도 순서가 어떻게 작동하는가의 원리·실습"을 가르치되, USD 합성에는 세부 규칙·예외(목록 편집 prepend/append, 인스턴싱 의미, 활성/비활성) 가 많아 모두를 담지 못한다 — 깊은 경계는 "그 버전 USD 문서·usdview로 확인". API(pxr.Usd)는 비교적 안정적이나 버전 의존이 있다. 코드(.usda·pxr)는 개념 골격이되 실제와 가깝게. USD는 오픈 표준(AOUSD, 10.3) — NVIDIA 전유물 아님.

10.4.2 컴포지션 아크 — 씬을 조립하는 여섯 가지 방법

컴포지션 아크는 USD가 레이어·프림을 합성해 씬을 조립하는 메커니즘들이다. 여섯 가지가 있고, 각각 다른 용도와 강도를 가진다.

여섯 컴포지션 아크(용도별):

  • sublayers — 로컬 레이어 스택(10.3): 내 씬을 여러 레이어로 조직·오버라이드
  • references — 다른 자산(레이어/프림)을 가져옴: 재사용·인스턴싱(로봇 N번)
  • payloads — references 같되 지연 로드(load/unload): 대용량 자산·대규모 씬
  • variants — 한 프림에 여러 명명된 옵션: 구성(그리퍼·LOD)을 한 자산에
  • inherits — 클래스 프림에서 상속: 모든 인스턴스에 브로드캐스트 편집
  • specializes — inherits 같되 가장 약함: 폴백·특수화 기본값

강도 순서(LIVRPS, 강→약): Local · Inherits · Variants · References · Payloads · Specializes

  • 두 부류로 보면 쉽다: ① 재사용·조립(references·payloads — 외부 자산 가져오기, variants — 옵션 선택) ② 오버라이드·계층(sublayers — 로컬 스택, inherits·specializes — 클래스 의미). 대부분의 작업은 sublayers(오버라이드) + references(재사용) + variants(옵션) 셋으로.
  • 왜 여러 아크인가: 각각 다른 문제를 푼다 — references(재사용), payloads(스케일·지연), variants(구성), inherits(브로드캐스트), sublayers(협업·오버라이드). 한 아크로 다 안 되니 여섯.
  • 합성의 결과(10.3): 이 아크들이 의견을 모아 Stage(합성 결과)를 만든다. 한 속성에 여러 아크가 의견을 내면 LIVRPS 강도 순서(10.4.6)로 승자 결정.
  • 로보틱스 맥락: 로봇 자산을 references로 N번(9.13 cloner)·그리퍼를 variants·대용량 공장을 payloads·도메인 랜덤화를 sublayers 오버라이드(9.14)·공통 설정을 inherits. 실제 씬은 이 아크들의 조합.

핵심: 컴포지션 아크는 씬을 조립하는 여섯 메커니즘 — sublayers(로컬 오버라이드)·references(재사용)·payloads(지연 로드)·variants(옵션)·inherits(브로드캐스트)·specializes(폴백). 재사용·조립(refs·payloads·variants)과 오버라이드·계층(sublayers·inherits·specializes)으로 묶어 보면 쉽다. 의견 충돌은 LIVRPS 강도 순서로 해결. 대부분은 sublayers+references+variants로.

10.4.3 References·Payloads — 자산 재사용과 지연 로드

가장 많이 쓰는 아크는 references — 다른 자산을 프림에 가져와 재사용한다. payloads 는 그 지연 로드 버전이다.

# 로봇 자산을 참조로 N번 재사용(인스턴싱)
def Xform "Robot_01" (
    references = @./assets/robot.usd@</Robot>   # robot.usd의 /Robot 프림을 가져옴
)
{
    # 참조한 로봇 위에 비파괴 오버라이드(이 인스턴스만)
    double3 xformOp:translate = (0, 0, 0)
    uniform token[] xformOpOrder = ["xformOp:translate"]   # 순서 명시 필수(없으면 translate 무효, 10.3)
    over "base_link" { color3f[] primvars:displayColor = [(0,0,1)] }  # 이 로봇만 파랑
}
def Xform "Robot_02" (references = @./assets/robot.usd@</Robot>) { double3 xformOp:translate = (2, 0, 0)  uniform token[] xformOpOrder = ["xformOp:translate"] }
def Xform "Robot_03" (references = @./assets/robot.usd@</Robot>) { double3 xformOp:translate = (4, 0, 0)  uniform token[] xformOpOrder = ["xformOp:translate"] }
# robot.usd는 한 번 정의, 세 곳에서 재사용 — 자산 수정은 robot.usd 한 곳만
# 대용량 환경은 payload로 지연 로드(필요할 때만)
def Xform "Factory" (
    payload = @./assets/factory_heavy.usd@</Factory>   # load 전엔 메모리에 안 올림
) {}
  • References = 재사용·인스턴싱: 자산(robot.usd)을 한 번 정의하고 여러 프림이 참조한다 — 자산을 고치면 모든 인스턴스에 반영(한 곳 수정, 전체 갱신). 9.13의 cloner가 수천 환경에 로봇을 복제하는 것도 이 정신(인스턴싱). 파일 전체 또는 특정 프림(@file@</Prim>)을 참조.
  • 비파괴 오버라이드와 결합(10.3): 참조한 자산 위에 이 인스턴스만의 오버라이드를 적용한다 — Robot_01만 파랑, Robot_02는 다른 위치. 자산(robot.usd)은 안 건드림. 같은 자산, 다른 변형.
  • Payloads = 지연 로드(스케일): references와 거의 같되 기본적으로 로드 안 됨 — stage.Load(path)/Unload(path)로 필요할 때만 메모리에. 대규모 씬·디지털트윈(10.8) — 도시·공장 전체를 열되 보는 부분만 로드해 메모리·성능 관리. "대용량이고 항상 필요하진 않은" 자산은 payload.
  • References vs Payloads 선택: 항상 필요·경량이면 reference, 대용량이고·지연 로드하고 싶으면 payload. 큰 씬은 최상위를 payload로 묶어 부분 로드.
  • 인스턴싱 최적화: 같은 자산을 많이 참조하면 scenegraph instancing(instanceable=true)으로 메모리·성능을 아낀다(수천 동일 프림 — 9.13). 단 인스턴스는 개별 오버라이드 제약이 있다(정직: 인스턴싱 의미는 문서 확인).

견해: References = 자산을 한 번 만들고 N번 재사용(인스턴싱, 한 곳 수정으로 전체 갱신) + 인스턴스별 비파괴 오버라이드. Payloads = 그 지연 로드 버전(대용량 자산·대규모 씬을 필요할 때만 load) — 디지털트윈·도시 규모(10.8)의 메모리·성능 핵심 요인. 로봇을 수천 배치(9.13)·환경 재사용이 references, 거대 씬 부분 로드가 payloads. 인스턴싱으로 스케일.

10.4.4 Variants — 한 프림의 여러 옵션

Variants(변형) 는 한 프림에 여러 명명된 옵션을 담아 하나를 선택하게 한다 — 별도 파일·분기 없이 구성(configuration)을.

# 로봇 그리퍼 옵션을 variant set으로(한 자산에 여러 구성)
def Xform "Robot" (
    variants = { string gripper = "parallel" }   # 현재 선택: parallel
    prepend variantSets = "gripper"
)
{
    variantSet "gripper" = {
        "parallel" {                              # 옵션 1: 평행 그리퍼
            def "Gripper" (references = @./parallel_gripper.usd@) {}
        }
        "suction" {                               # 옵션 2: 흡착 그리퍼
            def "Gripper" (references = @./suction_gripper.usd@) {}
        }
        "none" {}                                 # 옵션 3: 없음
    }
}
# 선택만 바꾸면(gripper = "suction") 다른 그리퍼로 — 한 자산, 여러 구성
  • Variant set = 옵션 묶음: gripper라는 variant set에 parallel·suction·none 변형이 있고, 하나를 선택(variants = {gripper = "parallel"}). 선택을 바꾸면 그 변형의 내용이 합성된다. 한 자산이 여러 구성을 품는다.
  • 왜 variant인가(별도 파일 대비): 그리퍼 옵션마다 robot_parallel.usd·robot_suction.usd를 따로 두면 자산이 폭증·중복. variant는 한 자산에 옵션을 담아 선택만 바꾼다 — 구성 관리가 간결. 로봇 구성·차량 트림·제품 옵션·LOD(상세 수준)·재질 변형 등.
  • 로보틱스·산업 활용: 로봇 그리퍼·센서 구성, 작업 셀 레이아웃 옵션, 제품 변형(디지털트윈 10.8의 "what-if"), LOD(거리별 상세). 도메인 랜덤화(9.14)도 변형으로 옵션화 가능.
  • 중첩·다중 variant set: 한 프림에 여러 variant set(gripper·sensor·color)을, 각각 독립 선택 → 조합 폭발 없이 구성. variant 안에 또 variant(중첩).
  • API: vset = prim.GetVariantSets().AddVariantSet("gripper")·vset.AddVariant("parallel")·vset.SetVariantSelection("parallel")·with vset.GetVariantEditContext(): ...(변형 내용 정의).

견해: Variants는 한 프림에 여러 명명된 옵션을 담아 선택하게 한다 — 그리퍼·LOD·구성·제품 트림을 별도 파일 없이 한 자산에. 옵션마다 파일을 두는 중복·폭증을 피하고, 선택만 바꿔 구성 전환. 다중 variant set으로 직교 구성(gripper×sensor×color). 디지털트윈 what-if(10.8)·도메인 랜덤화(9.14) 옵션화에. usdview로 변형 선택·미리보기.

10.4.5 Inherits·Specializes·Sublayers — 나머지 아크

남은 세 아크 — sublayers(10.3에서 봤음)·inherits·specializes — 는 계층·브로드캐스트·폴백을 담당한다.

   sublayers (Local, 가장 강함):
     · 내 씬을 여러 레이어로 쌓음(루트가 서브레이어 포함) → LayerStack
     · 협업(팀별 레이어 10.2)·오버라이드(랜덤화 9.14). 10.3의 그것.

   inherits (강함 — 클래스 브로드캐스트):
     · 프림이 "클래스(class)" 프림을 상속 → 클래스 변경이 모든 상속 프림에 전파
     · 예: 모든 "나무" 프림이 _class_Tree를 상속 → 나무 공통 속성을 한 곳에서
     · "이 종류 전부에 적용" 의미. references보다 강함.

   specializes (가장 약함 — 폴백·특수화):
     · inherits 같되 가장 약함 → "기본값/폴백"으로, 다른 의견이 없을 때만 적용
     · 특수화(specialization) 의미: 일반 → 특수로 다듬되 베이스 폴백 유지
  • Sublayers(Local — 최강): 10.3의 로컬 레이어 스택. 내 씬을 레이어로 조직하고 오버라이드. 협업(10.2)·랜덤화(9.14)의 오버라이드 레이어가 여기. LIVRPS의 L(가장 강함).
  • Inherits(클래스 브로드캐스트): 여러 프림이 공통 클래스(class) 를 상속하면, 클래스를 바꿀 때 모든 상속 프림에 전파된다 — "이 종류 전부에 공통 속성·오버라이드". 예: 모든 신호등 프림이 _class_TrafficLight를 상속 → 신호등 공통 동작을 한 곳에서 수정. references(개별 인스턴스)보다 강해(LIVRPS의 I), 참조로 들어온 인스턴스 의견을 이긴다(단, 로컬 오버라이드 L은 inherits보다 강함 — L>I).
  • Specializes(폴백 — 최약): inherits와 비슷하나 가장 약함 — "다른 의견이 없을 때만 적용되는 기본값/폴백". 일반 자산을 특수화하되 베이스 폴백을 유지하는 의미. 드물게 쓰이나 강도 체계의 바닥(LIVRPS의 S).
  • 언제 무엇: 대부분은 sublayers(오버라이드)·references(재사용)·variants(옵션) 로 충분하고, inherits는 "한 종류 전체에 브로드캐스트"가 필요할 때, specializes는 폴백 기본값이 필요한 드문 경우. inherits·specializes는 고급·라이브러리 설계에 주로.
  • 목록 편집(prepend/append/delete): 아크는 목록이라 prepend(앞에 — 더 강하게)·append(뒤에)·delete로 편집 — 강도·순서에 영향(고급, 문서 확인).

견해: sublayers(최강 — 로컬 오버라이드·협업)·inherits(강함 — 클래스 브로드캐스트 "이 종류 전부에")·specializes(최약 — 폴백 기본값)가 계층·전파·폴백을 담당. 일상은 sublayers·references·variants로 충분하고, inherits는 공통 속성 브로드캐스트, specializes는 폴백 — 라이브러리·고급 설계에. 이들의 상대 강도가 다음 절 LIVRPS.

10.4.6 LIVRPS — 누가 이기는가

한 속성에 여러 아크가 의견을 내면 무엇이 이기나? USD는 LIVRPS라는 고정된 강도 순서로 결정한다 — 이것이 합성의 핵심 규칙이자 디버깅의 핵심 요인.

   LIVRPS — 강도 순서(강 → 약):

   L  Local       — 로컬 레이어 스택(sublayers·직접 의견)  ← 가장 강함
   I  Inherits    — 상속(클래스)
   V  Variants    — 선택된 변형
   R  References   — 참조한 자산
   P  Payloads    — 페이로드(지연 로드 자산)
   S  Specializes  — 특수화(폴백)                          ← 가장 약함

   규칙: 더 강한 아크의 의견이 약한 것을 이긴다.
        한 아크 내에서는 레이어 순서(위가 강함)로.

   예: 참조한 robot.usd(R)가 색=빨강, 로컬 오버라이드(L)가 색=파랑
       → L > R → 색 = 파랑 (로컬이 참조를 이김 = 비파괴 오버라이드 10.3)
  • 왜 이 순서가 중요한가: "내 오버라이드가 왜 안 먹지?" "이 값이 왜 여기서 오지?"의 답이 거의 항상 LIVRPS다. 로컬(L)이 가장 강하므로 로컬 오버라이드는 참조·변형을 이긴다(10.3 비파괴 오버라이드가 되는 이유 = L > R). 반대로 inherits(I)는 references(R)보다 강해 클래스 브로드캐스트가 참조 자산의 의견을 이긴다(단, 로컬 오버라이드 L은 클래스를 이김 — L>I).
  • 요지: ① 로컬(내 직접 편집)이 최강 — 내가 지금 쓴 것이 가져온 자산을 이김(상식적). ② inherits(이 종류 전부)는 references(개별 자산)보다 강함 — 종류 전체 규칙이 개별을 이김. ③ specializes는 최약 — 폴백이라 다른 의견이 있으면 짐.
  • 아크 내 순서: 같은 아크(예: 여러 sublayer)에선 레이어 스택 순서(위가 강함)로 — 협업서 위 레이어가 아래를 이김(10.2).
  • 디버깅(usdview 합성 뷰): usdview의 "Composition" / prim 합성 탭이 한 프림의 모든 아크와 각 의견의 출처 레이어·강도를 보여준다 — "이 값이 어느 레이어·아크에서 오나"를 정확히. "오버라이드 안 먹음"은 ① edit target이 약한 레이어 ② 더 강한 아크가 이김(inherits·강한 sublayer) → usdview로 확인.
  • 정직: LIVRPS는 핵심 골격이고, 세부(목록 편집 강도·인스턴싱·활성)는 더 미묘하다 — 정확한 판정은 usdview 합성 뷰로(추측 금지).

견해: LIVRPS(Local·Inherits·Variants·References·Payloads·Specializes, 강→약) 가 의견 충돌의 승자를 정한다 — 합성의 핵심 규칙. 로컬(L) 최강이라 비파괴 오버라이드가 참조를 이기고(10.3), inherits(I)>references(R)라 클래스 브로드캐스트가 인스턴스를 이긴다. "오버라이드 왜 안 먹나"의 90%가 이 순서·edit target — usdview 합성 뷰로 출처를 보는 것이 디버깅. 추측 말고 합성 뷰로.

10.4.7 워크스루 — 참조·변형·오버라이드·합성 디버깅

아크들을 Python으로 조립하고 usdview로 합성을 디버깅하는 흐름.

# 컴포지션 아크 조립(개념 — pxr API, 버전 확인)
from pxr import Usd, UsdGeom, Sdf, Gf

stage = Usd.Stage.CreateNew("scene.usda")

# 1) Reference — 로봇 자산을 N번 재사용 + 인스턴스별 오버라이드(10.4.3)
for i in range(3):
    robot = UsdGeom.Xform.Define(stage, f"/World/Robot_{i:02d}")
    robot.GetPrim().GetReferences().AddReference("./assets/robot.usd", "/Robot")
    UsdGeom.XformCommonAPI(robot).SetTranslate(Gf.Vec3d(i*2, 0, 0))   # 위치 오버라이드(로컬 L)
# robot.usd는 한 번 정의 → 자산 수정은 한 곳, 모든 인스턴스 갱신

# 2) Variant set — 그리퍼 옵션(10.4.4)
robot0 = stage.GetPrimAtPath("/World/Robot_00")
vset = robot0.GetVariantSets().AddVariantSet("gripper")
for name, asset in [("parallel","./parallel.usd"), ("suction","./suction.usd")]:
    vset.AddVariant(name)
    vset.SetVariantSelection(name)
    with vset.GetVariantEditContext():
        g = stage.DefinePrim(robot0.GetPath().AppendChild("Gripper"))
        g.GetReferences().AddReference(asset)
vset.SetVariantSelection("parallel")     # 현재 선택

# 3) Payload — 대용량 환경 지연 로드(10.4.3)
factory = stage.DefinePrim("/World/Factory")
factory.GetPayloads().AddPayload("./assets/factory_heavy.usd")
# 기본 미로드 → 필요시 stage.Load("/World/Factory") / Unload(...)

stage.GetRootLayer().Save()
# 4) 비파괴 오버라이드 — 별도 레이어에서(10.3·L이 R 이김)
over_layer = Sdf.Layer.CreateNew("override.usda")
stage.GetRootLayer().subLayerPaths.insert(0, "override.usda")  # 위(강한) 서브레이어
stage.SetEditTarget(over_layer)
robot1 = stage.GetPrimAtPath("/World/Robot_01/base_link")  # 색은 지오메트리(Gprim) 프림에 — displayColor는 Xform이 아닌 Gprim 속성
robot1.CreateAttribute("primvars:displayColor", Sdf.ValueTypeNames.Color3fArray).Set([(0,0,1)])  # 이 로봇만 파랑(로컬 L)
over_layer.Save()
# 5) 합성 디버깅 — usdview(10.4.6)
usdview scene.usda
#   · 프림 선택 → "Composition" 탭: 이 프림의 모든 아크·각 의견 출처 레이어·강도
#   · "이 색이 어디서 오나?" → 합성 뷰로 출처 레이어 확인(override.usda? robot.usd?)
#   · variant 선택 드롭다운으로 그리퍼 전환 미리보기
#   · payload load/unload로 메모리·표시 제어
   체크포인트:
     · Reference로 자산 한 번 정의·N번 재사용 — robot.usd 수정이 전부 반영되나
     · 인스턴스별 로컬 오버라이드(위치·색)가 참조를 이기나(L > R, 10.4.6)
     · Variant 선택 전환으로 그리퍼 바뀌나
     · Payload load/unload로 대용량 환경 메모리 제어되나
     · usdview 합성 뷰로 "이 값의 출처"를 추적할 수 있나(디버깅 핵심)
  • 합성 디버깅이 핵심 역량: "왜 이 값이?"는 usdview 합성/prim stack 뷰로 — 각 의견의 출처 레이어·아크·강도(LIVRPS)를 보고 승자를 이해. 추측하지 말고 본다.
  • edit target 확인(10.3): 오버라이드가 안 먹으면 ① edit target이 약한 레이어인지 ② 더 강한 아크(inherits·강한 sublayer)가 이기는지 — 합성 뷰로.
  • 로보틱스 조립: 로봇(reference)·그리퍼(variant)·환경(payload)·랜덤화(override layer 9.14)·작업 셀 배치(reference + 위치 오버라이드) — 9.13 cloner·10.8 트윈의 실제 구성.

견해: 실습은 ① reference로 재사용(자산 한 곳, N번) + 로컬 오버라이드(L>R) ② variant로 옵션(그리퍼 전환) ③ payload로 지연 로드(대용량 환경) ④ usdview 합성 뷰로 "값의 출처" 디버깅(LIVRPS). 이 조합이 로봇 씬·작업 셀·디지털트윈(10.8)·병렬 환경(9.13)의 실제 조립법. "왜 이 값이?"는 추측 말고 합성 뷰로 출처를 본다.

10.4.8 중간 점검 (체크포인트)

  • [ ] 여섯 컴포지션 아크(sublayers·references·payloads·variants·inherits·specializes)의 용도를 구분한다.
  • [ ] References(재사용·인스턴싱)와 Payloads(지연 로드·스케일)의 차이와 언제 무엇인지 안다.
  • [ ] Variants가 한 프림에 여러 옵션을 담아(그리퍼·LOD) 별도 파일 없이 구성함을 안다.
  • [ ] Inherits(클래스 브로드캐스트, R보다 강함)·Specializes(폴백, 최약)·Sublayers(로컬, 최강)를 안다.
  • [ ] LIVRPS 강도 순서로 의견 충돌이 해결됨과(L>...>S), 비파괴 오버라이드가 L>R임을 안다.
  • [ ] usdview 합성 뷰로 "이 값의 출처·승자"를 추적해 합성을 디버깅할 줄 안다.

증상→의심: 오버라이드가 안 먹음 → edit target이 약한 레이어·더 강한 아크(inherits·강한 sublayer)가 이김 → usdview 합성 뷰·edit target 확인(10.4.6). 이 값이 어디서? → 합성 뷰로 출처 레이어·아크 추적. 자산 수정이 일부만 반영 → reference vs 복사·인스턴싱 제약 → 참조 구조 확인. variant 전환이 안 됨 → variant 선택·set 이름·편집 컨텍스트 → usdview. 대용량 씬이 안 열림/느림 → payload 미사용(전부 로드) → payload·부분 load(10.4.3). 인스턴스 오버라이드가 안 됨 → instanceable 인스턴싱 제약 → 문서 확인. 클래스 변경이 일부만 → inherits 구조·강도 → 합성 뷰.

10.4.9 트레이드오프·대안

결정트레이드오프
References vs 인라인 복사재사용·한 곳 수정·인스턴싱 vs 단순·독립
Payloads vs References지연 로드·스케일·메모리 vs 항상 로드·단순
Variants vs 별도 파일한 자산 구성·간결 vs 단순·명시
Inherits vs References(공통)종류 전체 브로드캐스트 vs 개별 인스턴스
Instancing vs 개별 프림메모리·성능(수천) vs 인스턴스별 자유 편집
로컬 오버라이드 vs 자산 수정비파괴·실험·협업 vs 영구·근본

견해: 대규모·재사용·협업 씬의 조립은 references(재사용)·payloads(스케일)·variants(구성)·sublayers(오버라이드)의 조합이 정석이다 — 로봇·작업 셀·디지털트윈(10.8)·병렬 환경(9.13). 인스턴싱은 수천 동일 프림의 메모리·성능에 필수이나 인스턴스별 자유 편집을 제약(트레이드오프). inherits·specializes는 강력하나 고급 — 대부분은 references+variants+sublayers로 충분, 종류 전체 브로드캐스트가 필요할 때만 inherits. 로컬 오버라이드(비파괴) 가 협업·실험의 기본(자산 수정은 근본 변경일 때만). 합성이 복잡해지면 usdview 합성 뷰가 유일한 진실 — 추측 금지.

비엔비디아 정직: 컴포지션·참조·변형의 개념은 USD 표준(픽사·AOUSD, 10.3) 의 것이지 NVIDIA 고유가 아니다 — USD를 쓰는 모든 도구가 같은 합성을 공유. 다른 씬 시스템도 참조·인스턴싱·LOD·오버라이드 개념을 갖지만(게임 엔진의 프리팹·인스턴스 등), USD의 차별점은 비파괴 레이어 합성 + 강도 규칙(LIVRPS) + 표준화·상호운용이다. 합성은 강력하나 학습 곡선·디버깅 난이도가 있어(LIVRPS·아크 상호작용), usdview·문서 의존이 크다 — 단순 씬엔 과할 수 있다. 깊은 경계는 그 버전 USD 문서로.

10.4.10 흔한 함정

  • 로컬 오버라이드가 적용되지 않는다고 당황. 거의 항상 edit target이 약한 레이어·더 강한 아크(inherits) → usdview 합성 뷰·LIVRPS(10.4.6).
  • References로 가져온 자산을 직접 수정. 자산(robot.usd)을 고치면 모든 인스턴스에 영향 → 인스턴스만 바꾸려면 로컬 오버라이드(10.3).
  • 대용량 씬 전부 로드. payload 미사용으로 메모리·느림 → payload·부분 load(10.4.3).
  • 옵션마다 파일 폭증. 그리퍼·LOD를 별도 파일로 → variants로 한 자산에(10.4.4).
  • 인스턴싱 한계 무시. instanceable 프림은 인스턴스별 자유 편집 제약 → 의미 확인(문서).
  • 합성을 추측으로 디버깅. "왜 이 값이?"를 짐작 → usdview 합성/prim stack 뷰로 출처 확인.
  • inherits·references 강도 혼동. inherits(I)>references(R) — 클래스가 인스턴스를 이김 → LIVRPS.
  • 목록 편집(prepend/append) 강도 무시. 아크 추가 순서·위치가 강도에 영향 → 문서·합성 뷰.
  • variant 편집 컨텍스트 누락. 변형 내용을 컨텍스트 밖에서 정의 → GetVariantEditContext() 안에서.
  • USD 합성을 NVIDIA 고유로 오해. USD 표준(AOUSD) — 다른 도구도 동일(10.2·10.3).

10.4.11 연습문제

연습 1 (여섯 아크 분류). 여섯 컴포지션 아크를 용도로 분류하고, References·Payloads·Sublayers를 각각 언제 쓰는지 구체 예로 답하라.

정답

용도 분류: 재사용·조립 — ① references(외부 자산을 가져와 재사용·인스턴싱) ② payloads(references 같되 지연 로드·스케일) ③ variants(한 프림에 여러 명명 옵션, 하나 선택). 오버라이드·계층 — ④ sublayers(로컬 레이어 스택·오버라이드·협업) ⑤ inherits(클래스 상속·종류 전체 브로드캐스트) ⑥ specializes(폴백·특수화 기본값). 강도(LIVRPS): Local(sublayers)>Inherits>Variants>References>Payloads>Specializes. References 언제: 자산을 재사용·인스턴싱할 때 — 로봇 한 자산을 작업 셀에 3대 배치(각 reference + 위치 오버라이드), 환경 자산 재사용, 9.13 cloner가 수천 환경에 로봇 복제. 자산을 한 곳(robot.usd) 정의하고 N번 참조 → 자산 수정이 모든 인스턴스에 반영. 항상 필요·비교적 경량인 자산. Payloads 언제: references와 같되 대용량이라 지연 로드하고 싶을 때 — 디지털트윈(10.8)의 공장·도시 전체, 고해상도 환경. payload로 묶으면 기본 미로드, stage.Load()로 보는 부분만 메모리에 → 거대 씬을 열되 메모리·성능 관리(부분 로드). "대용량이고 항상 필요하진 않은" 자산. Sublayers 언제: 내 씬을 레이어로 조직·오버라이드할 때 — 협업(10.2)에서 라이팅 팀은 lighting.usda, 모델 팀은 model.usda로 비파괴 동시 작업; 도메인 랜덤화(9.14)에서 베이스 위에 랜덤화 오버라이드 레이어; 디지털트윈(10.8)에서 설계 위에 운영 레이어. 로컬 레이어 스택(루트 + 서브레이어), 위가 강함(LIVRPS의 L 최강). 요약: 자산 재사용=references, 대용량 지연 로드=payloads, 내 씬 조직·오버라이드=sublayers, 옵션=variants, 종류 브로드캐스트=inherits, 폴백=specializes. 대부분은 references+variants+sublayers로.

연습 2 (참조·인스턴싱). 로봇 자산 하나를 작업 셀에 4대 배치하되 각각 다른 위치·색을 주는 USD 구조를 설계하고, 자산 수정 시 무엇이 어떻게 반영되는지, 9.13 cloner와 어떻게 연결되는지 답하라.

정답

구조: 로봇 자산을 robot.usd에 한 번 정의(/Robot 프림 — 링크·조인트·물리 스키마 10.3). 작업 셀 씬에서 4개 프림이 이를 reference: /World/Robot_00~03 각각 references = @robot.usd@</Robot>. 각 프림에 로컬 오버라이드(L>R, 10.4.6)로 위치·색: Robot_00 { translate=(0,0,0); over "base_link" { displayColor=[(1,0,0)] } }, Robot_01 { translate=(2,0,0); ... 파랑 } 등. 위치는 xformOp:translate, 색은 참조 내부 프림(over "base_link")에 오버라이드. 자산 수정 반영: robot.usd를 고치면(예: 새 센서 추가·링크 형상 변경) → 4대 모두에 자동 반영(reference라 한 곳 수정, 전체 갱신). 반대로 인스턴스별 오버라이드(위치·색)는 각 프림의 로컬 레이어에만 있어 그 인스턴스만 영향 — 자산은 안 건드림. 즉 공통(자산)은 한 곳, 개별(위치·색)은 인스턴스별. 9.13 cloner 연결: Isaac Lab의 cloner가 수천 RL 환경에 로봇을 복제하는 것이 이 reference/인스턴싱 정신이다 — 로봇 자산을 한 번 정의하고 N개 환경에 참조·복제, 각 환경은 다른 초기 상태(위치·관절). 수천 동일 프림은 scenegraph instancing(instanceable=true)으로 메모리·성능 최적화(개별 자유 편집은 제약, 트레이드오프). 즉 9.13의 "N환경 병렬"이 데이터 모델 차원에선 "로봇 자산을 N번 참조·인스턴싱"이고, GPU 물리(PhysX 9.11)가 그 N개를 배치로 시뮬. 자산 수정이 전체 반영되니 로봇 디자인 반복이 쉽고, 인스턴스 오버라이드로 환경별 변형(도메인 랜덤화 9.14는 오버라이드 레이어로). 핵심: reference=공통 자산 한 곳·N번 재사용, 로컬 오버라이드=인스턴스별 변형, instancing=스케일.

연습 3 (변형). 로봇 그리퍼를 parallel·suction·none 세 옵션으로 두는 variant set을 설계하고, variant가 별도 파일(robot_parallel.usd 등) 대비 무엇이 유리하며 다중 variant set은 어떻게 쓰는지 답하라.

정답

variant set 설계: /Robot 프림에 gripper variant set을 두고 세 변형: parallel(평행 그리퍼 자산 reference), suction(흡착 그리퍼 reference), none(빈 변형). variants = {gripper="parallel"}로 현재 선택, prepend variantSets="gripper"로 등록. 각 변형 안에서 def "Gripper" (references=@해당_그리퍼.usd@)로 내용 정의(GetVariantEditContext() 안에서). 선택을 suction으로 바꾸면 합성 결과가 흡착 그리퍼로 전환 — 한 자산, 선택만 변경. API: vset=prim.GetVariantSets().AddVariantSet("gripper")·vset.AddVariant("parallel")·SetVariantSelection. 별도 파일 대비 유리: 옵션마다 robot_parallel.usd·robot_suction.usd·robot_none.usd를 따로 두면 ① 자산 폭증·중복(로봇 본체가 세 파일에 중복) ② 본체 수정 시 세 파일 모두 고쳐야(불일치 위험) ③ "어느 것이 실제 로봇?" 혼란. variant는 ① 한 자산에 옵션을 담아 본체 중복 없음(본체는 한 번, 그리퍼만 변형) ② 본체 수정이 한 곳 ③ 선택만 바꿔 구성 전환(런타임·usdview 드롭다운). 간결한 구성 관리. 다중 variant set: 한 프림에 여러 독립 variant set — 예: gripper(parallel/suction)·sensor(camera/lidar)·color(red/blue). 각각 독립 선택 → 조합(parallel+camera+red, suction+lidar+blue…)을 곱집합 파일 없이 표현(2×2×2=8 구성을 8개 파일이 아니라 3개 set로). 직교 구성. 중첩(variant 안에 또 variant)도 가능. 활용: 로봇 구성(그리퍼·센서), 차량 트림, 제품 옵션, LOD(거리별 상세 — high/mid/low variant), 디지털트윈 what-if(10.8, 레이아웃 옵션), 도메인 랜덤화(9.14) 옵션화. usdview로 변형 미리보기·선택. 핵심: variant=한 자산의 여러 명명 옵션, 별도 파일 중복·폭증 회피, 다중 set로 직교 구성. 선택은 로컬 오버라이드로도 바꿀 수 있어 인스턴스별 다른 그리퍼(reference + variant 선택 오버라이드).

연습 4 (LIVRPS 디버깅). LIVRPS 강도 순서를 설명하고, "참조한 자산 위에 로컬 오버라이드를 했는데 적용되지 않는다"·"클래스를 바꿨는데 인스턴스 오버라이드가 이긴다" 두 상황을 진단하라.

정답

LIVRPS: 한 속성에 여러 컴포지션 아크가 의견을 내면, USD는 고정된 강도 순서로 승자를 정한다 — Local(로컬 레이어 스택·sublayers·직접 의견, 최강) > Inherits(상속 클래스) > Variants(선택된 변형) > References(참조 자산) > Payloads(페이로드) > Specializes(특수화 폴백, 최약). 더 강한 아크가 약한 것을 이기고, 같은 아크 내에선 레이어 순서(위가 강함). 상황 1 — "로컬 오버라이드가 적용되지 않는다": 이론상 L > R이라 로컬 오버라이드는 참조를 이겨야 한다(비파괴 오버라이드 10.3의 원리). 안 먹으면: ① edit target이 잘못된 레이어 — 오버라이드를 약한/잘못된 레이어에 썼거나, 더 약한 sublayer에(같은 L이라도 레이어 순서로 위가 강함) → edit target 확인, 강한(위) 레이어에. ② 더 강한 아크가 이김 — 그 속성에 inherits(I) 의견이 있으면? I는 R보다 강하지만 L보다 약하니 로컬이 이겨야… 그래도 안 먹으면 ③ 경로·프림 불일치(오버라이드가 다른 프림/경로를 가리킴, 인스턴싱으로 인스턴스 편집 제약) ④ 속성 이름·네임스페이스 오타. 진단: usdview 합성/prim stack 뷰로 그 속성의 모든 의견과 출처 레이어·아크·강도를 본다 → 어디서 이기는 값이 오는지 정확히. 추측 금지. 상황 2 — "클래스를 바꿨는데 인스턴스 오버라이드가 이긴다": inherits(I) 는 references(R)보다 강하지만 Local(L)보다 약하다. 인스턴스 오버라이드를 로컬 레이어(L) 에 썼다면, L > I라 로컬 인스턴스 오버라이드가 클래스(inherits)를 이긴다 — 정상 동작! 클래스 변경을 모든 인스턴스에 강제하려면 인스턴스의 로컬 오버라이드를 제거하거나, 클래스 의견이 인스턴스 로컬보다 강해야 하는데 LIVRPS상 그럴 수 없다(L이 최강). 즉 로컬 오버라이드는 항상 클래스 브로드캐스트를 이긴다 — 의도라면 OK, 아니면 인스턴스 로컬 오버라이드를 빼야. 진단: usdview 합성 뷰로 인스턴스의 displayColor가 로컬(L)에서 오는지 클래스(I)에서 오는지 확인. 핵심: LIVRPS가 충돌 승자를 정하고, 로컬이 최강(내 직접 편집이 가져온 것·종류 규칙을 이김)·inherits>references(종류>개별). "왜 이 값이?"는 usdview 합성 뷰가 유일한 진실 — 강도와 출처를 보고 이해. 추측·짐작이 디버깅 실패의 원인.

연습 5 (스케일·디지털트윈). Payloads의 지연 로드가 대규모 씬·디지털트윈(10.8)에 왜 중요한지 설명하고, 거대한 공장 디지털트윈을 references·payloads·variants·오버라이드 레이어로 어떻게 구성할지 설계하라.

정답

Payloads 지연 로드의 중요성: 디지털트윈(10.8)·도시·공장은 수십 GB~TB 규모일 수 있다 — 모든 자산(건물·기계·로봇·파이프)을 한 번에 메모리에 적재하면 ① 메모리 초과(RTX GPU·RAM 한계) ② 로딩·렌더 느림 ③ 사용자는 보통 일부만 본다(한 라인·한 구역). Payloads는 자산을 기본 미로드로 두고 stage.Load(path)/Unload(path)로 필요한 부분만 메모리에 적재한다 → 거대 씬을 열되(구조·계층은 보임) 보는/작업하는 부분만 로드해 메모리·성능 관리. references는 항상 로드라 거대 씬엔 부적합 → payload가 스케일의 핵심 요인. 공장 디지털트윈 구성 설계: ① 자산 라이브러리(references) — 기계·로봇·컨베이어·랙을 각각 한 자산(machine.usd·robot.usd…)으로 정의, 공장 전역에 reference로 재사용·인스턴싱(같은 기계 20대 = reference 20번 + 위치 오버라이드, 10.4.3). ② 구역별 payload — 공장을 라인/구역으로 나눠 각 구역을 payload로 묶음(/Factory/LineA payload, /Factory/LineB payload…) → 사용자가 보는 구역만 load, 나머지 unload → TB 공장을 메모리 한도에서. ③ 구성 variants — 기계의 레이아웃 옵션·제품 변형·LOD를 variant set으로(10.4.4) — what-if 시나리오(라인 재배치)를 variant 전환으로. LOD variant(원거리=저폴리, 근거리=고폴리)로 성능. ④ 오버라이드 레이어(sublayers) — 설계 레이어(CAD 원본, 10.2 커넥터) 위에 운영 레이어(실시간 센서·기계 상태, 10.8)·시뮬 레이어(로봇 시뮬 9.11)·what-if 레이어(가상 변경)를 비파괴로 겹침(L 최강이라 운영이 설계 위에). 설계는 그대로, 운영·실험을 오버레이하고 제거함. ⑤ 인스턴싱 — 동일 기계 수백 대는 instanceable로 메모리·성능. ⑥ 협업(Nucleus 10.2) — 각 팀(설계·운영·로봇)이 다른 레이어에 동시 작성. 결과: references(재사용)·payloads(부분 로드 스케일)·variants(구성·LOD)·오버라이드 레이어(설계+운영+what-if 비파괴)·인스턴싱(성능)이 합쳐 TB 규모 공장을 메모리 한도에서 협업·시뮬·운영. usdview·합성 뷰로 디버깅. 이것이 디지털트윈(10.8)이 USD 위에 서는 이유 — 합성·지연 로드·비파괴가 대규모·다팀·동적 트윈을 가능케. 정직: 실제 스케일·성능은 하드웨어·구조 의존, payload 경계·인스턴싱 설계가 관건.

10.4.12 요약 · 다음 장

  • 여섯 컴포지션 아크: sublayers(로컬 오버라이드·협업)·references(재사용·인스턴싱)·payloads(지연 로드·스케일)·variants(옵션)·inherits(클래스 브로드캐스트)·specializes(폴백). 대부분은 references+variants+sublayers.
  • References·Payloads: 자산을 한 번 만들고 N번 재사용(인스턴싱·한 곳 수정 전체 반영, 9.13 cloner) / 대용량 자산 지연 로드(대규모 씬·디지털트윈 10.8 메모리·성능).
  • Variants: 한 프림에 여러 명명 옵션(그리퍼·LOD·구성)을 담아 별도 파일 없이 선택. 다중 set로 직교 구성.
  • LIVRPS: 의견 충돌의 강도 순서 Local>Inherits>Variants>References>Payloads>Specializes. 로컬 최강(비파괴 오버라이드 L>R)·inherits>references. "왜 이 값이?"의 답.
  • 디버깅: usdview 합성/prim stack 뷰로 의견의 출처 레이어·아크·강도를 추적 — 추측 금지. 합성이 협업(10.2)·랜덤화(9.14)·트윈(10.8)·병렬(9.13)의 실제 메커니즘. 정직: USD 표준(AOUSD), 세부 규칙은 문서·usdview.

다음 장: 10.5 합성데이터 I — Replicator 파이프라인. OpenUSD(데이터 모델·합성)를 마쳤으니, 그 위에서 완벽한 라벨의 학습 데이터를 대량 생성하는 Replicator로 동작한다(9.11·9.12에서 맛봤다). USD 씬·RTX 센서(9.11)·도메인 랜덤화를 엮어 분할·박스·깊이 GT를 자동 생성하는 합성데이터 파이프라인을 본격적으로. 데이터 모델이 데이터 생성으로.