---
createdAt: 2026-07-30
updatedAt: 2026-07-30
title: 선택 기반 콘텐츠
description: Intlayer에서 선택 기반 콘텐츠를 사용하여 임의의 문자열 값을 기반으로 콘텐츠를 동적으로 표시하는 방법을 알아보세요. 이 문서를 따라 프로젝트에서 스위치(switch) 유사 콘텐츠를 효율적으로 구현하세요.
keywords:
- 선택 기반 콘텐츠
- Select Content
- 스위치 콘텐츠
- ICU select
- 동적 렌더링
- 문서
- Intlayer
- Next.js
- JavaScript
- React
slugs:
- doc
- concept
- content
- select
history:
- version: 9.1.0
date: 2026-07-30
changes: "선택 기반 콘텐츠 도입"
author: aymericzip
---
# 선택 기반 콘텐츠 (Select) / Intlayer
## Select의 작동 방식
Intlayer에서 선택 기반 콘텐츠는 `select` 함수를 통해 이루어지며, 임의의 문자열 값을 해당 콘텐츠에 매핑합니다. 이는 ICU의 `{value, select, …}` 메시지나 애플리케이션 코드의 `switch` 문과 동일합니다.
상태(status), 요금제(plan), 플랫폼(platform), 역할(role) 등 판별자(discriminant)가 자유 형식의 문자열일 때 `select`를 사용하세요. 다른 판별자의 경우 Intlayer는 전용 노드를 제공합니다:
| 판별자 | 노드 |
| ----------------- | ---------- |
| 수량 | `enu()` |
| 불리언(Boolean) | `cond()` |
| 성별 | `gender()` |
| 그 외 모든 문자열 | `select()` |
## 선택 기반 콘텐츠 설정하기
Intlayer 프로젝트에서 선택 기반 콘텐츠를 설정하려면, 선택 정의를 포함하는 콘텐츠 모듈을 생성하세요. 아래는 다양한 형식의 예시입니다.
```typescript fileName="**/*.content.ts" contentDeclarationFormat={["typescript", "esm", "commonjs"]}
import { select, type Dictionary } from "intlayer";
const myPostContent = {
key: "my_key",
content: {
publishStatus: select({
draft: "This post is a draft",
published: "This post is live",
scheduled: "This post is scheduled",
fallback: "Unknown status", // 선택 사항
}),
},
} satisfies Dictionary;
export default myPostContent;
```
```json5 fileName="**/*.content.json" contentDeclarationFormat="json"
{
"$schema": "https://intlayer.org/schema.json",
"key": "my_key",
"content": {
"publishStatus": {
"nodeType": "select",
"select": {
"draft": "This post is a draft",
"published": "This post is live",
"scheduled": "This post is scheduled",
"fallback": "Unknown status", // 선택 사항
},
},
},
}
```
> `fallback`이 선언되지 않은 경우, 제공된 값이 선언된 케이스와 일치하지 않으면 마지막으로 선언된 키가 대체(fallback)로 간주됩니다. 이는 `cond()` 및 `gender()`와 동일한 규칙입니다.
### 타입 안전성(Type Safety)
허용되는 인수는 선언된 케이스에서 유추됩니다:
- `fallback`이 없으면 선언된 케이스만 허용됩니다: 오타는 타입 오류로 처리됩니다.
- `fallback`이 있으면 모든 문자열이 허용되며(대체 항목이 일치하지 않는 값을 처리함), 동시에 선언된 케이스는 여전히 자동 완성(autocompletion)을 제공합니다.
## 일반 객체(Plain Object)를 사용하지 않는 이유
일반 객체를 선언하고 런타임 값을 사용하여 인덱싱하는 것은 매력적일 수 있습니다:
```tsx
// ❌ 이렇게 하지 마세요
const { publishStatus } = useIntlayer("my_key");
return
{publishStatus[publishType]}
;
```
Intlayer 컴파일러는 소스 코드를 분석하여 사용되지 않는 콘텐츠를 버리고 나머지 키를 축소(minify)합니다. 동적 계산 접근(`obj[expr]`)은 정적으로 해석될 수 없으므로, 전체 분기가 불투명(opaque)하게 표시됩니다: 해당 분기는 번들(bundle)에 보존되며 해당 키는 축소되지 않습니다.
`select()`를 사용하면, 케이스 해결이 속성 접근(property access)이 아닌 함수 호출 내부에서 이루어집니다. 컴파일러는 단일 정적 필드 접근을 인지하고, `enu()`, `cond()`, 또는 `gender()`와 동일한 방식으로 노드를 정확하게 최적화합니다:
```tsx
// ✅ 이렇게 하세요
const { publishStatus } = useIntlayer("my_key");
return {publishStatus(publishType)}
;
```
## 선택 기반 콘텐츠 사용하기
React 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `react-intlayer` 패키지의 `useIntlayer` 훅을 가져와 사용하세요. 이 훅은 지정된 키에 대한 콘텐츠를 가져오고, 적절한 출력을 선택하기 위해 값을 전달할 수 있게 해줍니다.
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
import type { FC } from "react";
import { useIntlayer } from "react-intlayer";
const PostStatus: FC = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{
/* 출력: This post is a draft */
publishStatus("draft")
}
{
/* 출력: This post is live */
publishStatus("published")
}
{
/* 출력: Unknown status */
publishStatus("Archived")
}
);
};
export default PostStatus;
```
Next.js 클라이언트 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 예시는 다음과 같습니다:
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
"use client";
import type { FC } from "react";
import { useIntlayer } from "next-intlayer";
const PostStatus: FC = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{publishStatus("draft")}
{publishStatus("published")}
);
};
export default PostStatus;
```
Vue 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 예시는 다음과 같습니다:
```vue fileName="**/*.vue"
{{ publishStatus("draft") }}
{{ publishStatus("published") }}
```
Svelte 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 스토어는 `$`를 사용하여 접근합니다. 예시는 다음과 같습니다:
```svelte fileName="**/*.svelte"
{$content.publishStatus("draft")}
{$content.publishStatus("published")}
```
Preact 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 예시는 다음과 같습니다:
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
import type { FC } from "preact";
import { useIntlayer } from "preact-intlayer";
const PostStatus: FC = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{publishStatus("draft")}
{publishStatus("published")}
);
};
export default PostStatus;
```
SolidJS 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 예시는 다음과 같습니다:
```tsx fileName="**/*.tsx" codeFormat={["typescript", "esm"]}
import type { Component } from "solid-js";
import { useIntlayer } from "solid-intlayer";
const PostStatus: Component = () => {
const { publishStatus } = useIntlayer("my_key");
return (
{publishStatus("draft")}
{publishStatus("published")}
);
};
export default PostStatus;
```
Angular 컴포넌트 내에서 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 예시는 다음과 같습니다:
```typescript fileName="app.component.ts" codeFormat="typescript"
import { Component } from "@angular/core";
import { useIntlayer } from "angular-intlayer";
@Component({
selector: "app-post-status",
template: `
{{ content().publishStatus("draft") }}
{{ content().publishStatus("published") }}
`,
})
export class PostStatusComponent {
content = useIntlayer("my_key");
}
```
`vanilla-intlayer`로 선택 기반 콘텐츠를 활용하려면 `useIntlayer` 훅을 통해 검색하세요. 예시는 다음과 같습니다:
```typescript fileName="**/*.ts" codeFormat={["typescript", "esm"]}
import { installIntlayer, useIntlayer } from "vanilla-intlayer";
installIntlayer();
const content = useIntlayer("my_key").onChange((newContent) => {
document.getElementById("status")!.textContent =
newContent.publishStatus("draft");
});
// 초기 렌더링
document.getElementById("status")!.textContent = content.publishStatus("draft");
```
## Select와 다른 노드의 결합
각 케이스에는 완전한 콘텐츠 노드가 포함되어 있으므로, `select`는 `t()`, `insert()`, `md()` 등과 조합될 수 있습니다:
```typescript fileName="**/*.content.ts" codeFormat="typescript"
import { insert, select, t, type Dictionary } from "intlayer";
const myPostContent = {
key: "my_key",
content: {
publishStatus: select({
draft: insert(
t({
en: "{{name}} saved a draft",
fr: "{{name}} a enregistré un brouillon",
ko: "{{name}}님이 초안을 저장했습니다",
})
),
published: insert(
t({
en: "{{name}} published the post",
fr: "{{name}} a publié l’article",
ko: "{{name}}님이 게시물을 발행했습니다",
})
),
fallback: insert(
t({
en: "{{name}} updated the post",
fr: "{{name}} a mis à jour l’article",
ko: "{{name}}님이 게시물을 업데이트했습니다",
})
),
}),
},
} satisfies Dictionary;
export default myPostContent;
```
```tsx
publishStatus("draft")({ name: "Alice" }); // 출력: Alice님이 초안을 저장했습니다
```
## ICU `select`에서 마이그레이션
ICU `select` 인수를 사용하는 메시지는 `select` 노드로 가져옵니다:
```text
{publishType, select, draft {draft} published {published} other {Unknown}}
```
위의 형식은 다음과 같이 변경됩니다:
```typescript
select(
{
draft: "draft",
published: "published",
fallback: "Unknown",
},
"publishType"
);
```
ICU `other` 케이스는 모든 불일치 케이스에 대한 Intlayer의 정규 이름인 `fallback`으로 이름이 바뀝니다. 두 번째 인수는 ICU 변수의 이름을 기록하므로 메시지를 내보낼 때 정확히 동일한 ICU 문자열로 되돌릴 수 있습니다.
> 참고로, 케이스가 성별 값(`male` / `female` / `other`)인 ICU `select`는 대신 [`gender`](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/dictionary/gender.md) 노드로 가져옵니다.
## 추가 리소스
구성 및 사용에 대한 더 자세한 정보는 다음 리소스를 참조하세요:
- [Intlayer CLI 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/cli/index.md)
- [Intlayer React 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_with_create_react_app.md)
- [Intlayer Next.js 문서](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ko/intlayer_with_nextjs_15.md)
이러한 리소스는 다양한 환경과 프레임워크에서 Intlayer를 설정하고 사용하는 방법에 대한 추가 통찰력을 제공합니다.