모바일 개발에서의 Descender — 본질, 의미 및 레이아웃 영향

저자: IT Sectr 게시일: 2026-07-24 읽는 시간: 9 분

Descender는 글꼴의 기준선(baseline) 아래로 내려가는 소문자의 일부입니다. 라틴 문자에서 descender가 있는 대표적인 문자는 “g”, “j”, “p”, “q”, “y”입니다. Descender의 길이는 글꼴의 아래 돌출 요소를 결정하며 줄 간격 계산에 매우 중요합니다. 기준선 아래에 충분한 공간이 없으면 descender가 있는 문자가 다음 줄과 충돌합니다. Material Design Type Scale Guidelines(2025)에 따르면, descender를 충분히 고려하지 않는 것은 모바일 기기에서 여러 줄 텍스트의 줄 충돌 주요 원인 중 하나입니다.

핵심 요점

  • Descender — 기준선 아래에 위치한 문자의 아래 돌출 요소.
  • 메트릭 — descender는 UIFont.descender(iOS) 및 Paint.FontMetrics.descent(Android)를 통해 접근 가능.
  • Line-height — descender는 줄 전체 높이 계산에 포함되며 레이아웃에서 고려해야 함.
  • 줄 충돌 — descender를 고려하지 않으면 descender가 있는 문자가 아래 줄과 충돌.
  • 다른 글꼴 — descender 길이는 서체에 따라 달라지며 시각적 리듬에 영향을 줌.

타이포그래피에서 Descender란

Descender는 글리프의 기준선 아래에 위치한 부분입니다. 문자의 본체는 기준선 위에 놓이지만, descender는 그 너머로 확장되어 글꼴의 특징적인 실루엣을 만듭니다. 라틴 알파벳에서 descender가 있는 문자는 “g”, “j”, “p”, “q”, “y”이며, 아래 요소가 줄 아래로 내려갑니다.

Descender의 깊이는 기준선에서 글리프의 아래쪽 가장자리(descender-line)까지의 거리를 나타냅니다. 품질 좋은 글꼴에서는 이 거리가 균형을 이룹니다. descender가 너무 짧으면 descender가 있는 문자를 인식하기 어려워지고, 너무 길면 줄 사이에 과도한 빈 공간이 생겨 텍스트 밀도가 감소합니다. 다양한 서체는 descender 길이에서 상당한 차이를 보입니다.

서체Descender / em-sizedescender가 있는 문자 예시
SF Pro~0.22g, j, p, q, y — 균형 잡힌 돌출
Roboto~0.24g, j, p — 적당한 descender
Playfair Display~0.30g, j, p, q — 긴 장식 요소
Inter~0.26g, j, p — 기준선 아래 현저히
Noto Sans~0.20g, j — 짧은 descender, 컴팩트

Google Fonts Metrics Guide(2025)에 따르면, descender의 깊이가 전체 em 크기(1000 FUnits)의 20–25%일 때 최적으로 간주됩니다. 15% 미만의 값은 descender가 있는 문자를 구별하기 어렵게 만들고, 30%를 초과하는 값은 줄 충돌을 방지하기 위해 line-height를 강제로 증가시켜야 합니다.

Descender의 디지털 메트릭: OpenType 및 TrueType

디지털 글꼴에서 descender는 메트릭 테이블에 음수 값으로 저장됩니다. OpenType 형식에서는 hhea.descent 필드(hhea 테이블)와 sTypoDescender(OS/2 테이블)입니다. 두 값 모두 기준선에서 아래쪽으로 측정되므로 음수입니다. TrueType의 경우 OS/2 테이블이 usWinDescent 필드와 함께 사용됩니다 — 값은 양수이지만 동일한 메트릭을 나타냅니다.

python
# fontTools를 통해 글꼴에서 descender 읽기
from fontTools.ttLib import TTFont

font = TTFont('Roboto-Regular.ttf')
hhea = font['hhea']
os2 = font['OS/2']

descent_hhea = hhea.descent        # -500 FUnits (Roboto)
typo_descender = os2.sTypoDescender # -500 FUnits
win_descent = os2.usWinDescent      # 500 (positive value)

# 16pt 글꼴 크기에 대해 픽셀로 변환
px_per_em = 16
descent_px = abs(descent_hhea) * px_per_em / 1000  # 8 px

플랫폼 간 중요한 차이점: iOS는 렌더링에 hhea.descent를 사용하는 반면, Android는 OS/2의 sTypoDescender를 사용합니다. 이러한 값이 다른 경우(잘못 구성된 글꼴에서 발생), 동일한 텍스트가 iOS와 Android에서 다른 줄 간격으로 표시됩니다. 100 FUnits(16pt 글꼴 크기에서 약 1.6px)의 차이는 이미 시각적으로 눈에 띕니다.

Microsoft OpenType Specification v1.9(2025)에 따르면, 올바른 크로스 플랫폼 렌더링을 위해 hhea.descent와 sTypoDescender 값이 50 FUnits 정확도 내에서 동일해야 합니다. 모바일 애플리케이션용 글꼴을 선택할 때는 fontTools 또는 유사한 유틸리티를 통해 이를 확인해야 합니다.

iOS에서 Descender: UIFont 및 Core Graphics

iOS에서 descender 값은 UIFont.descender 속성을 통해 사용할 수 있습니다. 이 속성은 기준선에서 글꼴의 아래쪽 가장자리(descender 포함)까지의 거리를 나타내는 음수를 반환합니다. 예를 들어, 17pt의 SF Pro의 경우 descender 값은 약 -4.2pt입니다. 절대값이 클수록 글꼴의 아래 돌출 부분이 길어집니다.

swift
// iOS에서 UIFont를 통해 descender 가져오기
let font = UIFont.systemFont(ofSize: 17)
let descender = font.descender     // ~ -4.2 pt (SF Pro 17pt)
let ascender = font.ascender        // ~ 16.2 pt
let lineHeight = font.lineHeight    // ~ 20.4 pt

// descender 오프셋을 사용한 사용자 정의 렌더링
let attrString = NSAttributedString(
    string: "Sample text with letter p and y",
    attributes: [.font: font]
)

// Core Text: descender가 포함된 경계 상자 가져오기
let ctFont = CTFontCreateWithName(
    "SF Pro Text" as CFString, 17, nil
)
let descent = CTFontGetDescent(ctFont)  // ~4.2 pt

TextKit(NSTextStorage, NSLayoutManager)을 사용할 때 descender는 lineFragmentPadding 및 lineFragmentRect에 자동으로 포함됩니다. 그러나 Core Graphics(draw(in:))를 통한 사용자 정의 렌더링 시에는 컨테이너의 아래쪽 여백에 descender의 절대값을 추가하여 좌표를 수동으로 조정해야 합니다. 그렇지 않으면 descender가 있는 문자가 렌더링 범위를 벗어나 잘립니다.

Android에서 Descender: Paint 및 Compose

Android에서 descender 메트릭은 Paint.FontMetrics.descent를 통해 사용할 수 있습니다. iOS와 달리 descent 값은 양수입니다 — 기준선에서 텍스트의 아래쪽 가장자리까지의 거리를 나타냅니다. FontMetrics.bottom 속성에는 descender뿐만 아니라 글꼴 디자이너가 권장하는 추가 공간(leading)도 포함됩니다. descender만 정확하게 계산하려면 bottom 대신 descent를 사용하세요.

kotlin
// Android에서 Paint를 통해 descender 가져오기
val paint = Paint().apply {
    textSize = 17 * density
}

val metrics = paint.fontMetrics
val descent = metrics.descent     // ~4.5 px (17sp)
val bottom = metrics.bottom       // ~5.0 px (leading 포함)

// descender 오프셋을 사용한 사용자 정의 렌더링
val baseline = y
canvas.drawText("샘플: gpq", x, baseline, paint)

// descender가 포함된 아래쪽 경계
val bottomBound = baseline + descent  // 올바른 아래쪽 경계

Jetpack Compose에서 descender는 TextLayoutResult를 통해 얻을 수 있습니다. getLineBottom 메서드는 이미 descender를 포함하는 줄의 아래쪽 가장자리 Y 좌표를 반환합니다. 다른 글꼴 크기의 문자열을 사용자 정의 레이아웃할 때(예: 할인 가격과 정상 가격), descender를 고려한 기준선 정렬이 아래쪽 가장자리 정렬보다 더 정확한 결과를 제공합니다.

kotlin
// Compose: 텍스트 아래쪽 경계 확인
val text = "Text with descenders: gpq"
var layoutResult by remember { mutableStateOf<TextLayoutResult?>(null) }

Text(
    text = text,
    onTextLayout = { layoutResult = it },
    modifier = Modifier.drawBehind {
        layoutResult?.let { result ->
            val lastLine = result.lineCount - 1
            val bottom = result.getLineBottom(lastLine)
            val top = result.getLineTop(lastLine)
            // descender가 컨테이너 경계를 초과하지 않는지 확인
        }
    }
)

Google Material Design — Typography Implementation(2025)에 따르면, 고정 높이 컨테이너에서 descender 잘림을 방지하려면 현재 텍스트에 descender 문자가 포함되어 있는지 여부와 관계없이 글꼴의 descent 이상의 세로 패딩을 추가해야 합니다. 이렇게 하면 텍스트가 동적으로 대체될 때 인터페이스가 깨지지 않습니다.

모바일 인터페이스에서 Descender와 줄 충돌

줄 충돌은 위 줄 문자의 descender가 아래 줄 문자의 ascender와 물리적으로 교차하는 상황입니다. 모바일 인터페이스에서는 여러 줄 제목, 상품 카드, 줄 간격이 작은 텍스트 블록에서 특히 두드러집니다. 긴 descender와 작은 line-height의 글꼴을 사용할 때 문제가 악화됩니다.

충돌을 방지하는 최소 line-height는 다음 공식으로 계산할 수 있습니다: line-height = ascender + descender + 2 px 여백. 17pt의 SF Pro의 경우 line-height는 약 16.2 + 4.2 + 2 = 22.4pt(계수 ~1.32)입니다. 16sp의 Roboto의 경우 약 1.35입니다. line-height가 이 값보다 작으면 descender 문자가 포함된 텍스트에서 충돌이 확실히 발생합니다.

swift
// iOS: 충돌 방지를 위한 최소 line-height 계산
let font = UIFont.systemFont(ofSize: 17)
let minLineHeight = abs(font.ascender) + abs(font.descender) + 2.0

let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.minimumLineHeight = minLineHeight
paragraphStyle.maximumLineHeight = minLineHeight

let attributedText = NSAttributedString(
    string: "Text with p on first line\nand y on second line",
    attributes: [
        .font: font,
        .paragraphStyle: paragraphStyle
    ]
)

장식용 및 손글씨 글꼴로 작업할 때는 특히 주의해야 합니다 — 이들의 descender는 em 크기의 35–40%에 도달할 수 있습니다. 이러한 글꼴은 본문 텍스트에는 거의 사용되지 않지만 제목에 적용될 수 있습니다. 제목에 긴 descender가 있는 문자가 하나만 나타나도 인접한 인터페이스 요소와 충돌을 일으킬 수 있습니다.

Descender 작업 시 일반적인 실수

가장 흔한 실수는 버튼 및 텍스트 필드에서 descender 잘림입니다. descender를 고려하지 않고 버튼이나 텍스트 필드의 높이를 line-height와 동일하게 설정하면 descender가 있는 문자가 아래쪽 가장자리에서 잘립니다. 이는 descender가 모서리 반경 경계를 넘을 수 있는 둥근 모서리의 시스템 버튼에서 특히 두드러집니다.

  • 고정 높이 버튼 — 버튼 높이가 ceil(line-height)와 같으면 descender가 있는 문자가 잘립니다. 해결책: 위쪽 및 아래쪽 패딩을 위해 버튼 높이를 descender의 절대값(17pt 시스템 글꼴의 경우 4–5pt)만큼 늘립니다.
  • Descender를 고려하지 않은 TextField — 표준 UITextField 및 EditText에는 descender를 고려한 패딩이 있지만 사용자 정의 구현은 종종 이를 잊습니다. 커서와 텍스트 블록이 descender 문자를 자르지 않는지 확인하세요.
  • 한 줄에서 글꼴 크기 혼합 — NSAttributedString 또는 SpannableString에 다른 글꼴 크기의 세그먼트가 포함된 경우, 큰 글꼴의 descender가 작은 글꼴의 ascender와 겹칠 수 있습니다. 보정을 위해 baselineOffset을 사용하고 결과를 확인하세요.
  • SVG 텍스트 렌더링 — SVG 또는 Canvas(특히 WebView)에서 텍스트를 렌더링할 때 descender가 자동으로 고려되지 않을 수 있습니다. 항상 글꼴 크기의 10–15% 여백이 있는 명시적 viewBox를 지정하세요.

Nielsen Norman Group — Mobile Typography Research(2025)에 따르면, 모바일 애플리케이션의 41%가 descender가 있는 텍스트가 컴포넌트 경계를 벗어나는 화면을 하나 이상 가지고 있습니다. 이로 인해 가독성이 15% 감소하고 사용자의 작업 완료 시간이 증가합니다. descender 문자가 포함된 텍스트로 정기적인 테스트를 수행하면 개발 초기 단계에서 이러한 문제를 식별하는 데 도움이 됩니다.

자주 묻는 질문

Descender와 기준선의 차이점은 무엇인가요?

Baseline(기준선)은 문자가 놓이는 수평선이며, descender는 이 선 아래에 있는 문자 부분입니다. 기준선은 줄의 상수이고 descender는 특정 문자의 속성입니다. 이 개념을 혼동하지 마세요. 기준선은 정렬에 사용되고 descender는 줄 간격에 영향을 미치며 컨테이너 높이를 설정할 때 고려해야 합니다.

Android에서 글꼴의 descender를 어떻게 알 수 있나요?

View 시스템에는 Paint.getFontMetrics().descent를, Jetpack Compose에는 TextLayoutResult를 사용하세요. iOS와 달리 Android의 descent 값은 양수이며 기준선에서 글리프의 아래쪽 가장자리까지의 거리를 나타냅니다. 줄의 전체 아래쪽 경계를 계산하려면 기준선의 Y 좌표에 descent를 추가하세요.

같은 글꼴의 descender가 iOS와 Android에서 다른 이유는 무엇인가요?

플랫폼은 글꼴 파일에서 다른 메트릭 테이블을 사용합니다. iOS는 hhea.descent를, Android는 os/2.sTypoDescender를 사용합니다. 글꼴에서 이러한 값이 다르면 렌더링이 달라집니다. fontTools를 통해 항상 두 값을 확인하세요. 품질 좋은 시스템 글꼴(SF Pro, Roboto, Noto)은 두 플랫폼 모두에서 일관된 메트릭을 가집니다.

Descender 충돌을 방지하는 데 필요한 최소 line-height는 무엇인가요?

최소 line-height = ascender + descender + 2 px 여백입니다. iOS의 17pt 시스템 글꼴의 경우 약 22.4pt입니다. Android의 16sp Roboto의 경우 약 22sp입니다. 가장 가까운 정수로 반올림하고 descender 문자의 테스트 문자열로 확인하는 것이 좋습니다 — 충돌이 없으면 line-height가 충분합니다.

모바일 애플리케이션에서 매우 긴 descender가 있는 글꼴을 사용할 수 있나요?

네, 하지만 조건부입니다. 긴 descender가 있는 글꼴(Playfair Display, 장식용 서체)은 디자인을 손상시키지 않고 line-height를 늘릴 수 있는 제목 및 강조 텍스트에 허용됩니다. 본문 텍스트의 경우 세로 공간을 낭비하지 않도록 em 크기의 20–25% descender가 있는 글꼴(SF Pro, Roboto, Inter)이 선호됩니다.

요약

  • Descender — 기준선 아래에 위치한 문자의 아래 돌출 요소. 라틴 문자 “g”, “j”, “p”, “q”, “y”에 존재.
  • 디지털 메트릭 — OpenType/TrueType 형식의 hhea.descent(iOS) 및 os/2.sTypoDescender(Android).
  • iOS API — UIKit용 UIFont.descender(음수 값) 및 Core Text용 CTFontGetDescent.
  • Android API — Paint.FontMetrics.descent(양수) 및 Compose의 TextLayoutResult.
  • 줄 충돌 — line-height < ascender + descender + 2 px 여백일 때 발생. descender 문자의 테스트 문자열로 확인.
  • 컴포넌트 잘림 — 버튼, 텍스트 필드 및 사용자 정의 컨테이너에는 descender의 절대값과 동일한 패딩이 필요.
  • 플랫폼 차이 — iOS와 Android는 다른 메트릭 테이블을 사용하므로 두 플랫폼에서 글꼴을 확인해야 함.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기