> 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/architecture/entities-components.md).

# 엔티티 및 컴포넌트

Decentraland 씬의 엔티티와 컴포넌트에 대한 필수 사항을 알아봅니다

Decentraland 장면은 다음을 중심으로 구성됩니다 [*엔티티*, *컴포넌트* 과 *시스템*](https://en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system). 이는 여러 게임 엔진의 아키텍처에서 사용되는 일반적인 패턴으로, 쉬운 조합성과 확장성을 가능하게 합니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-de62a18d51b28bebd55c86e8ef5a8a783467ae62%2Fecs-big-picture.png?alt=media\&token=0d7a02a2-955a-44ed-ae77-5df99c49e530)

## 개요

*엔터티* 은 Decentraland 장면에서 모든 것을 구성하는 기본 단위입니다. 장면의 보이거나 보이지 않는 모든 3D 오브젝트와 오디오 플레이어는 각각 엔티티가 됩니다. 엔티티는 컴포넌트에서 참조할 수 있는 ID에 불과합니다. 엔티티 자체에는 고유한 속성이나 메서드가 없으며, 단지 여러 컴포넌트를 함께 묶는 역할만 합니다.

*컴포넌트* 엔티티의 특성을 정의합니다. 예를 들어, `Transform` 컴포넌트는 엔티티의 좌표, 회전, 크기를 저장합니다.  `MeshRenderer` 컴포넌트는 장면에 렌더링될 때 엔티티에 보이는 형태(큐브나 구 같은)를 부여하며,  `재질` 컴포넌트는 엔티티에 색상이나 텍스처를 부여합니다. 또한 장면에 필요한 데이터를 담기 위해 커스텀 컴포넌트를 만들 수 있습니다. 예를 들어 커스텀  `체력` 는 엔티티의 남은 체력 값을 저장할 수 있으며, 게임에서 플레이어가 아닌 적을 나타내는 엔티티에 추가할 수 있습니다.

웹 개발에 익숙하다면, 엔티티를 다음에 해당하는 개념으로 생각하면 됩니다: *요소* 를 *DOM* 트리, 그리고 컴포넌트는 *속성* 의 속성으로 생각하면 됩니다.

의 [Creator Hub의 Scene Editor](/creator/content-creator-ko/scene-editor/get-started/about-editor.md), 엔티티를 선택하면 해당 엔티티에 속한 컴포넌트를 볼 수 있습니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-2ffe3126d7a92824658497ed2664fcfcc28ce16a%2Fcomponents-example.png?alt=media\&token=543af76c-1c78-4a46-8238-d22a92fe16cc)

{% hint style="warning" %}
**📔 참고**: 이전 SDK 버전에서는 엔티티가 *객체* 로 인스턴스화되었고, 함수를 추가하도록 확장할 수 있었습니다. SDK 7.0 버전부터는 엔티티가 단순한 ID만 됩니다. 이 구조는 다음의 원칙에 더 잘 부합합니다. [데이터 지향 프로그래밍](/creator/content-creator-ko/sdk7/architecture/data-oriented-programming.md) 이며, 장면 성능 향상에 도움이 될 수 있습니다.
{% endhint %}

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-ee29a02358e859a30079072e8da958b899aea659%2Fecs-components-new.png?alt=media\&token=c9ecdd6f-77bf-4b98-80aa-2b806c3e8949)

다음과 같은 컴포넌트는 `Transform`, `재질` 또는 다음 중 어느 하나 *형상* 컴포넌트는 장면의 렌더링과 밀접하게 연결되어 있습니다. 이러한 컴포넌트의 값이 변경되면, 그것만으로도 엔진이 다음 프레임에서 장면을 렌더링하는 방식을 바꾸기에 충분합니다.

엔진은 장면의 중심에 자리하며 다른 모든 부분을 관리하는 부분입니다. 어떤 엔티티가 렌더링될지, 플레이어가 그것들과 어떻게 상호작용할지를 결정합니다. 또한 다음에서 어떤 함수가 [시스템](/creator/content-creator-ko/sdk7/architecture/systems.md) 실행되는지와 그 시점도 조정합니다.

컴포넌트는 참조하는 엔티티에 대한 데이터를 저장하기 위한 것입니다. 이 데이터는 저장만 할 수 있고, 컴포넌트 자체가 이 데이터를 수정할 수는 없습니다. 컴포넌트 값의 모든 변경은 다음에 의해 수행됩니다. [시스템](/creator/content-creator-ko/sdk7/architecture/systems.md). 시스템은 컴포넌트와 엔티티 자체와 완전히 분리되어 있습니다. 엔티티와 컴포넌트는 다음이 무엇인지에 구애받지 않습니다. *시스템* 이것들에 작용하는 시스템이 무엇인지.

## 엔티티와 컴포넌트의 구문

아래 예시는 기본 엔티티와 컴포넌트를 선언하고 구성하는 몇 가지 기본 작업을 보여줍니다.

```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',
	})
}
```

{% hint style="warning" %}
**📔 참고**: 이전 SDK 버전에서는 렌더링을 시작하려면 엔티티를 엔진에 수동으로 추가해야 했습니다. SDK 7 버전부터는 컴포넌트가 할당되는 즉시 엔티티가 암묵적으로 엔진에 추가됩니다.
{% endhint %}

컴포넌트가 생성되면 항상 부모 엔티티에 할당됩니다. 그런 다음 컴포넌트의 값이 엔티티에 영향을 줍니다.

{% hint style="info" %}
**💡 팁**: 엔티티를 하나씩 만드는 대신, 다음에서 엔티티와 컴포넌트의 전체 트리를 한 번에 생성할 수 있습니다. [컴포지트](/creator/content-creator-ko/sdk7/architecture/composites.md) 파일을 추가할 수 있습니다.
{% endhint %}

## 엔티티 제거

엔진에서 엔티티를 제거하려면 다음을 사용합니다: `engine.removeEntity()`. 이 함수는 다음을 반환합니다. `불리언`: `true` 엔티티가 제거되었다면 `false` 제거가 거부되었다면

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

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

	// 엔티티 제거
	const removed = engine.removeEntity(door)
	console.log('Entity removed:', removed) // true
}
```

제거된 엔티티에 자식 엔티티가 있다면, 이들의 부모는 기본값으로 다시 변경됩니다. `engine.RootEntity` 이 엔티티는 장면의 기본 위치에 배치되며, 스케일은 다음과 같습니다. *1*.

### 렌더러가 예약한 엔티티

일부 엔티티 ID는 원격 플레이어 아바타를 위해 렌더러가 예약합니다. 이러한 엔티티는 제거할 수 없습니다. 다음을 호출하면 `engine.removeEntity()` 렌더러 예약 엔티티에 대해 호출하면 다음을 반환합니다 `false` 그리고 모든 컴포넌트는 그대로 둡니다.

이 [이름이 지정된 예약 엔티티](#reserved-entities) (`engine.RootEntity`, `engine.PlayerEntity`, `engine.CameraEntity`)는 특별한 경우입니다: `engine.removeEntity()` 여전히 다음을 반환하지만 `false` 이들에 대해서는 (ID가 절대 해제되지 않음) 하지만 그들의 컴포넌트는 **는** 삭제됩니다. 즉, 자체 컴포넌트를 이들에서 지울 수 있습니다(예를 들어, 다음을 제거하는 것 `InputModifier` 다음에서 `engine.PlayerEntity`)는 가능하지만, 엔티티 ID 자체는 절대 해제되지 않습니다.

```ts
// 예약된 엔티티 제거 시도
const result = engine.removeEntity(engine.PlayerEntity)
console.log(result) // false — 엔티티 ID는 해제되지 않음
// 하지만 PlayerEntity에 있는 장면 자체의 컴포넌트는 삭제됨
```

예외적인 경우를 처리하려면 엔티티를 제거할 때 반환 값을 확인할 수 있습니다:

```ts
if (!engine.removeEntity(someEntity)) {
	console.log('Entity could not be removed (reserved)')
}
```

### 자식과 함께 엔티티 제거

엔티티와 그 모든 자식(그리고 그 자식의 자식들까지 재귀적으로)을 함께 제거하려면 다음을 사용합니다: `removeEntityWithChildren()` 헬퍼.

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

	// 자식 엔티티 생성
	const doorKnob = engine.addEntity()

	// 엔티티에 보이는 형상 부여
	GltfContainer.create(door, {
		src: 'models/door.glb',
	})
	GltfContainer.create(doorKnob, {
		src: 'models/doorKnob.glb',
	})

	// 부모
	Transform.create(doorKnob, {
		parent: door,
	})

	// 부모와 자식 모두 제거
	removeEntityWithChildren(engine, door)
}
```

{% hint style="warning" %}
**참고:** 렌더러가 예약한 엔티티가 트리의 어느 위치에 있든, `removeEntityWithChildren` 다른 모든 하위 엔티티는 제거하지만 예약된 엔티티는 그대로 둡니다. 예약된 엔티티의 `Transform.parent` 는 제거된 엔티티를 가리키게 됩니다. 이는 장면에서 예약된 엔티티를 장면 엔티티의 자식으로 둘 때만 발생하며, 흔한 경우는 아닙니다.
{% endhint %}

{% hint style="info" %}
**💡 팁**: 엔진에서 엔티티를 제거하는 대신, 나중에 지연 없이 다시 불러올 수 있도록 어떤 경우에는 보이지 않게 만드는 것이 더 나을 수 있습니다. 다음을 참조하세요: [보이지 않게 만들기](/creator/content-creator-ko/sdk7/3d/shape-components.md#make-invisible)
{% endhint %}

### 장면 뒤에서 엔티티 제거하기

엔티티는 컴포넌트에서 참조하는 ID일 뿐입니다. 따라서 엔티티를 제거한다는 것은 실제로는 이 엔티티를 참조하는 각 컴포넌트를 제거하는 것입니다. 엔티티의 모든 컴포넌트를 수동으로 제거하면 플레이어에게는 다음을 수행한 것과 동일하게 보입니다: `engine.removeEntity()`. 그러나, `engine.removeEntity()` 는 추가적인 내부 처리도 수행하여 엔티티 ID를 더 이상 사용하지 않음으로 표시하므로, 엔티티를 제거할 때 항상 권장되는 방법입니다.

## 중첩 엔티티

엔티티는 다른 엔티티를 자식으로 가질 수 있습니다. 덕분에 웹페이지의 HTML처럼 엔티티를 트리 구조로 배치할 수 있습니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-8b6c8cd679f648a41400eb6f29889cd09ede8947%2Fecs-nested-entities-new.png?alt=media\&token=847cb6ef-9cee-49ea-9894-b294e72341d2)

한 엔티티를 다른 엔티티의 부모로 설정하려면, 자식 엔티티에는 반드시 다음이 있어야 합니다: `Transform` 컴포넌트. 그런 다음 `parent` 필드에 부모 엔티티에 대한 참조를 설정할 수 있습니다.

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

	const childEntity = engine.addEntity()

	// 부모 설정
	Transform.create(childEntity, {
		parent: parentEntity,
	})
}
```

부모가 할당되면, 자식 엔티티에서 다음의 `parent` 필드를 통해 읽을 수 있습니다. `Transform` 컴포넌트를 추가해야 합니다.

```ts
// 엔티티에서 부모 가져오기
const parent = Transform.get(childEntity).parent
```

부모 엔티티에 다음이 있으면 `Transform` 컴포넌트가 위치, 크기 또는 회전에 영향을 주면 자식 엔티티도 영향을 받습니다. 위치나 회전 값은 더해지고, 크기 값은 곱해집니다.

부모나 자식 엔티티 중 하나에 다음이 없으면 `Transform` 컴포넌트, 다음 기본값이 사용됩니다.

* 다음의 경우, **위치**, 부모의 중심은 *0, 0, 0*
* 다음의 경우, **회전** 부모의 회전은 쿼터니언 *0, 0, 0, 1* (오일러 각과 동일한 *0, 0, 0*)
* 다음의 경우, **크기**, 부모의 크기는 다음과 같은 것으로 간주됩니다. *1*. 부모의 크기 조정은 스케일과 위치에 비례하여 영향을 줍니다.

shape 컴포넌트가 없는 엔티티는 장면에서 보이지 않습니다. 이런 엔티티는 여러 엔티티를 하나의 그룹으로 처리하고 배치하기 위한 래퍼로 사용할 수 있습니다.

자식 엔티티를 부모에서 분리하려면, 엔티티의 부모를 다음으로 지정할 수 있습니다: `engine.RootEntity`.

```ts
const mutableChildTransform = Transform.getMutable(childEntity)
mutableChildTransform.parent = engine.RootEntity
```

{% hint style="warning" %}
**📔 참고**: 다른 플레이어와 동기화되는 중첩 엔티티를 다룰 때는 다음을 사용합니다: `parentEntity()` 함수 대신 다음을 사용하세요: `parent` Transform의 엔티티를 사용하세요. 다음을 참조하세요: [부모가 연결된 엔티티](/creator/content-creator-ko/sdk7/networking/serverless-multiplayer.md#parented-entities)
{% endhint %}

Scene Editor의 왼쪽 패널에서 장면의 중첩 엔티티 전체 계층 구조를 볼 수 있습니다.

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-60929069a225f48ce0d6c94d9dce285ff875af10%2Fentity-tree-example.png?alt=media\&token=b2baf1b6-e035-4ae5-92fc-509628408f8d)

## ID로 엔티티 가져오기

장면의 모든 엔티티에는 고유한 번호가 있습니다 *id*. 이 ID를 바탕으로 엔진에서 특정 엔티티를 참조하는 컴포넌트를 가져올 수 있습니다.

```typescript
// Transform 컴포넌트 가져오기
Transform.get(1000 as Entity)
```

{% hint style="warning" %}
**📔 참고**: 다음 사이의 엔티티 ID는 *0* 과 *511* 플레이어 아바타, 기본 장면 등과 같은 고정 엔티티를 위해 엔진이 예약합니다.
{% endhint %}

예를 들어, 플레이어의 클릭이나 [레이캐스트](/creator/content-creator-ko/sdk7/interactivity/raycasting.md) 가 엔티티에 맞으면, 맞은 엔티티의 ID를 반환하며, 위 명령을 사용해 해당 ID와 일치하는 엔티티의 Transform 컴포넌트를 가져올 수 있습니다. 같은 방식으로 해당 엔티티의 다른 컴포넌트도 가져올 수 있습니다.

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

Scene Editor에서 드래그 앤 드롭으로 엔티티를 추가하면 각 엔티티에는 고유한 이름이 있습니다. 다음을 사용하세요: `engine.getEntityOrNullByName()` 함수를 사용해 코드에서 이러한 엔티티 중 하나를 참조할 수 있습니다. 장면 편집기 UI의 왼쪽 트리 뷰에 표시된 대로 엔티티 이름을 문자열로 전달하세요.

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

{% hint style="warning" %}
**📔 참고**: 반드시 다음만 사용하세요 `engine.getEntityOrNullByName()` 안에서 `main()` 함수 안에서, 또는 다음 이후에 실행되는 함수 안에서 `main()`, 또는 시스템에서 사용하세요. 이러한 맥락 밖에서 사용하면 Scene Editor UI에서 생성된 엔티티가 아직 인스턴스화되지 않았을 수 있습니다.
{% endhint %}

이 메서드로 가져온 엔티티에는 컴포넌트를 추가하거나 제거하고, 기존 컴포넌트의 값을 수정하거나, 엔진에서 엔티티를 제거하는 등 어떤 작업이든 자유롭게 수행할 수 있습니다.

```ts
function main() {
	// 엔티티 가져오기
	const door = engine.getEntityOrNullByName('door-3')
	// 엔티티가 존재하는지 확인
	if (door) {
		// 포인터 이벤트 콜백 추가
		pointerEventsSystem.onPointerDown(
			{
				entity: door,
				opts: { button: InputAction.IA_PRIMARY, hoverText: '열기' },
			},
			function () {
				// 문 열기
			}
		)
	}
}
```

Scene Editor UI를 통해 추가된 모든 엔티티에는 다음이 있습니다: `이름` 컴포넌트가 있으므로, 다음과 같이 모두 순회할 수 있습니다:

```ts
function main() {
	for (const [entity, name] of engine.getEntitiesWith(Name)) {
		console.log({ entity, name })
	}
}
```

## 컴포넌트 추가 또는 교체

각 엔티티는 같은 종류의 컴포넌트를 하나만 가질 수 있습니다. 예를 들어 이미 Transform이 있는 엔티티에 Transform을 할당하려고 하면 오류가 발생합니다.

이 오류를 방지하려면 다음을 사용할 수 있습니다: `.createOrReplace` 대신 `.create`. 이 명령은 같은 종류의 기존 컴포넌트가 있으면 이를 덮어쓰고, 없으면 다음과 같이 새 컴포넌트를 만듭니다: `.create`.

```ts
Transform.createOrReplace(door, {
	position: Vector3.create(5, 1, 5),
})
```

{% hint style="warning" %}
**📔 참고**: 다음은 `.createOrReplace` 컴포넌트를 만들기 전에 추가 검사를 수행하므로, 항상 다음을 사용하는 것이 더 성능이 좋습니다: `.create`. 추가하려는 것과 같은 컴포넌트가 엔티티에 이미 없다고 확신한다면, 다음을 사용하세요: `.create`.
{% endhint %}

## 엔티티에서 컴포넌트에 접근하기

엔티티의 다음을 사용해 컴포넌트에 접근할 수 있습니다: `.get()` 또는 `getMutable()` 함수들입니다.

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

	// 해당 엔티티에 컴포넌트를 생성하고 추가
	Transform.create(box)

	// 컴포넌트의 읽기 전용 버전 가져오기
	let transform = Transform.get(box)

	// 컴포넌트의 변경 가능한 버전 가져오기
	let transform = Transform.getMutable(box)
}
```

이 `get()` 함수는 컴포넌트에 대한 읽기 전용 참조를 가져옵니다. 이 참조로는 컴포넌트의 값을 변경할 수 없습니다.

컴포넌트의 값을 변경하려면 다음을 사용하세요: `getMutable()` 대신 함수를 사용합니다. 컴포넌트의 변경 가능한 버전에서 값을 바꾸면, 해당 컴포넌트가 속한 엔티티에 직접 영향을 줍니다.

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

{% hint style="warning" %}
**📔 참고**: 다음은 오직 `getMutable()` 컴포넌트 값을 실제로 변경할 경우에만 사용하세요. 그렇지 않으면 항상 다음을 사용하세요: `get()`. 이 방식은 다음 원칙을 따릅니다: [데이터 지향 프로그래밍](/creator/content-creator-ko/sdk7/architecture/data-oriented-programming.md), 그리고 장면 성능 향상에 크게 도움이 될 수 있습니다.
{% endhint %}

```ts
// 컴포넌트의 변경 가능한 버전 가져오기
let transform = Transform.getMutable(box)

// 컴포넌트 값 변경
transform.scale.x = 5
```

위 예시는 다음 값은 직접 수정합니다: *x* Transform 컴포넌트의 scale.

가져오려는 컴포넌트가 엔티티에 정말 있는지 확실하지 않다면 다음을 사용하세요: `getOrNull()` 또는 `getMutableOrNull()`.

{% hint style="warning" %}
**📔 참고**: 다음 사용은 피하세요 `getOrNull()` 또는 `getMutableOrNull()` 가능한 경우, 이러한 함수는 추가 검사를 포함하므로 다음보다 효율이 떨어집니다: `.get()` 과 `getMutable()`.
{% endhint %}

```ts
//  getOrNull
const transformOrNull = Transform.getOrNull(myEntity)

// getMutableOrNull
const mutableTransformOrNull = Transform.getMutableOrNull(myEntity)
```

가져오려는 컴포넌트가 엔티티에 존재하지 않으면:

* `get()` 과 `getMutable()` 오류를 반환합니다.
* `getOrNull()` 과 `getMutableOrNull()` 반환합니다 `Null`.

## 엔티티에서 컴포넌트 제거

엔티티에서 컴포넌트를 제거하려면 엔티티의 다음을 사용합니다: `deleteFrom()` 컴포넌트 타입의 메서드

```ts
Transform.deleteFrom(myEntity)
```

엔티티에 존재하지 않는 컴포넌트를 제거하려고 해도 이 작업은 오류를 발생시키지 않습니다.

{% hint style="warning" %}
**📔 참고**: 엔티티의 모든 컴포넌트를 한 번에 제거하려면 다음을 참조하세요: [이 섹션](#remove-entities)
{% endhint %}

## 컴포넌트 존재 여부 확인

엔티티가 특정 컴포넌트의 인스턴스를 가지고 있는지 다음을 사용해 확인할 수 있습니다: `has()` 함수입니다. 이 함수는 다음을 반환합니다: *true* 컴포넌트가 있으면 *false* 없으면 반환합니다. 이는 장면의 조건부 로직에서 매우 유용할 수 있습니다.

```ts
const hasTransform = Transform.has(myEntity)
```

{% hint style="info" %}
**💡 팁**: 또한 다음도 가능합니다 [컴포넌트 쿼리](/creator/content-creator-ko/sdk7/architecture/querying-components.md) 특정 컴포넌트나 특정 컴포넌트 집합을 가진 컴포넌트의 전체 목록을 가져올 수 있습니다. 장면의 모든 엔티티를 수동으로 순회하며 각 엔티티를 다음으로 확인하지 마세요: `has()`, 그 방법은 훨씬 비효율적입니다.
{% endhint %}

## 컴포넌트 변경 사항 확인

다음을 사용하세요 `onChange` 함수를 사용하면 특정 엔티티의 컴포넌트 값이 변경될 때마다 콜백 함수를 실행할 수 있습니다. 이는 어떤 컴포넌트에도 사용할 수 있으며, 코드를 읽기 쉽게 유지하는 데 매우 유용한 지름길입니다.

콜백 함수에는 컴포넌트의 새 상태를 담은 입력 매개변수를 포함할 수 있습니다.

```ts
Transform.onChange(cubeEntity, (newTransform) => {
	if (!newTransform) return
	console.log(
		'Cube position changed: ',
		newTransform.position,
		newTransform.rotation
	)
})

VisibilityComponent.onChange(cubeEntity, (newVisibilityComponent) => {
	if (!newVisibilityComponent) return
	console.log('Cube visibility changed: ', newVisibilityComponent.visible)
})
```

컴포넌트가 엔티티에서 제거되면 함수는 다음 입력으로 호출됩니다: `undefined`.

{% hint style="info" %}
**💡 팁**: `.onChange()` 함수는 SDK의 기본 컴포넌트와 다음 모두에서 작동합니다: [커스텀 컴포넌트](/creator/content-creator-ko/sdk7/architecture/custom-components.md) 제작자가 정의한 컴포넌트.
{% endhint %}

## 자식 엔티티 가져오기

부모 엔티티의 직접 자식인 모든 엔티티에 접근하려면 다음을 사용합니다: `getEntitiesWithParent`. 인수로 다음을 받습니다: `엔진` 와 `parent` 엔티티를 받고, 해당 엔티티를 부모로 가진 모든 엔티티의 목록을 반환합니다. 직접 자식만 반환하며, 손자 엔티티는 반환하지 않습니다.

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

const children = getEntitiesWithParent(engine, myEntity)
for (const child of children) {
   // 각 자식 엔티티 처리
}
```

대신 엔티티의 모든 하위 엔티티에 접근하려면, 얼마나 깊이 중첩되어 있든 상관없이 다음 함수를 사용합니다: `getComponentEntityTree()`. 계층 구조를 단계별로 수동으로 탐색하는 대신, 이 함수는 순회하기 쉬운 모든 하위 엔티티의 평평한 목록을 반환합니다. 또한 주어진 컴포넌트 또는 컴포넌트 목록을 가진 엔티티만 필터링합니다.

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

export function main() {
	// 중첩된 자식을 가진 부모 엔티티 생성
	const parentEntity = engine.addEntity()
	Transform.create(parentEntity, {
		position: Vector3.create(8, 0, 8),
	})

	// ... 부모에게 여러 자식과 손자가 있다고 가정

	// 부모 엔티티의 모든 하위 엔티티를 순회
	for (const descendantEntity of getComponentEntityTree(
		engine,
		parentEntity,
		Transform
	)) {
		// 각 하위 엔티티에 접근
		const transform = Transform.get(descendantEntity)
		console.log('Descendant position:', transform.position)
	}
}
```

이 `getComponentEntityTree` 함수는 세 개의 매개변수를 받습니다:

* `엔진`: 엔티티를 실행하는 엔진 인스턴스
* `엔티티`: 시작할 루트 엔티티
* `컴포넌트`: 필터링할 컴포넌트(일반적으로 `Transform` 공간 계층 구조용)

이 함수는 트리 구조의 각 하위 엔티티를 산출하는 제너레이터를 반환합니다. 지정된 컴포넌트를 가진 엔티티만 결과에 포함됩니다.

이를 다른 컴포넌트 검사와 결합하여 계층 구조에서 특정 엔티티를 찾을 수 있습니다:

```ts
// 특정 이름을 가진 모든 하위 엔티티 찾기
for (const descendantEntity of getComponentEntityTree(
	engine,
	parentEntity,
	Transform
)) {
	const name = Name.getOrNull(descendantEntity)
	if (name && name.value === 'targetEntity') {
		console.log('Found target entity:', descendantEntity)
	}
}
```

## 예약된 엔티티

일부 엔티티 ID는 모든 장면에 존재하는 특수 엔티티를 위해 예약되어 있습니다. 다음 별칭으로 접근할 수 있습니다:

* `engine.RootEntity`
* `engine.PlayerEntity`
* `engine.CameraEntity`

{% hint style="warning" %}
**📔 참고**: 초기화되기 전에 이러한 엔티티를 참조하지 마세요. 이 문제를 피하려면 다음에서 이러한 엔티티를 참조하세요: `main()` 함수 또는 시스템에서.
{% endhint %}

## 루트 엔티티

장면의 모든 엔티티는 다음의 자식입니다: `engine.RootEntity`, 직접적 또는 간접적으로.

이 엔티티에는 Transform 컴포넌트가 없지만, 다음과 같은 더 전역적인 설정을 나타내는 여러 컴포넌트를 처리하는 데 사용됩니다: [스카이박스 제어](/creator/content-creator-ko/sdk7/interactivity/skybox-control.md), [커서 위치](/creator/content-creator-ko/sdk7/interactivity/user-data.md#check-the-players-cursor-position)또는 [화면 크기](/creator/content-creator-ko/sdk7/2d-ui/ui-positioning.md#responsive-ui-size).

## 플레이어 엔티티

이 `engine.PlayerEntity` 엔티티는 플레이어의 아바타를 나타냅니다.

플레이어의 다음을 가져오세요: `Transform` 컴포넌트를 가져와 플레이어의 현재 위치와 회전을 확인하세요. 다음을 참조하세요: [사용자 데이터](/creator/content-creator-ko/sdk7/interactivity/user-data.md). 플레이어의 Transform은 읽기 전용이며, 수정하려면 다음을 사용합니다: `movePlayerTo()` 함수, [자세히 알아보기](/creator/content-creator-ko/sdk7/interactivity/avatars/move-player.md).

이 엔티티의 자식으로 설정하여 플레이어에 오브젝트를 첨부할 수도 있지만, 다음이 [플레이어에 첨부](/creator/content-creator-ko/sdk7/3d/entity-positioning.md#attach-an-entity-to-an-avatar) 대개 더 나은 옵션입니다.

## 카메라 엔티티

이 `engine.CameraEntity` 엔티티는 플레이어의 카메라를 나타냅니다.

카메라의 다음을 가져오세요: `Transform` 컴포넌트를 가져와 카메라의 위치와 회전을 확인하세요. 이 엔티티의 Transform도 읽기 전용입니다. 카메라 각도나 위치를 수정하려면 다음을 사용하세요: [가상 카메라](/creator/content-creator-ko/sdk7/3d/camera.md#using-virtual-cameras).

카메라의 다음도 가져올 수 있습니다: `CameraMode` 컴포넌트를 사용해 플레이어가 1인칭 또는 3인칭 카메라 모드를 사용 중인지 확인하세요. 다음을 참조하세요: [카메라 모드](/creator/content-creator-ko/sdk7/interactivity/user-data.md#check-the-players-camera-mode).


---

# 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/architecture/entities-components.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.
