> 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)

## 개요

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

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

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

다음에서 [Creator Hub의 씬 편집기](/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)

{% 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)

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

엔진은 장면의 중심에 자리하며 다른 모든 부분을 관리하는 부분입니다. 어떤 엔티티가 렌더링되는지와 플레이어가 그것들과 어떻게 상호작용하는지를 결정합니다. 또한 다음에서 어떤 함수가 [시스템](/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('엔티티가 제거됨:', 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('엔티티를 제거할 수 없음(예약됨)')
}
```

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

엔티티와 그 모든 자식(그리고 그 자식의 자식까지 재귀적으로)도 함께 제거하려면 `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)

엔티티를 다른 엔티티의 부모로 설정하려면, 자식 엔티티에 Transform 컴포넌트가 있어야 합니다. 그런 다음 `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 컴포넌트가 있다면, 자식 엔티티 역시 영향을 받습니다. 모든 위치나 회전 값은 더해지고, 모든 스케일 값은 곱해집니다.

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

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

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

자식 엔티티를 부모와 분리하려면, 엔티티의 parent를 `engine.RootEntity`.

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

{% hint style="warning" %}
**📔 참고**: 다른 플레이어와 동기화되는 중첩 엔티티를 다룰 때는 `parentEntity()` 대신 다음을 사용하세요 `parent` Transform의 entity를 사용하세요. 자세히 보기 [부모가 있는 엔티티](/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)

## 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()` 함수를 사용하세요. Scene Editor UI의 왼쪽 트리 뷰에 표시된 그대로 엔티티의 이름을 문자열로 전달합니다.

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

{% hint style="warning" %}
**📔 참고**: 반드시 다음만 사용하세요. `engine.getEntityOrNullByName()` 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: 'Open' },
			},
			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()` function은 컴포넌트에 대한 읽기 전용 참조를 가져옵니다. 이 참조로는 컴포넌트의 어떤 값도 변경할 수 없습니다.

컴포넌트 값을 변경하고 싶다면 `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
```

위의 예제는 Transform 컴포넌트의 *x* 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(
		'큐브 위치가 변경됨: ',
		newTransform.position,
		newTransform.rotation
	)
})

VisibilityComponent.onChange(cubeEntity, (newVisibilityComponent) => {
	if (!newVisibilityComponent) return
	console.log('큐브 가시성이 변경됨: ', 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('후손 위치:', transform.position)
	}
}
```

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

* `엔진`엔티티를 실행하는 엔진 인스턴스
* `entity`시작할 루트 엔티티
* `컴포넌트`필터링할 컴포넌트(보통 `Transform` 공간 계층 구조용)

이 함수는 트리 구조의 각 후손 엔티티를 반환하는 제너레이터입니다. 지정된 컴포넌트가 있는 엔티티만 결과에 포함됩니다.

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

```ts
// 특정 이름을 가진 모든 후손 찾기
for (const descendantEntity of getComponentEntityTree(
	engine,
	parentEntity,
	Transform
)) {
	const name = Name.getOrNull(descendantEntity)
	if (name && name.value === 'targetEntity') {
		console.log('대상 엔티티를 찾음:', descendantEntity)
	}
}
```

## 예약된 엔티티

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

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

{% hint style="warning" %}
**📔 참고**: 초기화되기 전에 이러한 엔티티를 참조하지 마세요. 이 문제를 피하려면 `함수 내부,` 함수에서, 또는 시스템에서 이러한 엔티티를 참조하세요.
{% 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/player-avatar.md#move-player).

객체를 이 엔티티의 자식으로 설정해 플레이어에 연결할 수도 있지만, 그 경우에는 [Attach to Player](/creator/content-creator-ko/sdk7/3d/entity-positioning.md#attach-an-entity-to-an-avatar) 가 종종 더 나은 선택입니다.

## 카메라 엔티티

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

카메라의 `Transform` 컴포넌트를 가져오면 카메라의 위치와 회전을 확인할 수 있습니다. 이 엔티티의 Transform도 읽기 전용입니다. 카메라 각도나 위치를 수정하려면 [Virtual camera](/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 dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-ko/sdk7/architecture/entities-components.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
