개요

Text는 스타일이 지정된 텍스트를 표시하는 기본 위젯입니다.

Text 위젯은 단일 스타일의 텍스트를 표시합니다. 문자열은 여러 줄에 걸쳐 표시되거나 레이아웃 제약에 따라 한 줄에 모두 표시될 수 있습니다. style 속성을 사용하여 텍스트의 모양을 사용자 정의할 수 있습니다. 여러 스타일을 사용해야 하는 경우 Text.rich 생성자를 사용하거나 RichText 위젯을 직접 사용할 수 있습니다.

언제 사용하나요?

  • 화면에 텍스트를 표시할 때
  • 제목, 본문, 레이블 등을 표시할 때
  • 단일 스타일의 텍스트가 필요할 때
  • 텍스트 오버플로우 처리가 필요할 때
  • 텍스트 정렬이 필요할 때

기본 사용법

// 기본 텍스트
Text('안녕하세요, Flitter!')

// 스타일이 적용된 텍스트
Text('스타일 텍스트', {
  style: TextStyle({
    fontSize: 24,
    fontWeight: 'bold',
    color: 'blue'
  })
})

// 여러 스타일을 가진 텍스트 (Text.rich)
Text.rich(
  TextSpan({
    text: '안녕하세요 ',
    children: [
      TextSpan({
        text: 'Flitter',
        style: TextStyle({ color: 'blue', fontWeight: 'bold' })
      }),
      TextSpan({ text: '!' })
    ]
  })
)

생성자

Text(data, props?)

기본 생성자로 단일 스타일의 텍스트를 생성합니다.

Text('기본 텍스트')
Text('스타일 텍스트', { style: TextStyle({ fontSize: 18 }) })

Text.rich(textSpan, props?)

여러 스타일을 가진 텍스트를 생성합니다.

Text.rich(
  TextSpan({
    text: '기본 텍스트 ',
    style: TextStyle({ fontSize: 16 }),
    children: [
      TextSpan({
        text: '강조된 텍스트',
        style: TextStyle({ fontWeight: 'bold', color: 'red' })
      })
    ]
  })
)

Props

style

값: TextStyle | undefined

텍스트의 스타일을 정의합니다. null인 경우 기본 텍스트 스타일이 사용됩니다.

Text('스타일 텍스트', {
  style: TextStyle({
    fontSize: 20,
    fontWeight: 'bold',
    color: '#333333'
  })
})

textAlign

값: TextAlign | undefined

텍스트의 가로 정렬을 정의합니다.

사용 가능한 값:

  • TextAlign.left: 왼쪽 정렬
  • TextAlign.right: 오른쪽 정렬
  • TextAlign.center: 가운데 정렬
  • TextAlign.justify: 양쪽 정렬
  • TextAlign.start: 시작 방향 정렬 (LTR에서는 왼쪽)
  • TextAlign.end: 끝 방향 정렬 (LTR에서는 오른쪽)
Text('가운데 정렬된 텍스트', {
  textAlign: TextAlign.center
})

overflow

값: TextOverflow | undefined

텍스트가 공간을 초과할 때의 처리 방법입니다.

사용 가능한 값:

  • TextOverflow.clip: 잘라냄 (기본값)
  • TextOverflow.fade: 페이드 아웃
  • TextOverflow.ellipsis: 말줄임표(…) 표시
  • TextOverflow.visible: 오버플로우 허용
Text('아주 긴 텍스트가 여기에 표시됩니다...', {
  overflow: TextOverflow.ellipsis
})

softWrap

값: boolean | undefined (기본값: true)

텍스트가 줄바꿈될지 여부를 결정합니다.

Text('긴 텍스트는 자동으로 줄바꿈됩니다', {
  softWrap: true  // 줄바꿈 허용
})

Text('이 텍스트는 한 줄에만 표시됩니다', {
  softWrap: false  // 줄바꿈 금지
})

textDirection

값: TextDirection | undefined

텍스트의 방향을 지정합니다.

사용 가능한 값:

  • TextDirection.ltr: 왼쪽에서 오른쪽
  • TextDirection.rtl: 오른쪽에서 왼쪽
Text('مرحبا بالعالم', {
  textDirection: TextDirection.rtl
})

textWidthBasis

값: TextWidthBasis | undefined

텍스트 너비 계산 방식을 정의합니다.

사용 가능한 값:

  • TextWidthBasis.parent: 부모 너비 기준 (기본값)
  • TextWidthBasis.longestLine: 가장 긴 줄 기준
Text('여러 줄의\n텍스트', {
  textWidthBasis: TextWidthBasis.longestLine
})

TextStyle 속성

TextStyle은 텍스트의 시각적 속성을 정의합니다.

color

값: string | undefined

텍스트 색상입니다.

TextStyle({ color: 'blue' })
TextStyle({ color: '#FF5733' })
TextStyle({ color: 'rgba(255, 0, 0, 0.5)' })

fontSize

값: number | undefined

글꼴 크기입니다 (픽셀 단위).

TextStyle({ fontSize: 16 })  // 16px
TextStyle({ fontSize: 24 })  // 24px

fontWeight

값: string | undefined

글꼴 두께입니다.

사용 가능한 값:

  • 'normal' 또는 '400'
  • 'bold' 또는 '700'
  • '100' ~ '900' (100 단위)
TextStyle({ fontWeight: 'bold' })
TextStyle({ fontWeight: '600' })

fontStyle

값: FontStyle | undefined

글꼴 스타일입니다.

사용 가능한 값:

  • FontStyle.normal: 일반
  • FontStyle.italic: 이탤릭
TextStyle({ fontStyle: FontStyle.italic })

fontFamily

값: string | undefined

사용할 글꼴 패밀리입니다.

TextStyle({ fontFamily: 'Roboto' })
TextStyle({ fontFamily: 'Arial, sans-serif' })

height

값: number | undefined

줄 높이를 글꼴 크기의 배수로 지정합니다.

TextStyle({ 
  fontSize: 16,
  height: 1.5  // 줄 높이는 24px (16 * 1.5)
})

inherit

값: boolean (기본값: true)

부모의 텍스트 스타일을 상속할지 여부입니다.

TextStyle({ 
  inherit: false,  // 부모 스타일 무시
  fontSize: 20
})

실제 사용 예제

예제 1: 제목과 본문

const ArticleHeader = () => {
  return Column({
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Text('Flutter에서 Flitter로', {
        style: TextStyle({
          fontSize: 28,
          fontWeight: 'bold',
          color: '#1a1a1a'
        })
      }),
      SizedBox({ height: 8 }),
      Text('JavaScript로 Flutter 앱을 만드는 새로운 방법', {
        style: TextStyle({
          fontSize: 16,
          color: '#666666',
          height: 1.5
        })
      }),
      SizedBox({ height: 4 }),
      Text('2024년 1월 10일 • 5분 읽기', {
        style: TextStyle({
          fontSize: 14,
          color: '#999999'
        })
      })
    ]
  });
};

예제 2: 말줄임표가 있는 카드

const ProductCard = ({ title, description, price }) => {
  return Container({
    padding: EdgeInsets.all(16),
    decoration: BoxDecoration({
      color: 'white',
      borderRadius: BorderRadius.circular(8),
      boxShadow: [
        BoxShadow({
          color: 'rgba(0, 0, 0, 0.1)',
          blurRadius: 4,
          offset: { x: 0, y: 2 }
        })
      ]
    }),
    child: Column({
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(title, {
          style: TextStyle({
            fontSize: 18,
            fontWeight: 'bold'
          }),
          overflow: TextOverflow.ellipsis
        }),
        SizedBox({ height: 8 }),
        Text(description, {
          style: TextStyle({
            fontSize: 14,
            color: '#666666',
            height: 1.4
          }),
          overflow: TextOverflow.ellipsis,
          softWrap: true
        }),
        SizedBox({ height: 12 }),
        Text(`₩${price.toLocaleString()}`, {
          style: TextStyle({
            fontSize: 20,
            fontWeight: 'bold',
            color: '#FF5733'
          })
        })
      ]
    })
  });
};

예제 3: 스타일이 혼합된 텍스트

const TermsText = () => {
  return Text.rich(
    TextSpan({
      text: '계속하시면 저희 ',
      style: TextStyle({ fontSize: 14, color: '#666' }),
      children: [
        TextSpan({
          text: '이용약관',
          style: TextStyle({ 
            color: 'blue',
            fontWeight: 'bold'
          })
        }),
        TextSpan({ text: ' 및 ' }),
        TextSpan({
          text: '개인정보 처리방침',
          style: TextStyle({ 
            color: 'blue',
            fontWeight: 'bold'
          })
        }),
        TextSpan({ text: '에 동의하는 것으로 간주됩니다.' })
      ]
    })
  );
};

예제 4: 채팅 메시지

const ChatMessage = ({ message, isMe, time }) => {
  return Container({
    margin: EdgeInsets.symmetric({ horizontal: 16, vertical: 4 }),
    alignment: isMe ? Alignment.centerRight : Alignment.centerLeft,
    child: Container({
      padding: EdgeInsets.symmetric({ horizontal: 12, vertical: 8 }),
      decoration: BoxDecoration({
        color: isMe ? '#007AFF' : '#E5E5EA',
        borderRadius: BorderRadius.circular(18)
      }),
      constraints: Constraints({ maxWidth: 250 }),
      child: Column({
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          Text(message, {
            style: TextStyle({
              fontSize: 16,
              color: isMe ? 'white' : 'black'
            })
          }),
          SizedBox({ height: 2 }),
          Text(time, {
            style: TextStyle({
              fontSize: 12,
              color: isMe ? 'rgba(255, 255, 255, 0.7)' : '#999999'
            })
          })
        ]
      })
    })
  });
};

예제 5: 가격 표시

const PriceDisplay = ({ originalPrice, salePrice, discountRate }) => {
  return Row({
    crossAxisAlignment: CrossAxisAlignment.baseline,
    textBaseline: TextBaseline.alphabetic,
    children: [
      if (originalPrice !== salePrice) ...[
        Text(`₩${originalPrice.toLocaleString()}`, {
          style: TextStyle({
            fontSize: 14,
            color: '#999999',
            decoration: 'line-through'
          })
        }),
        SizedBox({ width: 8 })
      ],
      Text(`₩${salePrice.toLocaleString()}`, {
        style: TextStyle({
          fontSize: 24,
          fontWeight: 'bold',
          color: '#1a1a1a'
        })
      }),
      if (discountRate > 0) ...[
        SizedBox({ width: 8 }),
        Text(`${discountRate}%`, {
          style: TextStyle({
            fontSize: 18,
            fontWeight: 'bold',
            color: '#FF5733'
          })
        })
      ]
    ]
  });
};

주의사항

  • overflow 속성은 softWrap이 false이거나 텍스트가 한 줄로 제한될 때 가장 효과적입니다.
  • fontFamily를 사용할 때는 해당 폰트가 시스템에 설치되어 있거나 앱에 포함되어 있어야 합니다.
  • height는 줄 간격을 조정하는 데 사용되며, fontSize의 배수로 작동합니다.
  • Text.rich를 사용할 때 기본 style은 모든 TextSpan에 상속됩니다 (inherit가 true인 경우).

관련 위젯

  • RichText: 더 복잡한 텍스트 스타일링이 필요한 경우
  • TextField: 사용자 입력을 받을 때
  • SelectableText: 선택 가능한 텍스트가 필요한 경우
  • DefaultTextStyle: 하위 트리의 기본 텍스트 스타일을 정의할 때