Jetpack Compose로 UI를 만들다 보면 Text 컴포넌트의 위치가 미묘하게 어긋나거나, 상하 여백이 어색하게 느껴지는 경우가 있습니다.
이런 문제는 대부분 Font Padding, Baseline 정렬, LineHeight 같은 텍스트 관련 속성을 상황에 맞게 설정하지 않아서 발생합니다.
이번 포스팅에서는 각 속성이 어떤 역할을 하는지, 그리고 어떤 상황에서 어떤 속성을 조절해야 자연스러운 텍스트 UI를 만들 수 있는지 알아보겠습니다.
1. Font Padding
Jetpack Compose에서 Text 컴포넌트를 사용할 때, 의도하지 않은 위아래 여백이 생긴다고 느껴본 적 있으신가요?
그 이유는 Font Padding 때문입니다. Text는 기본적으로 폰트 자체에 정의된 패딩을 포함하는데, 이 여백은 우리가 직접 설정하지 않아도 자동으로 적용됩니다. 이러한 기본 패딩은 각 폰트의 디자인에 따라 다르게 설정되어 있으며, 텍스트 위·아래에 불필요한 공간이 생기는 주된 원인이 됩니다.
Font Padding이 적용되었을 때 문제점

위 사진은 실제로 텍스트에 폰트만 적용한 경우입니다. 아무런 패딩을 주지 않았는데도, Font Padding 의해 의도하지 않은 공간을 차지하고 있습니다.
따라서, Font Padding은 텍스트 주변에 여백이 추가되어, 실제 UI의 높이가 예상보다 커질 수 있습니다. 이로 인해, 디자이너가 제공한 스펙과 다르게 구현될 가능성이 크게되죠.
그렇다면 이 자체적으로 폰트에서 적용되는 패딩을 비활성화할 수는 없을까요?
다행히도 Jetpack Compose에서는 이 기본 패딩을 제거할 수 있는 방법을 제공합니다.
Text(
text = "텍스트",
style = TextStyle(
platformStyle = PlatformTextStyle(
includeFontPadding = false // 폰트 패딩 제거
)
)
)
위 설정을 해주게 되면 폰트 자체적으로 적용되는 패딩을 제거할 수 있게됩니다.
2. 베이스라인(Baseline)
Baseline은 텍스트에서 문자의 바닥 부분이 맞춰지는 수평 기준선입니다. 대부분의 문자(예: 한글, 알파벳)는 이 선을 기준으로 정렬되며, 아래쪽으로 꼬리가 내려가는 g, y 같은 문자는 베이스라인 아래로 튀어나오게 됩니다.
Jetpack Compose에서는 Modifier.alignByBaseline()이나 Modifier.firstBaselineToTop()을 사용해 정밀한 텍스트 정렬이 가능합니다. 특히 Row나 Column 내에서 여러 텍스트 컴포넌트를 균형 있게 정렬할 때 유용합니다.
베이스라인 정렬이 없을 때 생기는 문제점
만약 정해지지 않은 높이의 한 줄에 여러 크기의 Text가 존재한다고 할 때, 이 Text들이 만약 중앙 정렬된다면 어떻게 될까요?
이를 코드로 한 번 만들어보겠습니다. 다음의 MultipleTextRow는 Row의 verticalAlignment 속성을 Alignment.Center로 설정해서 두 개의 Text를 중앙 정렬합니다.
@Composable
fun MultipleTextRow() {
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text(text = "Hello", fontSize = 16.sp)
Text(text = "Dev World", fontSize = 28.sp)
}
}
위 코드를 Preview를 통해 확인하면 다음 그림과 같습니다.

텍스트가 이쁘게 정렬되지 않는 것을 확인할 수 있습니다. 이러한 이유는 텍스트가 정렬되는 기준선이 다르기 때문입니다.
실제로 verticalAlignment를 Alignment.Center가 아닌, Alignment.Bottom으로 설정하면 확실히 문제가 됨을 확인할 수 있습니다.

그럼 이렇게 표시되는 이유가 무엇일까요?
바로 텍스트의 기준선이 Text Composable의 높이에 의해 결정되기 때문입니다. 따라서 높이가 다른 두개의 Text들은 서로 다른 기준선을 가질 수 밖에 없습니다.
이를 해결하기 위해서 안드로이드 컴포즈에서는 alignByBaseline이라는 솔루션을 제공합니다. 이를 사용하면 자식 Composable들의 baseline 좌표를 같은 위치에 정렬시킴으로써 원하는 디자인에 맞게 정렬할 수 있습니다.
다음은 위의 문제가 되는 코드를 alignByBaaseline을 통해 정렬한 코드입니다.
@Composable
fun MultipleTextRowAligned() {
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
Text(modifier = Modifier.alignByBaseline(), text = "Hello", fontSize = 16.sp)
Text(modifier = Modifier.alignByBaseline(), text = "Dev World", fontSize = 28.sp)
}
}
이를 Preview로 확인하면 다음음 사진과 같습니다.

이제 기준선이 정렬된 것을 확인할 수 있습니다.
(빨간 선은 정렬이 제대로 되는지 확인하기 위해 직접 넣은 선입니다.)
한줄에 있는 여러개의 텍스트를 깔끔하기 정렬하기를 원한다면 alignByBaseline를 사용할 것을 권장합니다.
3. LineHeight (줄 간격)
LineHeight는 텍스트 라인의 높이를 정의합니다.
글자가 커지면 자연스럽게 줄 간격도 늘어나지만, 가독성을 위해 TextStyle에 LineHeight를 별도로 지정하는 경우가 많습니다.

하지만, 우리가 TextStyle에 LineHeight 를 적용하더라도 디자인과 미묘하게 다른 경험을 한번 씩 해보셨을 겁니다.
이건 안드로이드에서 LineHeight의 정의가 텍스트 baseline 사이의 거리 이기 때문입니다.
흔히 생각할 수 있는 LineHeight는 다음과 같이 텍스트 상자의 위부터 아래까지 전체 높이일 것입니다.

하지만, 실제로 LineHeight는 한 줄의 baseline과 다음 줄의 baseline 사이 거리를 의미합니다.

그렇기 때문에, 텍스트가 한줄일 땐 위아래에 baseline이 없으니 LineHeight가 적용되지 않는 것입니다.
여러줄인 경우에도 맨 윗줄과 맨 아랫줄은 각 위아래에 baseline이 없으니 마찬가지로 LineHeight가 적용되지 않습니다.
그런데 Figma에서 텍스트를 표시할 땐 1번처럼 LineHeight가 적용됩니다. 여기서 디자인과 개발 결과가 다른 현상이 발생하는 거죠.
그렇다면 이를 어떻게 해결할 수 있을까요?
이건 Text의 TextStyle을 통해서 수정할 수 있습니다.
실제로 TextStyle 코드를 보면 LineHeightStyle 항목을 볼 수 있는데요.


TextStyle의 lineHeightStyle에 null을 넘겨주면 LineHeightStyle의 Default가 사용되는데,
여기서 trim의 값이 Trim.Both로 설정된 걸 보실 수 있습니다.

Trim 클래스에는 4가지 상수가 있는데 이중 Both의 설명을 읽어보면,
“첫 번째 줄의 위쪽과 마지막 줄의 아래쪽에 줄 높이로 인해 추가되는 여백을 잘라냅니다.”
라는 문장이 있습니다.


즉, 위 이미지의 노란색 영역이 Trim.Both 설정으로 제거되는 것이 기본 설정인 것입니다.
따라서 LineHeight는 첫째 줄의 윗 부분과 마지막째 줄의 아랫 부분에 여백이 제외되어서 예상과는 다른 높이를 갖게 되는 것입니다.
예를 들면, lineHeight가 20일 때 text 높이가 16이라고 가정한다면 아래의 높이를 갖게 됩니다.
- 1줄 일 때 : 16
- 2줄 일 때 : 16 + 20
- 3줄 일 때 : 16 + 20 + 20
결국 Trim.Both라는 디폴트 설정때문에 Figma의 텍스트 높이와 개발 결과의 텍스트 높이가 다르게 됩니다.
이걸 Trim.None 으로 위아래 space를 제거하지 않도록 함으로써 텍스트의 lineHeight 높이를 유지할 수 있습니다.
여기까지 설정했을 때, 텍스트의 높이는 맞지만 실제로 텍스트가 그려지는 영역이 높이의 중간이 아닐 수 있는데요.
이건 LineHeightStyle의 나머지 항목인 Alignment 설정을 통해 해결할 수 있습니다.

기본값은 Alignment.Proportional 입니다.
이 값은 사용하는 Font metrics를 따라가기때문에 텍스트가 중간에 위치하지 않을 수 있는데요.
Alignment.Center로 설정함으로써 텍스트를 높이 중간에 위치시킬 수 있습니다.
val lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None
)
결과적으로, 위 코드와 같이 lineHeightStyle을 설정함으로써 Figma의 텍스트 디자인과 개발 결과가 동일하도록 만들 수 있습니다.
마치며
Compose에서 텍스트는 단순한 UI 요소 같지만, 실제 앱에서 가장 많은 정보를 담는 중요한 구성 요소입니다. 텍스트의 정렬과 간격을 세심하게 다루면 전체 UI의 완성도가 올라갑니다.
끝.
참고자료
[Compose] Font에 적용되는 Padding 제거하기
[Compose] Font에 적용되는 Padding 제거하기
토이 프로젝트를 진행하던 도중, Text Component에 알 수 없는 padding이 적용된 것을 확인하였습니다. 기본적으로 적용되는 Padding을 제거하고, 커스텀하게 UI를 제공해주기 위해 해결방법을 찾아보던
rien-atelier.tistory.com
[Compose Text] alignByBaseLine 사용해 텍스트 기준선 정렬하기 — 조세영의 Kotlin World
[Compose Text] alignByBaseLine 사용해 텍스트 기준선 정렬하기
Text의 기준선이 필요한 이유 우리가 노트 앱을 만든다고 해보자. 노트 앱은 다양한 크기의 문자들이 들어간다. 만약 정해지지 않은 높이의 한 줄에 여러 크기의 Text가 존재한다고 할 때, 이 Text들
kotlinworld.com
[Compose] 디자인과 Text 높이 맞추는 방법 😉— LineHeightStyle | by Minseon Cho | Medium
[Compose] Text 한 줄일 때 LineHeight 적용하는 방법 — 디자인과 Text 높이 맞추는 방법😉
Compose에서 TextStyle로 앱에 사용되는 텍스트 스타일을 미리 정의해놓고 쓰는 경우가 많은데요.
medium.com
[Android/Foundation] 안드로이드에서 LineHeight 속성이 타 플랫폼과 다른 이유 :: 경문이네 개발 일지
[Android/Foundation] 안드로이드에서 LineHeight 속성이 타 플랫폼과 다른 이유
안드로이드 개발을 하다보면 디자이너가 전달준 텍스트 컴포넌트 스펙을 그대로 사용했는데도왠지 모르게 디자인이 묘하게 달라 보일 때가 있습니다.왼쪽은 기본 Text고 오른쪽은 이 글의 내용
developer-munny.tistory.com
'Android > Compose' 카테고리의 다른 글
| [Android] Compose에서 이미지를 자유자재로 커스터마이징 해보기 (0) | 2025.09.17 |
|---|---|
| [Android] Compose의 staticCompositionLocalOf와 compositionLocalOf의 차이 (0) | 2025.08.30 |
| [Android] Compose의 ConstraintLayout (1) | 2025.06.05 |
| [Android] Compose 레이아웃에서 Intrinsic 측정 (0) | 2025.06.02 |
| [Android] Compose의 정렬선(Alignment lines) (1) | 2025.06.02 |