# 텍스트 런과 단락

- Human documentation: [https://docs.univer.ai/ko-KR/guides/docs/model/text-runs-and-paragraphs](https://docs.univer.ai/ko-KR/guides/docs/model/text-runs-and-paragraphs)

- Agent Markdown: [https://docs.univer.ai/ko-KR/guides/docs/model/text-runs-and-paragraphs.md](https://docs.univer.ai/ko-KR/guides/docs/model/text-runs-and-paragraphs.md)

- Requested language: `ko-KR`

- Content language: `ko-KR`

- Documentation version: `1.0.4`

- Source: [docs/model/text-runs-and-paragraphs.ko-KR.mdx](https://github.com/dream-num/documentation/blob/dev/content/guides/docs/model/text-runs-and-paragraphs.ko-KR.mdx)

---

## 인덱스 기반 모델

Univer Docs는 리치 텍스트를 중첩된 트리로 저장하지 않습니다. 일반 텍스트를 `body.dataStream`[^utf16-offsets]에 저장한 다음, 인덱스 범위를 사용해 텍스트에 스타일과 구조를 연결합니다.

가장 일반적인 인덱스 기반 구조는 다음과 같습니다.

* `ITextRun`: 인라인 텍스트 스타일 범위입니다.
* `IParagraph`: 단락 메타데이터와 단락 스타일입니다.
* `ISectionBreak`: 구역 나누기 메타데이터입니다.

## ITextRun

`ITextRun`은 연속된 텍스트 범위의 스타일을 나타냅니다.

| 속성   | 타입           | 설명                             |
| ---- | ------------ | ------------------------------ |
| st   | `number`     | **시작 인덱스이며, 해당 위치를 포함합니다.**    |
| ed   | `number`     | **끝 인덱스이며, 해당 위치를 포함하지 않습니다.** |
| sId? | `string`     | 참조되는 스타일 ID입니다.                |
| ts?  | `ITextStyle` | 인라인 텍스트 스타일 객체입니다.             |

```typescript
const body: IDocumentBody = {
  dataStream: 'Hello Univer\r\n',
  textRuns: [
    {
      st: 0,
      ed: 5,
      ts: { bl: 1 },
    },
    {
      st: 6,
      ed: 12,
      ts: { cl: { rgb: '#2563eb' } },
    },
  ],
}
```

이 예제에서는 `Hello`가 굵게 표시되고 `Univer`가 파란색으로 표시됩니다. 단락 나누기 `\r\n`은 스타일 범위에 포함되지 않습니다.

## IParagraph

`IParagraph`는 단락 수준의 메타데이터를 나타냅니다. `startIndex`는 `dataStream`에서 단락 나누기가 있는 위치를 가리킵니다.

| 속성              | 타입                | 설명                                   |
| --------------- | ----------------- | ------------------------------------ |
| startIndex      | `number`          | 단락 나누기의 인덱스입니다.                      |
| paragraphId     | `string`          | 안정적인 단락 ID입니다.                       |
| paragraphStyle? | `IParagraphStyle` | 맞춤, 들여쓰기, 줄 간격, 제목 유형과 같은 단락 스타일입니다. |
| bullet?         | `IBullet`         | 목록 표식 메타데이터입니다.                      |

```typescript
const body: IDocumentBody = {
  dataStream: 'Hello Univer\r\nSecond line\r\n',
  paragraphs: [
    {
      startIndex: 12,
      paragraphId: 'p-1',
      paragraphStyle: {
        namedStyleType: NamedStyleType.HEADING_1,
      },
    },
    {
      startIndex: 25,
      paragraphId: 'p-2',
    },
  ],
}
```

## ISectionBreak

`ISectionBreak`도 인덱스를 사용해 구역 수준 설정을 텍스트 스트림에 연결합니다. 구역별로 페이지 크기, 여백, 머리글, 바닥글, 단, 텍스트 방향을 재정의할 수 있습니다.

```typescript
const body: IDocumentBody = {
  dataStream: 'First section\nSecond section\r\n',
  sectionBreaks: [
    {
      startIndex: 13,
      pageSize: { width: 595, height: 842 },
      marginTop: 72,
      marginBottom: 72,
    },
  ],
}
```

## 참고

* 인덱스를 `dataStream`에 맞게 유지하세요. 인덱스가 잘못되면 스타일 범위, 단락, 선택 영역 또는 렌더링이 일관되지 않을 수 있습니다.
* 활성 문서를 편집할 때는 Facade API와 명령을 사용하는 것이 좋습니다.
* 스냅샷을 직접 생성할 때는 먼저 `dataStream`을 만든 다음 해당 문자열을 기준으로 범위와 단락 위치를 계산하세요.

[^utf16-offsets]: 텍스트 위치는 보이는 글자 수가 아닌 JavaScript UTF-16 코드 단위로 셉니다. 예를 들어 `"😀".length`는 2입니다. 텍스트 범위 `[st, ed)`는 끝을 포함하지 않으므로 시트 범위의 끝 포함 규칙과 다릅니다.
