Skip to main content

text

id: text title: Text

텍스트를 표시하는 React 컴포넌트이다.

Text 컴포넌트는 중첩, 스타일링, 터치 이벤트 처리를 지원한다.

다음 예제에서 중첩된 제목과 본문 텍스트는 styles.baseTextfontFamily를 상속받지만, 제목은 추가적인 스타일을 제공한다. 제목과 본문은 줄바꿈 문자로 인해 서로 위아래로 배치된다.

중첩 텍스트

안드로이드와 iOS 모두 특정 범위의 문자열에 굵게 표시하거나 색상을 지정하는 등의 서식을 적용할 수 있다. iOS에서는 NSAttributedString을, 안드로이드에서는 SpannableString을 사용한다. 하지만 실제로 이 방법은 매우 번거롭다. 리액트 네이티브에서는 웹의 방식을 차용해 중첩된 텍스트를 사용해 같은 효과를 얻을 수 있도록 했다.

리액트 네이티브는 이 코드를 내부적으로 평면화된 NSAttributedString이나 SpannableString으로 변환한다. 이 변환 결과는 다음과 같은 정보를 포함한다.

"I am bold and red"
0-9: bold
9-17: bold, red

컨테이너

<Text> 엘리먼트는 레이아웃 측면에서 독특한 특성을 가진다. <Text> 안에 포함된 모든 요소는 더 이상 플렉스 박스 레이아웃을 사용하지 않고 텍스트 레이아웃을 사용한다. 이는 <Text> 내부의 요소들이 더 이상 직사각형 형태가 아니며, 줄 끝에 도달하면 자동으로 줄바꿈된다는 것을 의미한다.

tsx
<Text>
<Text>First part and </Text>
<Text>second part</Text>
</Text>
// 텍스트 컨테이너: 공간이 허용되면 텍스트는 인라인으로 배치된다.
// |First part and second part|

// 그렇지 않으면 텍스트는 하나로 흐르는 것처럼 줄바꿈된다.
// |First part |
// |and second |
// |part |

<View>
<Text>First part and </Text>
<Text>second part</Text>
</View>
// 뷰 컨테이너: 각 텍스트는 독립적인 블록으로 처리된다.
// |First part and|
// |second part |

// 그렇지 않으면 각 텍스트는 자신의 블록 안에서 줄바꿈된다.
// |First part |
// |and |
// |second part|

제한적인 스타일 상속

웹에서는 일반적으로 전체 문서에 대한 폰트 패밀리와 크기를 설정하기 위해 CSS 상속 속성을 활용한다. 예를 들면 다음과 같다:

css
html {
font-family: 'lucida grande', tahoma, verdana, arial, sans-serif;
font-size: 11px;
color: #141823;
}

이 폰트는 문서 내 모든 엘리먼트에 상속된다. 단, 해당 엘리먼트나 그 상위 엘리먼트에서 새로운 규칙을 지정한 경우는 예외이다.

React Native에서는 이와 달리 더 엄격한 규칙이 적용된다. 모든 텍스트 노드는 반드시 <Text> 컴포넌트로 감싸야 한다. <View> 아래에 직접 텍스트 노드를 배치할 수 없다.

tsx
// 잘못된 예: 예외가 발생한다. <View>의 자식으로 텍스트 노드를 사용할 수 없다.
<View>
Some text
</View>

// 올바른 예
<View>
<Text>
Some text
</Text>
</View>

또한, 전체 하위 트리에 기본 폰트를 설정하는 기능도 제공하지 않는다. fontFamily는 단일 폰트 이름만 허용하며, 이는 CSS의 font-family와 다르다. 애플리케이션 전체에서 일관된 폰트와 크기를 사용하려면 MyAppText와 같은 컴포넌트를 만들어 활용하는 것이 좋다. 이 컴포넌트를 기반으로 MyAppHeaderText와 같은 더 구체적인 컴포넌트를 만들 수도 있다.

tsx
<View>
<MyAppText>
애플리케이션 전체에 적용되는 기본 폰트로 스타일링된 텍스트
</MyAppText>
<MyAppHeaderText>헤더로 스타일링된 텍스트</MyAppHeaderText>
</View>

MyAppText가 스타일링을 포함한 Text 컴포넌트로 자식 엘리먼트를 렌더링하는 컴포넌트라면, MyAppHeaderText는 다음과 같이 정의할 수 있다:

tsx
const MyAppHeaderText = ({children}) => {
return (
<MyAppText>
<Text style={{fontSize: 20}}>{children}</Text>
</MyAppText>
);
};

이렇게 MyAppText를 합성하면 상위 컴포넌트에서 스타일을 상속받으면서도 특정 사용 사례에서 추가하거나 재정의할 수 있다.

React Native는 여전히 스타일 상속 개념을 지원하지만, 텍스트 하위 트리로 제한된다. 이 경우 두 번째 부분은 볼드체이면서 빨간색이 된다.

tsx
<Text style={{fontWeight: 'bold'}}>
나는 볼드체입니다.
<Text style={{color: 'red'}}>그리고 빨간색입니다.</Text>
</Text>

이렇게 텍스트 스타일링을 제한적으로 접근하는 방식이 더 나은 앱을 만드는 데 도움이 된다고 생각한다:

  • (개발자) React 컴포넌트는 강력한 격리를 염두에 두고 설계되었다. 컴포넌트를 애플리케이션 어디에든 배치할 수 있어야 하며, props가 동일하다면 동일한 모습과 동작을 보장해야 한다. props 외부에서 상속받을 수 있는 텍스트 속성은 이 격리를 깨뜨릴 수 있다.

  • (구현자) React Native의 구현도 단순해진다. 모든 엘리먼트에 fontFamily 필드를 추가할 필요가 없으며, 텍스트 노드를 표시할 때마다 트리를 루트까지 탐색할 필요도 없다. 스타일 상속은 네이티브 Text 컴포넌트 내부에만 인코딩되며, 다른 컴포넌트나 시스템 자체로 누출되지 않는다.

참고 자료

Props

accessibilityHint

접근성 힌트는 사용자가 접근성 엘리먼트에 특정 동작을 수행했을 때 어떤 결과가 발생할지 이해하는 데 도움을 준다. 이는 접근성 레이블만으로는 명확하지 않은 경우에 특히 유용하다.

타입
string

accessibilityLanguage
iOS

사용자가 엘리먼트와 상호작용할 때 스크린 리더가 사용해야 하는 언어를 나타내는 값이다. 이 값은 BCP 47 명세를 따라야 한다.

자세한 내용은 iOS accessibilityLanguage 문서를 참고한다.

타입
string

accessibilityLabel

사용자가 엘리먼트와 상호작용할 때 스크린 리더가 읽어주는 텍스트를 재정의한다. 기본적으로 이 레이블은 모든 자식 엘리먼트를 탐색하고 공백으로 구분된 Text 노드를 누적하여 구성된다.

타입
string

accessibilityRole

스크린 리더가 현재 포커스된 엘리먼트를 특정 역할로 인식하도록 지시한다.

iOS에서는 이 역할들이 해당하는 접근성 특성(Accessibility Traits)에 매핑된다. 이미지 버튼은 'image'와 'button' 두 가지 특성이 모두 설정된 것과 동일한 기능을 제공한다. 자세한 내용은 접근성 가이드를 참고한다.

Android에서 이 역할들은 TalkBack에서 iOS의 Voiceover와 유사한 기능을 수행한다. 접근성 특성을 추가하는 것과 같은 효과를 가진다.

타입
AccessibilityRole

accessibilityState

스크린 리더가 현재 포커스된 엘리먼트를 특정 상태로 처리하도록 지시한다.

하나의 상태, 상태 없음, 또는 여러 상태를 제공할 수 있다. 상태는 객체 형태로 전달해야 한다. 예를 들어 {selected: true, disabled: true}와 같은 방식이다.

타입
AccessibilityState

accessibilityActions

접근성 액션은 보조 기술이 컴포넌트의 액션을 프로그래밍 방식으로 호출할 수 있게 한다. accessibilityActions 속성은 액션 객체 목록을 포함해야 한다. 각 액션 객체는 namelabel 필드를 포함해야 한다.

자세한 내용은 접근성 가이드를 참고한다.

타입필수 여부
배열아니오

onAccessibilityAction

사용자가 접근성 동작을 수행할 때 호출된다. 이 함수는 수행할 동작의 이름을 포함한 이벤트를 유일한 인자로 받는다.

자세한 내용은 접근성 가이드를 참고한다.

타입필수 여부
function아니오

accessible

true로 설정하면 해당 뷰가 접근성 요소임을 나타낸다.

자세한 내용은 접근성 가이드를 참고한다.

타입기본값
booleantrue

adjustsFontSizeToFit는 주어진 스타일 제약 조건에 맞게 글꼴 크기를 자동으로 조정할지 여부를 지정한다.

타입기본값
booleanfalse

allowFontScaling

폰트가 접근성 설정 중 텍스트 크기 조정을 반영할지 여부를 지정한다.

타입기본값
booleantrue

android_hyphenationFrequency
Android

Android API 레벨 23 이상에서 단어 줄바꿈을 결정할 때 사용할 자동 하이픈 넣기 빈도를 설정한다.

타입기본값
enum('none', 'normal','full')'none'

aria-busy

이 속성은 엘리먼트가 수정 중임을 나타내며, 보조 기술이 변경이 완료될 때까지 기다린 후에 사용자에게 업데이트를 알릴 수 있도록 한다.

타입기본값
booleanfalse

aria-checked

체크 가능한 엘리먼트의 상태를 나타낸다. 이 속성은 불리언 값이나 "mixed" 문자열을 사용해 혼합 상태의 체크박스를 표현할 수 있다.

타입기본값
boolean, 'mixed'false

aria-disabled

이 속성은 엘리먼트가 인식 가능하지만 비활성화되어 있어 편집하거나 작동할 수 없음을 나타낸다.

타입기본값
booleanfalse

aria-expanded

확장 가능한 엘리먼트가 현재 확장되었는지 축소되었는지를 나타낸다.

타입기본값
booleanfalse

aria-label

인터랙티브 엘리먼트에 대한 레이블 문자열 값을 정의한다.

타입
string

aria-selected

선택 가능한 엘리먼트가 현재 선택되었는지 여부를 나타낸다.

타입
boolean

dataDetectorType
Android

텍스트 엘리먼트에서 클릭 가능한 URL로 변환될 데이터의 타입을 결정한다. 기본적으로는 어떤 데이터 타입도 감지하지 않는다.

하나의 타입만 지정할 수 있다.

타입기본값
enum('phoneNumber', 'link', 'email', 'none', 'all')'none'

disabled
Android

텍스트 뷰의 비활성화 상태를 테스트 목적으로 지정한다.

타입기본값
boolfalse

dynamicTypeRamp
iOS

iOS에서 이 엘리먼트에 적용할 Dynamic Type 램프를 설정한다.

타입기본값
enum('caption2', 'caption1', 'footnote', 'subheadline', 'callout', 'body', 'headline', 'title3', 'title2', 'title1', 'largeTitle')'body'

ellipsizeMode

numberOfLines가 설정되었을 때, 이 prop은 텍스트가 어떻게 잘릴지 정의한다. 이 prop은 numberOfLines와 함께 설정해야 한다.

이 prop은 다음과 같은 값 중 하나를 가질 수 있다:

  • head - 줄의 끝이 컨테이너에 맞도록 표시되며, 줄의 시작 부분에서 누락된 텍스트는 생략 부호(...)로 표시된다. 예: "...wxyz"
  • middle - 줄의 시작과 끝이 컨테이너에 맞도록 표시되며, 중간 부분에서 누락된 텍스트는 생략 부호(...)로 표시된다. 예: "ab...yz"
  • tail - 줄의 시작이 컨테이너에 맞도록 표시되며, 줄의 끝 부분에서 누락된 텍스트는 생략 부호(...)로 표시된다. 예: "abcd..."
  • clip - 텍스트 컨테이너의 경계를 넘어가는 부분은 그리지 않는다.

Android에서는 numberOfLines1보다 큰 값으로 설정되었을 때, tail 값만 정상적으로 동작한다.

타입기본값
enum('head', 'middle', 'tail', 'clip')tail

id

이 속성은 네이티브 코드에서 해당 뷰를 찾는 데 사용된다. nativeID 속성보다 우선순위가 높다.

타입
string

maxFontSizeMultiplier

allowFontScaling이 활성화된 상태에서 폰트가 도달할 수 있는 최대 크기 비율을 지정한다. 가능한 값은 다음과 같다:

  • null/undefined: 부모 노드나 전역 기본값을 상속받는다 (기본값은 0)
  • 0: 최대 크기 제한 없음, 부모/전역 기본값을 무시한다
  • >= 1: 이 노드의 maxFontSizeMultiplier를 해당 값으로 설정한다
타입기본값
numberundefined

minimumFontScale
iOS

adjustsFontSizeToFit이 활성화된 상태에서 폰트가 도달할 수 있는 가장 작은 크기 비율을 지정한다. (값 범위: 0.01-1.0).

타입
number

nativeID

이 속성은 네이티브 코드에서 해당 뷰를 식별하기 위해 사용된다.

타입
string

numberOfLines

텍스트 레이아웃을 계산한 후, 줄 바꿈을 포함하여 총 줄 수가 이 값을 초과하지 않도록 텍스트를 생략 부호(...)로 잘라낸다. 이 값을 0으로 설정하면 이 값이 해제되어 줄 수 제한이 적용되지 않는다.

이 속성은 주로 ellipsizeMode와 함께 사용된다.

타입기본값
number0

onLayout

마운트 시와 레이아웃 변경 시 호출된다.

타입
({nativeEvent: LayoutEvent}) => void

onLongPress

이 함수는 길게 누를 때 호출된다.

타입
({nativeEvent: PressEvent}) => void

onMoveShouldSetResponder

이 뷰가 터치 응답성을 "요청"하려는지 여부를 결정한다. 뷰가 현재 응답자가 아닐 때, 뷰에서 발생하는 모든 터치 이동에 대해 이 함수가 호출된다.

타입
({nativeEvent: PressEvent}) => boolean

onPress

사용자가 눌렀을 때 호출되는 함수로, onPressOut 이후에 트리거된다.

타입
({nativeEvent: PressEvent}) => void

onPressIn

터치가 시작되자마자 즉시 호출된다. onPressOutonPress 이전에 발생한다.

타입
({nativeEvent: PressEvent}) => void

onPressOut

터치가 해제될 때 호출된다.

타입
({nativeEvent: PressEvent}) => void

onResponderGrant

이제 뷰가 터치 이벤트에 반응하기 시작한다. 이 시점에서 사용자에게 어떤 일이 일어나고 있는지 강조하고 보여줄 수 있다.

안드로이드에서는 이 콜백에서 true를 반환하면, 현재 응답자가 종료될 때까지 다른 네이티브 컴포넌트가 응답자가 되는 것을 막을 수 있다.

타입
({nativeEvent: PressEvent}) => void | boolean

onResponderMove

사용자가 손가락을 움직이고 있다.

타입
({nativeEvent: PressEvent}) => void

onResponderRelease

터치가 끝날 때 발생한다.

타입
({nativeEvent: PressEvent}) => void

onResponderTerminate

View에서 응답자(responder)가 제거된다. 이는 onResponderTerminationRequest 호출 후 다른 뷰가 응답자를 가져갈 때 발생할 수도 있고, iOS의 컨트롤 센터나 알림 센터처럼 운영체제가 묻지도 않고 가져갈 때도 발생한다.

타입
({nativeEvent: PressEvent}) => void

onResponderTerminationRequest

다른 View가 응답자(responder)가 되려고 하며, 현재 View에게 응답자 권한을 해제할 것을 요청한다. true를 반환하면 응답자 권한을 해제한다.

타입
({nativeEvent: PressEvent}) => boolean

onStartShouldSetResponderCapture

부모 View가 자식 View가 터치 시작 시 responder가 되는 것을 막으려면, 이 핸들러를 사용해 true를 반환해야 한다.

타입
({nativeEvent: PressEvent}) => boolean

onTextLayout

텍스트 레이아웃이 변경될 때 호출된다.

타입
(TextLayoutEvent) => mixed

pressRetentionOffset

스크롤 뷰가 비활성화된 상태에서, 버튼이 비활성화되기 전에 터치가 버튼을 얼마나 벗어날 수 있는지를 정의한다. 버튼이 비활성화된 후, 다시 버튼으로 터치를 옮기면 버튼이 다시 활성화되는 것을 확인할 수 있다. 스크롤 뷰가 비활성화된 상태에서 이 동작을 여러 번 반복해 보자. 메모리 할당을 줄이기 위해 상수 값을 전달해야 한다.

타입
Rect, number

role

role은 보조 기술 사용자에게 컴포넌트의 목적을 전달한다. accessibilityRole 속성보다 우선순위가 높다.

타입
Role

selectable

사용자가 텍스트를 선택할 수 있게 해주어, 기본 복사 및 붙여넣기 기능을 사용할 수 있게 한다.

타입기본값
booleanfalse

selectionColor
Android

텍스트의 강조 색상을 지정한다.

타입
color

style

타입
텍스트 스타일, 뷰 스타일 프로퍼티

suppressHighlighting
iOS

true로 설정하면 텍스트를 눌렀을 때 시각적 변화가 발생하지 않는다. 기본적으로는 텍스트를 누르면 회색 타원형으로 강조 표시된다.

타입기본값
booleanfalse

testID

이 속성은 엔드투엔드 테스트에서 해당 뷰를 찾는 데 사용한다.

타입
string

textBreakStrategy
Android

Android API Level 23 이상에서 텍스트 줄바꿈 전략을 설정한다. 가능한 값은 simple, highQuality, balanced이다.

타입기본값
enum('simple', 'highQuality', 'balanced')highQuality

lineBreakStrategyIOS
iOS

iOS 14 이상에서 라인 브레이크 전략을 설정한다. 가능한 값은 none, standard, hangul-word, push-out이다.

타입기본값
enum('none', 'standard', 'hangul-word', 'push-out')'none'

타입 정의

TextLayout

TextLayout 객체는 TextLayoutEvent 콜백의 일부로, Text 라인의 측정 데이터를 포함한다.

예제

js
{
capHeight: 10.496,
ascender: 14.624,
descender: 4,
width: 28.224,
height: 18.624,
xHeight: 6.048,
x: 0,
y: 0
}

속성

이름타입선택 가능설명
ascendernumberNo텍스트 레이아웃 변경 후 줄의 윗부분 높이.
capHeightnumberNo기준선 위 대문자 높이.
descendernumberNo텍스트 레이아웃 변경 후 줄의 아랫부분 높이.
heightnumberNo텍스트 레이아웃 변경 후 줄의 높이.
widthnumberNo텍스트 레이아웃 변경 후 줄의 너비.
xnumberNoText 컴포넌트 내에서 줄의 X 좌표.
xHeightnumberNo기준선과 줄의 중간선 사이 거리 (본문 크기).
ynumberNoText 컴포넌트 내에서 줄의 Y 좌표.

텍스트 레이아웃 이벤트

TextLayoutEvent 객체는 컴포넌트 레이아웃 변경의 결과로 콜백에서 반환된다. 이 객체는 lines라는 키를 포함하며, 이 키의 값은 렌더링된 각 텍스트 줄에 해당하는 TextLayout 객체를 담은 배열이다.

예제

js
{
lines: [
TextLayout,
TextLayout,
// ...
];
target: 1127;
}

속성

이름타입선택 사항설명
linesTextLayout 배열아니오렌더링된 각 줄에 대한 TextLayout 데이터 제공.
target숫자아니오엘리먼트의 노드 ID.