[SwiftUI] figma의 LineHeight 대응하기

민경준·2025년 5월 21일
0
post-thumbnail

🧑🏻‍💻 Intro

Figma에서 제공하는 lineHeight 값을 보고, SwiftUI에서 이를 어떻게 구현할지 고민해본 적 있으신가요?
SwiftUI에는 lineHeight라는 속성이 존재하지 않고, 대신 lineSpacing이라는 modifier가 존재합니다.
이 글에서는 lineHeight가 무엇인지, lineSpacing과는 어떤 차이가 있는지, 그리고 SwiftUI에서는 어떻게 대응할 수 있는지 정리해보았습니다.


Figma의 lineHeight란?

lineHeight는 말 그대로 텍스트 줄 간의 전체 높이를 의미합니다.
이는 한 줄의 높이를 결정하는 기준이 되며, 폰트의 크기(fontSize)와는 별개입니다.

  • 예:
    • fontSize: 16
    • lineHeight: 24
      → 한 줄의 전체 높이가 24pt가 되고, 위아래 여백을 포함한 높이가 됩니다.

Figma에서 lineHeight는 주로 다음 2가지 형태로 설정됩니다:

  1. 픽셀(px) 단위 고정: 예) 24px → 고정된 줄 높이
  2. % 기반 상대 값: 예) 150% → fontSize * 1.5

lineHeight는 웹(CSS)에서는 line-height 속성으로 바로 지정할 수 있지만, SwiftUI에서는 그렇지 않습니다.


SwiftUI의 lineSpacing과의 차이점

SwiftUI의 TextlineSpacing(_:) modifier를 통해 줄 간 간격을 조절할 수 있습니다.
하지만 이건 lineHeight가 아니라, 줄과 줄 사이의 추가 간격입니다.

  • lineSpacing은:
    • 기본 lineHeight에 더해지는 값입니다.
    • 줄과 줄 사이의 간격만 조절할 수 있으며, 전체 줄 높이를 직접 지정할 수 없습니다.

📌 즉, SwiftUI의 lineSpacing은 Figma의 lineHeight와 직접적으로 1:1 대응되지 않습니다.

Text("SwiftUI에서 lineSpacing 사용")
    .font(.system(size: 16))
    .lineSpacing(8) // 24 - 16 = 8?

위 코드는 줄 간 간격을 늘리는 것뿐, 전체 줄 높이를 정확히 설정하지는 않습니다.
첫 줄과 마지막 줄의 위/아래 패딩은 적용되지 않기 때문에 시각적으로 오차가 생깁니다.


그렇다면 SwiftUI에서 lineHeight를 어떻게 맞출까?

SwiftUI에서는 Figma의 lineHeight 개념을 정확히 반영하기 위해 NSParagraphStyle을 사용하는 방법도 있지만, 더 간결하고 SwiftUI스러운 방식으로는 커스텀 ViewModifier를 통해 lineHeight를 구현하는 전략이 있습니다.

🔧 lineSpacing과 padding을 조합해 lineHeight 맞추기

Figma의 lineHeight는 보통 폰트 크기보다 크며, 줄 간 간격 외에도 한 줄 위아래의 여백까지 포함된 개념입니다.
SwiftUI에서는 다음과 같은 전략으로 대응할 수 있습니다:

  • 폰트의 기본 lineHeight를 가져와 원하는 multiple만큼 곱해줄 것
  • 그 차이를 lineSpacing으로 설정
  • 줄 위/아래 균형을 맞추기 위해 해당 차이의 절반을 padding(.vertical)로 적용

이를 코드로 일반화한 것이 아래의 LineHeightModifier입니다.

🧩 LineHeightModifier 구현

extension Text {
    func pretendard(size: CGFloat, weight: Pretendard.Weight, multiple: CGFloat) -> some View {
        self.modifier(
            LineHeightModifier(size: size, weight: weight, multiple: multiple)
        )
    }
}

struct LineHeightModifier: ViewModifier {
    let weight: Pretendard.Weight
    let fontSize: CGFloat
    let lineHeightMultiple: CGFloat

    init(size: CGFloat, weight: Pretendard.Weight, multiple lineHeightMultiple: CGFloat = 1.0) {
        self.fontSize = size
        self.weight = weight
        self.lineHeightMultiple = lineHeightMultiple
    }

    private var uiFont: UIFont {
        .init(name: weight.fontName, size: fontSize)!
    }

    private var font: Font {
        Font(uiFont)
    }

    private var lineSpacing: CGFloat {
        let adjusted = uiFont.lineHeight * lineHeightMultiple
        return adjusted - uiFont.lineHeight
    }

    private var padding: CGFloat {
        return lineSpacing / 2.0
    }

    func body(content: Content) -> some View {
        content
            .font(font)
            .lineSpacing(lineSpacing)
            .padding(.vertical, padding)
    }
}

정리: SwiftUI에서 Figma의 lineHeight 대응 전략

항목Figma 설명SwiftUI 대응 방식
fontSize텍스트 크기.font(.custom(_:size:)) 또는 UIFont 기반 커스텀 폰트 적용
lineHeight줄의 전체 높이 (텍스트+위아래 여백 포함)(UIFont.lineHeight * multiple) 값을 기준으로 lineSpacingpadding 계산
lineSpacing줄과 줄 사이의 간격lineHeight - UIFont.lineHeight 값을 .lineSpacing()으로 적용
시각적 정렬 보정텍스트 블록 위/아래 공백 포함 정렬 필요.padding(.vertical, lineSpacing / 2)으로 여백 균형 맞추기

✅ 마무리

SwiftUI에서 디자인 시스템을 구현할 때, Figma의 lineHeight를 정확히 반영하지 않으면
텍스트의 줄 간 간격이나 블록의 시각적 정렬이 미묘하게 어긋날 수 있습니다.

이를 해결하기 위해 lineSpacingpadding을 조합한 커스텀 ViewModifier를 사용하면,
별도의 AttributedString 없이도 Figma와 일관된 줄 높이를 구현할 수 있습니다.

특히 폰트의 UIFont.lineHeight를 기반으로 계산한 값은 실제 렌더링 시 정확도도 높고,
코드의 재사용성과 유지보수에도 유리합니다.

디자인과 개발의 간극을 줄이기 위해, lineHeight 대응 로직을 명시적으로 다루는 습관이 중요합니다.

profile
iOS Developer 💻

0개의 댓글