> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-ko/sdk7/getting-started/coding-scenes.md).

# 코딩 필수 요소

이 세트는 Decentraland의 클라이언트와 SDK에서 일이 어떻게 작동하는지 이해하는 데 도움이 됩니다.

## 개발 도구

매우 높은 수준에서, Decentraland는 **소프트웨어 개발 키트** (SDK)를 사용하면 다음을 할 수 있습니다:

* 기본값을 생성하는 *프로젝트* 콘텐츠를 렌더링하고 실행하는 데 필요한 모든 자산을 포함한 Decentraland 씬을 포함합니다.
* Decentraland 씬의 콘텐츠를 웹 브라우저에서 로컬로 빌드, 테스트, 미리보기할 수 있습니다. Ethereum 거래를 하거나 LAND를 소유할 필요 없이 완전히 오프라인으로 가능합니다.
* Decentraland API를 사용해 TypeScript 코드를 작성하여 씬에 상호작용적이고 동적인 동작을 추가하세요.
* 씬의 콘텐츠를 콘텐츠 서버에 업로드합니다.
* 보유한 LAND 토큰을 업로드한 콘텐츠의 URL에 연결합니다.

우리 SDK에는 다음이 포함됩니다:

* **크리에이터 허브**: 그중에서도 쉬운 드래그 앤 드롭 인터페이스로 씬을 만들 수 있는 독립형 애플리케이션입니다. 미리보기를 실행하고, 디버그하고, 코드를 편집하고, 게시할 수 있습니다. [자세히 보기](/creator/content-creator-ko/scene-editor/get-started/about-editor.md)
* **Decentraland ECS**: 상호작용 경험을 만들 수 있게 해주는 헬퍼 메서드 프레임워크가 포함된 TypeScript 패키지입니다. 이를 사용하여 씬의 객체를 만들고 조작하며, 플레이어 간 또는 다른 애플리케이션과의 인월드 거래를 지원할 수 있습니다. ( [최신 ECS 참고 문서](https://github.com/decentraland/ecs-reference/blob/master/docs-latest/decentraland-ecs.md))
* **장면 예시**: 다음에서 영감과 코딩 모범 사례를 얻어보세요: [씬 예제](https://studios.decentraland.org/resources?sdk_version=SDK7).

기타 레거시 도구:

* **웹 편집기**: 간단한 씬을 만들고 게시할 수 있는 웹 기반 도구입니다.

## 요구 사항

씬을 로컬에서 개발하려면 LAND 토큰을 소유할 필요가 없습니다. 씬의 개발과 테스트는 완전히 오프라인으로 할 수 있으며, Ethereum 네트워크(Decentraland가 LAND와 Decentraland Name의 소유권을 확립하는 데 사용하는 시스템)나 콘텐츠 서버에 씬을 배포할 필요도 없습니다.

다음이 필요합니다:

* **크리에이터 허브**: 그중에서도 쉬운 드래그 앤 드롭 인터페이스로 씬을 만들 수 있는 독립형 애플리케이션입니다. 미리보기를 실행하고, 디버그하고, 코드를 편집하고, 게시할 수 있습니다. [자세히 보기](/creator/content-creator-ko/scene-editor/get-started/about-editor.md).

씬의 코드를 편집할 계획이라면, 다음 중 하나도 설치해야 합니다:

* <img src="https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-72733d889cecbb74400d2c9292b43a212b253969%2Fvscode.png?alt=media" alt="VS Code" data-size="line"> **Visual Studio Code**: 다운로드하세요 [여기](https://code.visualstudio.com/). 코드를 훨씬 더 빠르고 오류를 줄여가며 작성하는 데 도움이 됩니다. 소스 코드 편집기는 구문 오류를 표시하고, 입력하는 동안 자동 완성을 제공하며, 현재 문맥에 맞는 스마트 제안까지 보여줍니다. 또한 코드의 객체를 클릭해 해당 클래스의 전체 정의와 지원하는 속성을 확인할 수 있습니다.
* <img src="https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-2c1650edc9dbc881f65cd788d7c8ccfa2c27575c%2Fcursor-icon.png?alt=media" alt="Cursor" data-size="line"> **Cursor AI**: 다운로드하세요 [여기](https://www.cursor.com/). AI가 통합된 강력한 코드 편집기입니다. 코드를 작성하는 데 도움이 되도록 여러 AI 모델을 선택할 수 있으며, 모두 무료입니다. AI 어시스턴트는 입력할 때 자동 완성만 하는 것이 아니라, 큰 코드베이스를 리팩터링하고, 문서를 작성하는 등 다양한 작업도 요청할 수 있습니다.

{% hint style="info" %}
**💡 팁**: Cursor, OpenDCL, Claude Code 같은 AI 어시스턴트를 사용해 일반 언어 설명만으로 전체 씬을 만들 수 있습니다. TypeScript 경험은 필요하지 않습니다. 다음을 참조하세요: [AI와 함께하는 바이브 코딩](/creator/content-creator-ko/sdk7/getting-started/vibe-coding.md) 시작하려면.
{% endhint %}

## 지원되는 언어 및 구문

Decentraland는 [TypeScript(.ts)](https://www.typescriptlang.org/docs/handbook/jsx.html) 씬을 작성하는 기본 언어로 사용합니다.

TypeScript는 JavaScript의 상위 집합이므로 JavaScript에 익숙하다면 거의 같다고 느낄 수 있지만, TypeScript에는 타입 선언이 포함됩니다. 타입 선언 덕분에 자동 완성과 더 나은 디버깅 힌트 같은 기능을 사용할 수 있어 개발 시간을 단축하고 더 견고한 코드베이스를 만들 수 있습니다. 이러한 기능은 모두 긍정적인 개발자 경험을 만드는 핵심 요소입니다.

씬이 빌드되면, 작성한 TypeScript 코드는 더 가볍게 만들기 위해 최소화된 JavaScript로 컴파일됩니다. TypeScript의 원본 소스 코드는 서버에 업로드되지 않으며, 컴파일된 JavaScript 버전만 업로드됩니다.

### 다른 언어

TypeScript 대신 다른 도구나 언어를 사용해 JavaScript로 컴파일할 수 있습니다. 단, 컴파일된 스크립트는 scene의 `main` 씬의 `scene.json` 파일(기본값으로 *bin/index.js*). 제공되는 모든 타입 선언은 TypeScript로 작성되어 있으며, 다른 언어와 트랜스파일러는 공식적으로 지원되지 않습니다.

## 씬

LAND에 배포하는 콘텐츠를 **씬**. 씬은 3D 콘텐츠를 렌더링하는 상호작용 프로그램으로, 게임, 인터랙티브 경험, 미술관 등 원하는 무엇이든 될 수 있습니다!

씬은 Decentraland의 가상 LAND에 배포됩니다. LAND는 Ethereum 스마트 계약에서 유지되는 희소하고 대체 불가능한 자산입니다. 단일 **구획**, 즉 16미터 x 16미터 크기의 LAND 구획 하나나 인접한 여러 구획에 배포할 수 있습니다.

플레이어가 Decentraland를 방문하면, 맵을 따라 걸어갈 때 각 씬의 콘텐츠를 다운로드하고 렌더링합니다. 씬에서 멀어지면 해당 씬을 언로드합니다.

CLI에서 미리보기를 실행하여 자신의 컴퓨터에서 씬을 로컬로 실행할 수도 있습니다.

## 엔티티와 컴포넌트

Decentraland의 3차원 씬은 [Entity-Component-System](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system) 아키텍처를 기반으로 하며, 씬의 모든 것은 *엔티티*입니다. 엔터티에는 *컴포넌트*가 있으며, 각 컴포넌트는 속한 엔터티에 특정 속성을 제공합니다. 문 엔터티에는 적어도 Transform 컴포넌트(위치, 회전, 크기를 설정함)와 모양을 제공하는 다른 컴포넌트가 있을 가능성이 큽니다. 컴포넌트는 단지 데이터를 저장하는 장소일 뿐이며, 그 자체로 어떤 동작도 수행하지 않습니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-ee29a02358e859a30079072e8da958b899aea659%2Fecs-components-new%20\(1\).png?alt=media)

```ts
export function main() {
	// 엔티티 생성
	const door = engine.addEntity()

	// Transform 컴포넌트로 엔티티에 위치를 부여
	Transform.create(door, {
		position: Vector3.create(5, 1, 5),
	})

	// GltfContainer 컴포넌트로 엔티티에 보이는 형상을 부여
	GltfContainer.create(door, {
		src: 'assets/models/door.glb',
	})
}
```

엔터티는 트리 구조를 이루도록 다른 엔터티 안에 중첩될 수 있습니다. 웹 개발에 익숙하다면, 엔터티를 DOM 트리의 요소로, 컴포넌트를 이러한 각 요소의 속성으로 생각하면 이해하기 쉬울 것입니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-8b6c8cd679f648a41400eb6f29889cd09ede8947%2Fecs-nested-entities-new%20\(1\).png?alt=media)

엔터티는 추상적인 개념입니다. 엔터티는 단지 여러 컴포넌트를 그룹화하기 위한 참조로 사용되는 ID일 뿐입니다.

다음 [엔티티와 컴포넌트](/creator/content-creator-ko/sdk7/architecture/entities-components.md) 이 두 개념과 Decentraland 씬에서 어떻게 사용되는지에 대한 자세한 설명은 다음을 참조하세요.

### 사용자 정의 컴포넌트

기본 컴포넌트 집합(예: `Transform`, `GltfContainer`, `재질`, 등)은 엔진에 의해 해석되며, 엔터티가 어떻게 보이는지, 위치는 어떤지, 소리를 내는지 등에 직접적인 영향을 미칩니다.

또한 다음을 정의할 수 있습니다: *커스텀 컴포넌트* 씬의 메커니즘에 유용할 수 있는 데이터를 저장하기 위해 컴포넌트를 정의할 수 있습니다. 엔진은 이러한 컴포넌트의 값이 무엇을 의미하는지 해석할 수 없으며, 씬이 렌더링되는 방식에도 직접적인 영향을 주지 않습니다. 하지만 씬 코드에서 이 값들을 감시하고 반응하는 로직을 작성할 수 있습니다. 예를 들어, 문의 열림/닫힘 상태를 추적하는 사용자 정의 "doorState" 컴포넌트를 정의할 수 있습니다. 이 경우 이 컴포넌트는 이 상태를 추적하는 값을 저장하는 장소에 불과합니다. 씬에서 문이 열리고 닫히는 것을 보려면, 이 값을 사용해 문의 회전에 영향을 주는 로직을 별도로 구현해야 합니다. 엔진이 해석할 수 있는 `Transform` 컴포넌트의 값을 사용합니다.

다음 [사용자 지정 컴포넌트](/creator/content-creator-ko/sdk7/architecture/custom-components.md) 을(를) 참조하세요.

### 이름으로 엔터티 가져오기

Creator Hub의 Scene Editor에서 드래그 앤 드롭하여 추가한 엔터티도 코드로 접근하여 추가 편집하거나 동작을 추가할 수 있습니다.

다음을 사용하세요 `engine.getEntityOrNullByName()` 엔터티를 가져오려면 Scene Editor UI에서 엔터티에 할당한 이름을 전달합니다. 각 엔터티는 고유한 이름을 가져야 합니다.

```ts
function main() {
	const door = engine.getEntityOrNullByName('door3')
}
```

그런 다음 해당 엔터티에 새 컴포넌트를 추가하거나, 기존 컴포넌트를 수정하거나, 복제하거나, 삭제하는 등 원하는 작업을 할 수 있습니다.

다음 [이름으로 엔터티 가져오기](/creator/content-creator-ko/sdk7/architecture/entities-components.md#get-an-entity-by-name) 을(를) 참조하세요.

엔터티가 [스마트 아이템](/creator/content-creator-ko/scene-editor/interactivity/smart-items.md)이라면, 해당 **동작** 를 호출하거나 해당 **트리거** 에 코드로 구독할 수도 있습니다. 다음을 참조하세요: [참조 항목](/creator/content-creator-ko/scene-editor/extend-with-code/reference-items.md).

## 시스템

엔터티와 컴포넌트는 씬의 객체에 대한 정보를 저장하는 장소입니다. *시스템* 컴포넌트에 저장된 정보를 시간이 지나면서 변경하는 함수를 담고 있습니다.

시스템은 게임 로직을 구현하는 곳으로, 게임 루프의 매 틱마다 주기적으로 업데이트하거나 확인해야 하는 작업을 수행합니다.

시스템은 다음을 따르며 매 틱마다 한 번(초당 최대 30회) 호출되는 순수하고 단순한 함수입니다: [*업데이트 패턴*](http://gameprogrammingpatterns.com/update-method.html).

```ts
// 기본 시스템
function mySystem() {
	console.log('내 시스템이 실행 중입니다')
}

engine.addSystem(mySystem)

// dt가 있는 시스템
function mySystemDT(dt: number) {
	console.log('마지막 프레임 이후 시간:  ', dt)
}

engine.addSystem(mySystemDT)
```

하나의 씬에는 동시에 0개 또는 여러 개의 시스템이 실행될 수 있습니다. 시스템은 씬이 진행되는 동안 서로 다른 시점에 켜거나 끌 수 있습니다. 일반적으로는 독립적인 동작을 별도의 시스템으로 분리하는 것이 좋습니다.

다음 [시스템](/creator/content-creator-ko/sdk7/architecture/systems.md) 씬에서 시스템이 어떻게 사용되는지에 대한 자세한 내용은 다음을 참조하세요.

### 게임 루프

이 [게임 루프](http://gameprogrammingpatterns.com/game-loop.html) Decentraland 씬 코드의 핵심입니다. 일정한 간격으로 코드의 일부를 반복 실행하며 다음을 수행합니다:

* 플레이어 입력을 수신합니다
* 씬을 업데이트합니다
* 씬을 다시 렌더링합니다

대부분의 전통적인 소프트웨어 프로그램에서는 모든 이벤트가 플레이어의 동작에 의해 직접 트리거됩니다. 플레이어가 버튼을 클릭하거나 메뉴를 열기 전까지는 프로그램 상태의 어떤 것도 바뀌지 않습니다.

하지만 인터랙티브 환경과 게임은 다릅니다. 씬의 모든 변화가 반드시 플레이어의 행동으로 인해 발생하는 것은 아닙니다. 씬에는 스스로 움직이는 애니메이션 오브젝트나, 자체 AI를 가진 NPC가 있을 수도 있습니다. 일부 플레이어 동작은 완료되는 데 여러 틱이 필요할 수도 있는데, 예를 들어 문을 여는 데 1초가 걸린다면 문이 움직이는 동안 회전값을 약 30번에 걸쳐 점진적으로 업데이트해야 합니다.

루프를 한 번 반복하는 각 과정을 *틱*. Decentraland 씬은 가능한 경우 초당 30틱으로 렌더링됩니다. 기기가 각 틱을 렌더링하는 데 어려움을 겪으면 업데이트 빈도가 낮아질 수 있습니다.

각 틱마다 씬이 업데이트되고, 그다음 업데이트된 값을 바탕으로 씬이 다시 렌더링됩니다.

Decentraland 씬에서는 명시적으로 선언된 게임 루프가 있는 것이 아니라, [시스템](/creator/content-creator-ko/sdk7/architecture/systems.md) 씬의

씬의 컴파일과 렌더링은 백엔드에서 수행되므로, 씬을 개발하는 동안 이를 직접 처리할 필요가 없습니다.

## 컴포넌트 쿼리하기

할 수 있습니다 [컴포넌트 쿼리](/creator/content-creator-ko/sdk7/architecture/querying-components.md) 다음 메서드로 `engine.getEntitiesWith(...components)` 특정 컴포넌트를 가진 씬의 모든 엔티티를 추적할 수 있습니다.

일반적으로 다음 안에서 컴포넌트를 쿼리하는 것이 좋습니다: [시스템](/creator/content-creator-ko/sdk7/architecture/systems.md), 그런 다음 반환된 각 엔터티를 순회하며 각각에 동일한 작업 집합을 수행합니다.

게임 루프의 매 틱마다 씬의 모든 엔터티를 반복하려고 하면 성능에 큰 부담이 될 수 있습니다. 쿼리에서 반환된 엔터티만 참조하면 관련 있는 것들만 처리하게 됩니다.

```ts
// 시스템 정의
function boxHeightSystem(dt: number) {
	// MeshRenderer와 Transform 컴포넌트를 모두 포함하는 엔터티를 쿼리
	for (const [entity] of engine.getEntitiesWith(MeshRenderer, Transform)) {
		const transform = Transform.get(entity)
		console.log('상자의 높이:  ', transform.position.y)
	}
}

// 시스템을 엔진에 추가
engine.addSystem(boxHeightSystem)
```

## 장면 수명 주기

코드의 줄을 `index.ts`에 직접 작성하기 시작하면, 코드에 중요한 맥락이 빠질 수 있습니다. 예를 들어 플레이어 엔터티에 대한 정보나 Creator Hub에서 드래그 앤 드롭으로 추가한 엔터티에 대한 정보가 없을 수 있습니다. 코드의 해당 줄이 읽히는 시점에는 그런 것들이 아직 로드되지 않았기 때문입니다.

그런 상황을 피하려면, 씬의 초기 로딩 코드를 항상 다음을 사용해 작성하는 것이 권장됩니다: `main()` 함수(다음의 `index.ts` 파일)을 엔트리포인트로 사용하세요. 이 함수는 씬의 초기 컨텍스트가 모두 로드된 후에만 실행되며, 여기에는 Scene Editor UI를 통해 추가된 모든 항목이 포함됩니다.

다음 밖에서 코드를 작성할 수 있습니다: `main()` 함수인 경우:

* 코드가 다음에 의해 간접적으로 호출되는 경우 `main()`
* 코드가 시스템을 정의하거나 엔진에 시스템을 추가하는 경우
* 코드가 다음 안에 있는 경우 [비동기 함수](/creator/content-creator-ko/sdk7/programming-patterns/async-functions.md)

{% hint style="warning" %}
**📔 참고**: async 함수나 시스템 안의 코드가 처음 실행될 때는 씬의 모든 것이 이미 제대로 초기화되어 있습니다.

[사용자 정의 컴포넌트](/creator/content-creator-ko/sdk7/architecture/custom-components.md) 정의는 예외이며, 이는 항상 다음 밖에 작성해야 합니다: `main()` 함수, 별도의 파일에 작성해야 합니다. 이들은 다음 전에 해석되어야 합니다: `main()` 실행됩니다.
{% endhint %}

## 변경 가능성

컴포넌트의 변경 가능한 버전 또는 변경 불가능한(읽기 전용) 버전을 선택해서 다룰 수 있습니다.  `.get()` 컴포넌트의 get 함수는 해당 컴포넌트의 변경 불가능한 버전을 반환합니다. 값은 읽을 수 있지만 속성은 변경할 수 없습니다.

이 `.getMutable()` getMutable 함수는 값을 변경할 수 있는 컴포넌트 표현을 반환합니다. 컴포넌트를 변경할 계획일 때만 변경 가능한 버전을 사용하세요. 변경 불가능한 버전을 다루면 성능이 크게 향상됩니다.

```ts
// 변경 불가능한 버전 가져오기(읽기 전용)
const immutableTransform = Transform.get(myEntity)

// 다음은 작동하지 않습니다:
// \timmutableTransform.position.y = 2

const mutableTransform = Transform.getMutable(myEntity)

// 다음은 엔터티의 위치를 변경합니다
mutableTransform.position.y = 2
```

다음 [변경 가능한 데이터](/creator/content-creator-ko/sdk7/programming-patterns/mutable-data.md) 자세한 내용은.

## 전체를 종합하면

이 *엔진* 는 다음 사이에 있는 것입니다: *엔티티*, 그리고 *컴포넌트* 한편으로는 *시스템* 다른 한편으로는

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-de62a18d51b28bebd55c86e8ef5a8a783467ae62%2Fecs-big-picture%20\(1\).png?alt=media)

씬의 컴포넌트에 저장된 모든 값은 그 시점의 씬 상태를 나타냅니다. 게임 루프의 매 틱마다 엔진은 각 시스템의 함수를 실행하여 컴포넌트에 저장된 값을 업데이트합니다.

모든 시스템이 실행된 후에는 각 엔터티의 컴포넌트가 새로운 값을 갖게 됩니다. 엔진이 씬을 렌더링할 때 이 새로 업데이트된 값을 사용하며, 플레이어는 엔터티가 새로운 상태에 맞게 바뀌는 것을 보게 됩니다.

```ts
export function main() {
	// 엔티티 생성
	const cube = engine.addEntity()

	// Transform 컴포넌트로 엔티티에 위치를 부여
	Transform.create(cube, {
		position: Vector3.create(5, 1, 5),
	})

	// MeshRenderer 컴포넌트를 통해 엔터티에 보이는 모양을 부여
	MeshRenderer.setBox(cube)
}

// 시스템 정의
function rotationSystem(dt: number) {
	// MeshRenderer와 Transform 컴포넌트를 모두 포함하는 엔터티를 쿼리
	for (const [entity] of engine.getEntitiesWith(MeshRenderer, Transform)) {
		const transform = Transform.getMutable(entity)
		transform.rotation = Quaternion.multiply(
			transform.rotation,
			Quaternion.fromAngleAxis(dt * 10, Vector3.Up())
		)
	}
}

// 시스템을 엔진에 추가
engine.addSystem(rotationSystem)
```

위 예시에서는 `큐브` 엔터티와 `rotationSystem` 시스템이 엔진에 추가됩니다. 해당 `큐브` 엔터티에는 `Transform`, 그리고 a `MeshRenderer` 컴포넌트가 있습니다. 게임 루프의 매 틱마다 `rotationSystem` 시스템이 호출되고, 다음의 회전 값을 변경합니다: `Transform` 컴포넌트의 `큐브` 엔티티를 사용해 플레이어 카메라 위치에서 앞으로 레이를 추적합니다.

위 코드의 대부분은 씬을 로드할 때 한 번만 실행된다는 점에 유의하세요. 예외는 `rotationSystem` 시스템으로, 게임 루프의 매 틱마다 호출됩니다.

## 씬 분리

여러분의 씬은 엔진(즉, 메인 스레드)과 같은 컨텍스트에서 실행되지 않습니다. 우리는 SDK가 렌더링 엔진과 완전히 분리되도록 만들었습니다. 안전성과 성능상의 이유 모두를 위해 이렇게 설계했습니다.

이러한 분리 때문에 씬 코드에서는 DOM이나 `window` 객체에 접근할 수 없으므로 플레이어의 브라우저나 지리적 위치 같은 데이터에는 접근할 수 없습니다.

이 분리는 RPC 프로토콜을 사용해 이루어지며, 이 프로토콜은 클라이언트의 일부를 씬 렌더링과 이벤트 제어만 담당하도록 할당합니다.

통신 프로토콜도 추상화했습니다. 이를 통해 씬을 WebWorker에서 로컬로 실행할 수 있습니다.

개발자가 엔진 내부에 개입하거나 엔진 안에 무엇이 있는지 알 필요조차 없도록 하고 싶습니다. Decentraland 맵 전체에서 플레이어에게 일관된 경험을 보장해야 하며, 그런 "낮은" 수준에서는 실수가 더 쉽게 발생합니다.

이러한 분리는 이웃 씬이 플레이어가 다른 사람의 씬에 있는 동안 경험을 방해하는 것을 막기 위해서도 중요합니다. 플레이어는 주변의 여러 씬을 동시에 로드한 상태일 수 있으며, 각 씬은 자체 코드를 실행합니다. 일부 동작(예: 외부 링크 열기 또는 플레이어 이동)은 씬이 로드되어 있더라도 플레이어가 그 특정 씬 위에 서 있을 때만 허용되며, 플레이어가 밖에 있으면 허용되지 않습니다.

## 트리 셰이킹

TypeScript의 소스 코드를 최소화된 JavaScript의 컴파일된 코드로 변환할 때, 이 과정은 다음을 수행합니다: [트리 셰이킹](https://en.wikipedia.org/wiki/Tree_shaking) 실제로 사용되는 코드 부분만 변환되도록 보장합니다. 이렇게 하면 씬의 최종 코드를 가능한 한 가볍게 유지하는 데 도움이 됩니다. 외부 라이브러리를 사용할 때 특히 유용한데, 보통 이런 라이브러리에는 사용되지 않는 기능이 많아 그대로 두면 씬이 불필요하게 커지기 때문입니다.

트리 셰이킹의 결과로, 씬에서 실행되게 하려는 코드는 어떤 식으로든 코드의 엔트리 포인트에서 참조되어야 합니다: `main()` 함수 on `index.ts`. 시스템은 또한 다음에서 엔진에 추가할 수도 있습니다: `index.ts` 파일에서 참조하지 않고 `main()`. 이러한 파일에서 명시적 또는 간접적으로 참조되지 않은 코드는 씬에 포함되지 않습니다.

예를 들어, 다음과 같은 이름의 파일이 있다고 가정해 보겠습니다: `extraContent.ts` 다음과 같은 내용이라면 엔터티는 렌더링되지 않고 시스템도 실행을 시작하지 않습니다:

```ts
// extraContent.ts

const myEntity = engine.addEntity()
Transform.create(myEntity, {
	position: { x: 8, y: 0, z: 8 },
})
MeshRenderer.setBox(myEntity)

function mySystem(dt: number) {
	console.log('시스템 실행 중')
}

engine.addSystem(mySystem)
```

씬의 일부로 실행되게 하려면 다음에서 참조할 수 있습니다: `index.ts` 다음과 같은 방식으로:

```ts
// extraContent.ts에서

export function addEntities() {
	const myEntity = engine.addEntity()
	Transform.create(myEntity, {
		position: { x: 8, y: 0, z: 8 },
	})
	MeshRenderer.setBox(myEntity)
}

export function mySystem(dt: number) {
	console.log('시스템 실행 중')
}

/////////////////////////////

// index.ts에서

import { addEntities, mySystem } from './extraContent'

export function main() {
	addEntities()
}

engine.addSystem(mySystem)
```

이 규칙의 예외는 사용자 정의 컴포넌트 정의입니다. 이는 다음을 통해 접근해서는 안 됩니다: `main()` function 엔트리포인트를 통해서는 안 되는데, 이는 다른 모든 것보다 먼저 해석되어야 하기 때문입니다.

## 가져오기

씬에서 사용되는 모든 함수, 객체, 컴포넌트 및 기타 요소는 사용하려면 각 파일로 가져와야 합니다. 이는 다음의 결과입니다: [트리 셰이킹](#tree-shaking), 전체 SDK를 패키징하는 대신 씬이 사용하는 부분만 포함하기 때문입니다.

문서 전반의 스니펫은 깔끔하게 보이도록 각 파일 맨 앞의 import 줄을 생략하지만, 제대로 작동하려면 이를 씬에 추가해야 합니다.

VS Studio Code를 사용해 씬을 작성할 때는, 작성 중 스마트 자동 완성 옵션이 import 처리를 알아서 해주므로 이를 따로 신경 쓸 필요가 없어야 합니다.

하지만 스니펫을 씬에 붙여넣으면 해당 파일로 import되지 않은 일부 요소가 빨간색으로 표시될 가능성이 큽니다. 이를 수정하려면:

* 밑줄이 그어진 각 단어를 클릭합니다
* 줄 왼쪽의 전구 아이콘을 클릭합니다
* 선택하세요 **가져오기 추가**
* 파일 맨 앞에 import 줄이 추가됩니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-7a9b5a49dd3ff062e5609e6205f2a41c55d9ea55%2Fimports.png?alt=media\&token=7d6f1e13-e683-422f-82ad-dffcf105f362)

가져와야 할 항목이 많다면 다음도 선택할 수 있습니다: **누락된 가져오기를 모두 추가** 같은 드롭다운에서.

요소가 사용되는 모든 파일에 대해 import해야 한다는 점에 유의하세요.

VS Studio Code는 import의 올바른 경로를 스스로 해결할 수 있어야 합니다. 어떤 이유로 문제가 있다면, 파일 맨 앞에 다음의 빈 import 문을 붙여 넣는 것이 요령입니다. 그러면 VS Studio가 나머지를 처리할 수 있어야 합니다.

```ts
import {} from '@dcl/sdk/ecs'
import {} from '@dcl/sdk/math'
```

## SDK 버전

새로운 씬을 개발할 때는 다음을 기본으로 사용합니다: `@latest` 안정적인 SDK 릴리스

다음을 설치할 수 있습니다: `@next` 최신 안정 릴리스에는 아직 포함되지 않은 예정된 기능을 활용하거나 미리 보고 싶다면 SDK 릴리스를 사용할 수 있습니다.

그러려면 다음을 엽니다: `package.json` 씬의 파일을 열고 다음 줄을 변경하세요:

```json
  "devDependencies": {
    "@dcl/js-runtime": "next",
    "@dcl/sdk": "next"
  },
```

그런 다음 씬 프로젝트 폴더에서 다음 명령을 실행하세요:

```
npm i
```

다음 [종속성 관리](/creator/content-creator-ko/sdk7/libraries/manage-dependencies.md) 자세한 내용은.

{% hint style="warning" %}
**📔 참고**: @next 버전은 때때로 문제가 있을 수 있다는 점을 기억하세요. 새 기능의 구문과 이름은 안정 버전으로 출시되기 전에 변경될 수 있습니다.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/creator/content-creator-ko/sdk7/getting-started/coding-scenes.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
