[iOS / SwiftUI] Figma 의 Line Height 를 구현하기 위한 Text 행간 설정하기

박준혁 - Niro·2024년 5월 2일
6

SwiftUI

목록 보기
5/7
post-thumbnail
post-custom-banner

안녕하세요 Niro 🚗 입니다!

현재 프로젝트를 새롭게 진행하게 되었는데 Figma 를 보니 각 Font 에 따른 Line Height 가 설정되어 있었습니다....

어떻게 보면 굉장히 귀찮은 일이지만... 전체적인 구조나 디자이너분께서 고심하시어 만드셨기 때문에 1dp 도 차이가 나지 않게 그대로 만들어야 한다는 강박관념으로.. 구현했던 경험에 대해 적어볼까 합니다.


🛠️ 행간 설정하는 수정자가 있지 않나요..?

SwiftUI 의 Text 에는 .lineSpacing 이라는 수정자가 있는데 행 사이의 공백을 설정해주는 역할을 합니다.

해당 수정자로 행 간격을 설정해주면 구현할 수 있겠구나 생각했지만 겹쳐보니 다른 간격을 갖고 있었습니다....

또한 행 사이의 공백이기 때문에 한 줄만 있을 경우 다른 요소와의 간격 차이가 발생한 부분이 있어 lineSpacing 으로는 구현할 수 없겠구나 생각했습니다.


📏 Fimga 에서의 Line Height

그러면 왜 차이가 발생하는지 알아보기 위해 자세히 살펴보니 큰 차이점이 존재했습니다.

Figma 에서는 Text 높이를 의미하는 Line Height 를 통해 높이를 조절하게 됩니다.

즉, 해당 Text 의 높이에 더해 상, 하 부분에 빈 여백을 추가하여 Text 에 대한 높이를 증가시키는 것입니다!
한 줄만 존재하더라도 상, 하에 여백이 생기게 되는 것이죠!

하지만 SwiftUI 에서는 한 줄만 존재했을 때는 행간이 존재하지 않고 두 줄부터 간격이 형성됩니다.

당연... 하다고 생각하겠지만 그 당시에는 전혀 생각지못한 부분이였습니다..


👀 백문이 불여 일견

결론적으로 Figma 에서 처럼 한 줄만 있어도 상, 하에 여백이 존재하면서 여러 줄일 때 간격이 존재해야만 했습니다.

그러면.. 어떻게 구현 해야하지......??
라는 고민 끝에 상, 하에 여백은 padding 수정자를 통해 만들고 각 줄당 간격은 위에서 살펴봤던 lineSpacing 으로 적용하는 것으로 정했습니다.

한 줄만 존재하는 상황

자, 초록색 부분이 Text 에 padding 을 주어서 생긴 여백입니다.
실제로 여백이 없이 기존 Text 에 대한 높이는 회색 배경인 Font lineHeight 를 의미합니다.

실제 Figma 에서는 해당 글자의 높이가 36 이였고 상, 하의 여백과 Text 높이를 더하여 36 을 만들어주었습니다!

이렇게 한 줄만 존재했을 때도 여백을 추가하여 디자이너가 요구하는 글자의 높이를 구현하였습니다.

여러 줄 존재하는 상황

이번에는 여러 줄이 있는 상황입니다.
한 줄만 존재했을 때와 상황과 다르게 빨간 배경색이 보이죠? 이 부분이 lineSpacing 수정자를 적용한 부분, 즉 행간입니다!

기존과 동일하게 상, 하에 padding 이 적용되어 있고 행간 (Line Spacing) 높이는 각각 약 7.3 높이를 갖고 있습니다.

이렇게 해서 총 108 의 높이를 가진 Text 를 만들 수 가 있었고 실제로 만들 화면과 대조 시 완벽히 동일한 부분까지 확인할 수 있었습니다.

가장 가장 중요한 점!
여기서 줄 간격을 의미하는 행간은 저희 프로젝트의 Figma 상에서는 0이였습니다.
한 줄의 상, 하에 여백을 두어 여백이 행간의 역할을 하게 되는 것이죠

즉, 우리가 설정해야할 행간은 여백 2개 (3.6 + 3.6 ≈ 7.3) 를 합친 값과 같다는 의미입니다.


🤷🏻 그럼 어떻게 구현했어요??

모든 Text 에 padding 과 lineSpacing 을 적용해서 구현한다면 복잡한 일이겠죠..?
만약 어떠한 변경사항으로 인해 값들이 바뀐다면 해당 하는 모든 부분에서 바꿔야 하는 상황도 생길거라 생각합니다.

그래서!
FontWithLineHeight 라는 ViewModifier 를 직접 만들어 Text 에서 사용할 수 있게 구현을 해보았습니다.
일단 먼저 View 에 Extension 으로 추가한 메서드를 보시죠!

⌨️ fontWithLineHeight()

func fontWithLineHeight(fontLevel: FontLevel) -> some View { // FontLevel 은 직접 만든 Enum
    return ModifiedContent(content: self, 
                           modifier: FontWithLineHeight(font: Font.uiFontGuide(fontLevel), 
                                                        lineHeight: fontLevel.lineHeight))
}

사용하려는 폰트(fontLevel) 를 입력받아서 padding 과 lineSpacing 을 설정해주려고 합니다.
SwiftUI 에서는 Font 유형을 통해 폰트를 정해주는데 이상한 메서드가 보이죠..?

⌨️ uiFontGuide()

static func uiFontGuide(_ fontLevel: FontLevel) -> UIFont {
    return UIFont(name: fontLevel.fontWeight, size: fontLevel.fontSize)!
}

해당 메서드는 Font 유형을 UIFont 로 바꿔주는 역할을 합니다.
그냥 Font 를 쓰면 되는데 왜 바꾸는지 궁금하실 겁니다!

자, 위에서 봤던 이미지를 다시 가져왔습니다.
Line Spacing 과 Text Padding 이라는 값을 구하기 위해선 전체 높이와 Text 의 높이를 알아야만 구할 수 있습니다.

여기서 힘들었던 부분은 SwiftUI 에서 해당 Text 의 height 를 직접 구할 수 없었습니다.

찾아본 결과 UIKit 의 UIFont 에서는 높이를 직접 반환 받을 수 있기 때문에 먼저 Font 를 UIFont 로 변경하는 uiFontGuide 함수를 만들었습니다.

전체 높이는 Figma 에 나와 있으니 enum 을 통해 처리를 해주었고 ViewModifier 에서 padding 과 Spacing 값을 구하러 가볼까요?


⌨️ FontWithLineHeight

struct FontWithLineHeight: ViewModifier {
    let font: UIFont // 입력받은 폰트
    let lineHeight: CGFloat // Text 의 전체 높이 (Full Height)

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

제가 변수명을 다르게 사용했어야했는데 변수명에 대해 헷갈릴 수 있다고 생각합니다..
lineHeight 속성은 figma 에서 설정되어있는 폰트의 높이를 의미하고 font.lineHeight 는 실제 Xcode 상에서 Text 의 높이를 의미하고 Enum 을 통해 처리를 해준 값입니다.

행간 구하기

여기서 중요한건 행간입니다!
위에서 설명드린것 처럼 행간의 경우 상, 하의 여백 2개를 더해 행간 처럼 사용한다고 했습니다.

한 줄일 때 초록색 배경이 여백을 의미한다 했기 때문에 전체 높이(lineHeight)에서 글자 높이(font.lineHeight)를 뺀다면 상, 하 여백 2개의 높이 값을 구할 수 있겠죠?

이것이 바로 우리가 여러 줄일 때 행간으로 사용할 값, 빨간색 배경을 의미합니다.

여백 구하기

그 다음은 상, 하에 여백을 적용하기 위해 verticalpadding 을 사용하였습니다.
아까 행간 설정할 때 설명드린 것처럼 전체 높이에서 글자 높이를 빼면 상, 하 여백 값을 구할 수 있다고 했죠?

그러면 각 위치에 여백을 적용하기 위해선 나누기 2 를 해주면 여백의 크기를 구할 수 있게 되는 것이죠!

이해가 잘 되셨을까요?


정리하자면

아무것도 적용하지 않은 기본 Text 와 상, 하 여백과 행간을 적용한 Text 를 한번에 볼 수 있게 정리했습니다.

먼저, 상단의 Text 는 가장 기본적인 Text 만 썼을 때 보여지는 상황입니다.

상단 Text 의 높이 (Text height1) 는 86, 행간과 패딩 없이 나온 높이이기 때문에 각 줄당(font.lineHeight) 약 28 정도의 높이를 갖고 있다고 보시면 됩니다!

두번째로 하단의 Text 는 행간과 상, 하 여백을 제공해서 만들어 주었는데

총 높이(Text height2) 는 약 108, 여백을 만들기 위한 높이(Text padding) 는 약 3.6, 행간의 높이(Text lineSpacing)는 약 7.3 입니다.

회색 배경만 봐도 상, 하에 여백이 아주 미미하지만 추가된것이 보이고 각 줄당의 간격(행간) 이 추가된 것도 볼 수 있습니다.
실제로 두번째 Text 를 통해 만들 화면과 겹쳐보면 동일한 디자인을 갖고 있는 것까지 확인을 했습니다!

이렇게 상, 하의 여백과 줄 간격을 통해 한줄일 때와 여러 줄일 때에 대한 행간을 설정해보았습니다.
코드로만 봤을 때는 정말 간단했지만 코드를 작성하기까지 많은 시간이 걸릴줄은 몰랐습니다...

이번 글을 통해 많은 분들이 Figma 에 있는 Line Height 를 Xcode 상에서 구현할 수 있도록 많은 도움이 됐으면 좋겠습니다!
긴 글 읽어주셔서 감사하고 피드백은 환영입니다!

profile
📱iOS Developer, 🍎 Apple Developer Academy @ POSTECH 1st, 💻 DO SOPT 33th iOS Part
post-custom-banner

4개의 댓글

comment-user-thumbnail
2024년 6월 10일

니로... 덕분에 잘 해결했습니다. 감사합니다!!

1개의 답글
comment-user-thumbnail
2024년 7월 9일

좋은 글 덕에 해결했습니다. 감사합니다.

답글 달기
comment-user-thumbnail
2024년 8월 1일

니로 최고입니다 . .

답글 달기