# 테마 컴포넌트 우선순위 순서

**URL:** https://meta.discourse.org/t/theme-component-order-of-precedence/156615
**Category:** Development
**Created:** [7월 2, 2020, 3:13오후 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615 "2020-07-02T15:13:16Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![guildai](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/guildai/32/248544_2.png) [@guildai](https://meta.discourse.org/u/guildai)
#### Post date: [7월 2, 2020, 3:13오후 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/1 "2020-07-02T15:13:16Z")

</div>

테마 컴포넌트가 설치 순서대로 실행되는 것 같습니다. 예를 들어 A를 설치한 후 B를 설치하면, 생성된 페이지에서 A의 스크립트가 B보다 먼저 포함됩니다.

이것에 의존할 수 있을까요? 이 순서를 보여주는 뷰가 어딘가에 있나요? 설치된 컴포넌트를 볼 때, 컴포넌트는 알파벳 순서로 나열되어 보입니다.

특정 컴포넌트보다 먼저 액션을 실행할 수 있는 방법을 선호합니다. 제 경우, TOC 컴포넌트(이 주제와 관련됨)보다 먼저 액션을 실행하고 싶습니다. [Ember 문서](https://api.emberjs.com/ember/release/functions/@ember%2Frunloop/schedule)에 따르면, 특정 큐에 예약된 함수는 예약된 순서대로 실행되는 것 같습니다. 제 경우 스케줄링 순서가 매우 중요합니다.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [7월 3, 2020, 1:05오전 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/2 "2020-07-03T01:05:05Z")

</div>

> [@guildai](#):
>
> 이것에 의존할 수 있을까요?

이것은 의존할 수 있는 것이 아닙니다. 대신 적절한 API를 통해 이를 제어해야 합니다. 일정 정도까지 Ember 초기화(initializers)를 사용하여 이를 제어할 수 있습니다. 스케줄링하려고 하는 예제 코드를 붙여넣어 주시면 @eviltrout이 구체적인 아이디어를 제시할 수 있을 것입니다.

---

<div class="post-metadata">

### Author: ![guildai](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/guildai/32/248544_2.png) [@guildai](https://meta.discourse.org/u/guildai)
#### Post date: [7월 3, 2020, 1:59오후 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/3 "2020-07-03T13:59:48Z")

</div>

다음은 제가 실행 중인 코드입니다:

```plaintext
<script type="text/discourse-plugin" version="0.8">
    const { run } = Ember;
    
    api.decorateCooked($elem => {
        run.scheduleOnce("actions", () => {
          // Must run before the scheduled actions from TOC component.
        });
    })

```

TOC 컴포넌트는 동일한 인터페이스를 사용하여 [동작을 예약](https://github.com/discourse/DiscoTOC/blob/master/common/header.html#L254)합니다.

Ember 문서에 따르면, 예약 인터페이스는 다음과 같습니다:

> 전달된 대상/메서드 및 선택적 인수를 지정된 큐에 추가하여 RunLoop의 끝에서 실행되도록 합니다

이 용어 "추가(add)"는 예약된 동작이 FIFO(선입선출) 순서로 처리됨을 시사합니다. 따라서 여기서는 `schedule` 호출 순서가 매우 중요합니다.

---

<div class="post-metadata">

### Author: ![guildai](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/guildai/32/248544_2.png) [@guildai](https://meta.discourse.org/u/guildai)
#### Post date: [7월 3, 2020, 10:32오후 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/4 "2020-07-03T22:32:00Z")

</div>

TOC 컴포넌트를 재설치하고 제거하는 방식으로 JavaScript 실행 순서를 재배열하려는 시도를 하던 중, TOC JavaScript가 _마지막으로_ 실행되는 것처럼 보이는 우연한 부수 효과가 있다는 것을 발견했습니다. 그리고 CSS 규칙이 이제 이 순서로 적용되고 있습니다. 🙂

테마 컴포넌트 코드 배치의 순서 문제는 꽤 중요하다고 생각합니다. 순서가 공식적으로 “미정의(undetermined)” 상태라면, 컴포넌트들이 서로 상호작용할 수 있는 방법이 없습니다.

아마도 컴포넌트 간 상호작용은 목표가 아닐 수도 있습니다. 하지만 순서 휴리스틱(예: 동일한 이름의 다른 컴포넌트 파일보다 _앞서_ 또는 _뒤에_ 위치하도록 선언 — 이는 아마도 about.json에서 정의될 것입니다)를 사용한다면 이 문제는 그렇게 어렵지 않을 것입니다.

제 경우에는 제가 하려는 작업에 기반할 때 TOC 컴포넌트를 포크하는 것이 올바른 방향이라고 점점 더 느끼고 있습니다.

---

<div class="post-metadata">

### Author: ![Johani](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/johani/32/176920_2.png) [@Johani](https://meta.discourse.org/u/Johani)
#### Post date: [7월 6, 2020, 8:42오전 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/5 "2020-07-06T08:42:26Z")

</div>

테마 또는 컴포넌트를 생성/설치할 때마다 Discourse는 해당 항목에 id를 부여합니다. 해당 컴포넌트의 페이지를 방문하면 URL에서(끝부분의 숫자) 그 id를 확인할 수 있습니다.

![component id in the URL](https://global.discourse-cdn.com/meta/original/3X/5/0/5080f66f7f0a462bcc7dab47e7efdb5ed25afba4.png)

해당 컴포넌트가 테마에 추가되면, 실행 순서는 기본적으로 id를 기준으로 결정되는 것 같습니다(디퍼링 없이 콘솔 로그를 출력하는 매우 기본적인 수준에서). 즉, 233은 234보다 먼저 실행되는 식입니다.

이 방식은 대부분의 경우 잘 작동합니다. 후속 변경 사항들은 보통 새로운 컴포넌트로 추가되므로 자연스럽게 순서가 정해지기 때문입니다.

장기적으로는 테마에 추가한 컴포넌트 목록의 순서를 따르는 방식으로 변경될 수 있습니다.

 ![active components setting](https://global.discourse-cdn.com/meta/original/3X/1/a/1a469acf4947d2f2be7460d9e0d0eeb2b4b5cdb6.png)

하지만 현재로서는 로드맵에 포함되어 있지 않습니다.

실제로 필요한 것은 이니셜라이저(initializer)의 실행 순서입니다. 코드를 [새로운 테마 JS 생성 방식](https://meta.discourse.org/t/splitting-up-theme-javascript-into-multiple-files/119369)으로 이동하지 않는 한 이를 구현할 수 없다고 생각합니다. 이 방식은 이니셜라이저에 이름과 실행 순서를 지정할 수 있게 해줍니다. 예를 들어, 다음과 같은 파일이 있다고 가정해 보겠습니다.

`/javascripts/discourse/initializers/initialize-for-foo.js`

그 내용이 다음과 같다고 합시다.

```js
import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "foo",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("foo")
    });
  }
}

```

그리고 다음과 같이 생긴 다른 이니셜라이저가 있다고 가정해 보겠습니다.

`/javascripts/discourse/initializers/initialize-for-bar.js`

```js
import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "bar",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("bar")
    });
  }
}

```

`bar`가 `foo`보다 나중에 실행되도록 하려면 `after:` 인수를 추가할 수 있습니다. 이렇게 하면 해당 인수로 전달한 이니셜라이저 이름의 코드보다 나중에 실행되도록 보장됩니다. 따라서 `bar`가 `foo`보다 나중에 실행되려면 다음 파일에서 이렇게 하면 됩니다.

`/javascripts/discourse/initializers/initialize-for-bar.js`

```diff
import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "bar",
+ after: "foo",
  initialize() {
    withPluginApi("0.8.7", api => {
      console.log("bar");
    });
  }
};

```

---

<div class="post-metadata">

### Author: ![guildai](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/guildai/32/248544_2.png) [@guildai](https://meta.discourse.org/u/guildai)
#### Post date: [7월 6, 2020, 12:53오후 UTC](https://meta.discourse.org/t/theme-component-order-of-precedence/156615/6 "2020-07-06T12:53:09Z")

</div>

상세한 조언을 주셔서 정말 감사합니다! TOC 컴포넌트와 관련된 문제들(이 부분에도 답변을 주셨는데, 다시 한번 감사드립니다) 때문에 TOC를 포크하고 종속 코드를 해당 컴포넌트로 옮겼습니다. 이는 제목 ID와 관련이 있으며, 구체적으로 게시글에서 ID를 제어하여 중복 및 핵심 요소 ID와의 충돌을 처리해야 하는 필요성 때문입니다.

문서 작업에서 제가 하는 일 중 일부가 다소 비전통적인 방식이므로, 이것이 올바른 접근 방식이라고 생각합니다.
