> 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/2d-ui/dynamic-ui.md).

# 동적 UI

데이터 변경에 반응하는 동적 UI를 만드는 방법을 알아봅니다.

틱마다 업데이트되는 동적 요소를 포함하는 UI를 정의할 수 있습니다. 이 데이터를 나타내는 변수를 업데이트하는 것만 처리하면 되고, UI는 새 값에 맞춰 자동으로 조정됩니다.

이것은 타이머, 플레이어 점수 등과 같은 요소를 포함하는 데 매우 유용합니다. 하지만 여기서 한 걸음 더 나아가 상태에 기반해 전체 UI 구조를 정의할 수도 있습니다.

## 참조 변수

uiEntity의 컴포넌트 중 하나의 어떤 속성에서든 단순히 변수를 참조할 수 있습니다. 변수가 값이 바뀌면 UI도 그에 따라 조정됩니다.

아래 예제는 변수를 정의합니다 `playerCurrentPosition` 와 이를 문자열의 일부로 참조합니다.  `uiText` 컴포넌트. 그런 다음 시스템이 플레이어의 현재 위치를 사용하여 매 틱마다 이 변수의 값을 업데이트합니다. 변수 값이 바뀌면 UI는 명시적으로 수정할 필요 없이 그에 따라 업데이트됩니다.

***ui.tsx 파일:***

```tsx
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { playerCurrentPosition } from './index'
import { Color4 } from '@dcl/sdk/math'

// UI 그리기
export const uiMenu = () => (
  <UiEntity
    uiTransform={{
			width: '100%',
			height: '100px',
			justifyContent: 'center',
			alignItems: 'center',
    }}
    uiText={{ value: `플레이어: `+  playerCurrentPosition, fontSize: 40 }}
    uiBackground={{ color: Color4.create(0.5, 0.8, 0.1, 0.6) }}
  />
)
```

***index.ts 파일:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { engine, Transform } from '@dcl/sdk/ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}

// 변수 정의
export let playerCurrentPosition: string = ""

// 변수를 업데이트하는 시스템
engine.addSystem(() => {
  const playerPosition = Transform.getOrNull(engine.PlayerEntity)
  if (!playerPosition) return
  const { x, y, z } = playerPosition.position
  playerCurrentPosition =  `{x: ${x.toFixed(2)}, y: ${y.toFixed(2)}, z: ${z.toFixed(2)} }`
})
```

위의 예제에서는 변수를 문자열의 일부로 포함하기 위해, 변수를 `${ }`.

```ts
uiText={{
	value: `플레이어: ${playerCurrentPosition}`,
	fontSize: 40
}}
```

## UI 내부에서 함수 호출하기

JSX 정의 내부에서 함수도 호출할 수 있으며, UI의 속성에 사용할 값을 반환할 수 있습니다. 이 JSX 정의 내부에서 호출되는 함수는 게임 루프의 매 틱마다 반복적으로 호출됩니다.

아래 예제에서는, 한 `uiText` 컴포넌트가 `getPlayerPosition()` 표시할 문자열의 일부를 정의하는 데 사용됩니다.

이 예제는 이전 섹션의 예제와 유사하지만, UI 정의 내부에서 함수를 호출함으로써 별도의 변수를 선언하고 해당 변수를 변경하는 시스템을 정의하는 일을 피할 수 있습니다. 참고로 `getPlayerPosition()` 명시적으로 시스템을 선언할 필요 없이 게임 루프의 매 틱마다 호출됩니다.

***ui.tsx 파일:***

```tsx
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'
import { engine, Transform } from "@dcl/sdk/ecs";

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: '100%',
      height: '100px',
      justifyContent: 'center',
      alignItems: 'center',
    }}
    uiText={{ value: `플레이어: `+  getPlayerPosition(), fontSize: 40 }}
    uiBackground={{ color: Color4.create(0.5, 0.8, 0.1, 0.6) }}
  />
)

function getPlayerPosition(){
  const playerPosition = Transform.getOrNull(engine.PlayerEntity)
  if (!playerPosition) return '로딩 중...'
  const { x, y, z } = playerPosition.position
  return `{x: ${x.toFixed(2)}, y: ${y.toFixed(2)}, z: ${z.toFixed(2)} }`
}
```

***index.ts 파일:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

## UI를 켜고 끄기

UI를 켜고 끄는 가장 쉬운 방법은 `표시` 속성은 엔터티의 `uiTransform`. `표시` 속성은 UI 엔터티와 그 모든 자식 요소를 보이지 않게 만들며, 값이 `none`.

다음 예제에서는 변수를 사용해 UI의 일부에 있는 `표시` 필드를 설정합니다. 이 변수의 값은 다른 UI 요소를 클릭하여 전환할 수 있습니다.

***ui.tsx 파일:***

```tsx
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'

// 메뉴 표시 여부의 현재 상태를 반영하는 변수
var isMenuVisible: boolean = false

// 메뉴 상태를 전환하는 함수
function toggleMenuVisibility() {
  isMenuVisible = !isMenuVisible
}

export const uiMenu = () => (
   // 부모
   <UiEntity>
      {/* 메뉴 */}
      <UiEntity
       uiTransform={{
          width: '80%',
          height: '100px',
          alignContent: 'center',
          justifyContent: 'center',
          display: isMenuVisible ? 'flex': 'none'
        }}
         uiText={{
          value: "메뉴",
          fontSize: 30
        }}
        uiBackground={{ color: Color4.Green() }}
      />
      {/* 버튼 */}
      <UiEntity
        uiTransform={{
          width: 100,
          height: 30,
          margin: { top: '35px', left: '500px' }
        }}
        uiText={{
          value: "메뉴 전환",
          fontSize: 40
        }}
        uiBackground={{ color: Color4.Red() }}
        onMouseDown={toggleMenuVisibility}
      />
   </UiEntity>
)
```

***index.ts 파일:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```

## 동적 UI 엔터티

위 섹션의 예제들은 엔터티의 단일 속성을 동적으로 변경하는 방법을 보여주지만, 동적으로 변하는 데이터에 따라 확장될 수 있는 엔터티의 전체 구조를 정의할 수도 있습니다. 이런 패턴은 React 같은 라이브러리를 사용할 때 웹 개발에서 흔하며, 매우 강력합니다. 이를 통해 매우 유연하고 확장 가능한 UI 애플리케이션을 정의할 수 있습니다.

다음 예제는 씬에서 다음을 가진 모든 엔터티의 ID를 나열합니다. `MeshRenderer` 과 `Transform`. 각 항목에 대해 하나를 생성합니다. `uiText` 각각에 대해. 씬의 콘텐츠가 변경되면 UI 엔터티 목록도 매 틱마다 자동으로 조정됩니다.

***ui.tsx 파일:***

```tsx
import { UiEntity, ReactEcs } from '@dcl/sdk/react-ecs'
import { Color4 } from '@dcl/sdk/math'
import { engine } from '@dcl/sdk/ecs'
import { MeshRenderer } from '@dcl/sdk/ecs'
import { Transform } from '@dcl/sdk/ecs'

export const uiMenu = () => (
  <UiEntity
    uiTransform={{
      width: '100%',
      height: '300px',
      justifyContent: 'center',
      alignItems: 'center',
    }}
    uiBackground={{ color: Color4.create(0.5, 0.8, 0.1, 0.6) }}
  >
    <UiEntity>
      {generateText()}
    </UiEntity>
  </UiEntity>
)


function generateText(){
  return Array.from(engine.getEntitiesWith(
    MeshRenderer,
    Transform
  )).map(([entity]) => <TextComponent value={entity.toString()} key={entity} /> )
}


function TextComponent(props: { value: string; key: string | number }) {
  return <UiEntity
    key={props.key}
    uiTransform={{ width: 80, height: 20 }}
    uiText={{ value: props.value, textAlign: 'middle-center', fontSize: 12 }}
    uiBackground={{ color: { r: 1, g: 0.176, b: 0.333, a: 1 } }}
  />
}
```

***index.ts 파일:***

```ts
import { ReactEcsRenderer } from '@dcl/sdk/react-ecs'
import { uiMenu } from './ui'

export function main() {
    ReactEcsRenderer.setUiRenderer(uiMenu, { virtualWidth: 1920, virtualHeight: 1080 })
}
```


---

# 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/2d-ui/dynamic-ui.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.
