๋ชฉ์ฐจ
  1. Figma
  2. ๊ฐœ๋ฐœ

ํฐํŠธ๋Š” ํ”„๋ฆฌํ…๋‹ค๋“œ ์‚ฌ์šฉํ•จ (์‚ฌ์ดํŠธ๋งํฌ)

 

Pretendard

Pretendard ํ”„๋ฆฌํ…๋‹ค๋“œ Pretendard ํ”„๋ฆฌํ…๋‹ค๋“œ ๊ธ€๊ผด ๋‹ค์šด๋กœ๋“œ ์ผ๋ณธ์–ด ๋ฒ„์ „ ๋‹ค์šด๋กœ๋“œ GitHub์—์„œ ๋ณด๊ธฐ system-ui๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๊ธ€๊ผด Apple์˜ system-ui๊ฐ€ ์ต์ˆ™ํ•œ ๋‚˜๋กœ์„œ๋Š” San Francisco์™€ Apple SD ์‚ฐ๋Œ๊ณ ๋”• Neo๊ฐ€ ์—†๋Š”

cactus.tistory.com

  • ๊ธ€๊ผด ๋‹ค์šด๋กœ๋“œ๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ๋งฅ์— ์ €์žฅ

  • ํ”ผ๊ทธ๋งˆ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ํ•ญ๋ชฉ์„ ๋”๋ธ” ํด๋ฆญํ•ด์„œ ์„ค์น˜

 

Figma

  • ํ…์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•œ ํ›„ ํฐํŠธ, ํฐํŠธ์˜ ๊ตต๊ธฐ, ์ž๊ฐ„, ํ–‰๊ฐ„์„ ์ง€์ •
  • ๊ทธ ํ›„ Text ์˜†์— ์  ๋„ค๊ฐœ ์•„์ด์ฝ˜ ํด๋ฆญ

  • ํ…์ŠคํŠธ ์Šคํƒ€์ผ ๋ฉ”๋‰ด๊ฐ€ ๋‚˜์˜ค๋ฉด + ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ƒˆ๋กœ์šด ํ…์ŠคํŠธ ์Šคํƒ€์ผ์„ ๋“ฑ๋ก

  • ์ƒˆ๋กœ์šด ํ…์ŠคํŠธ ์Šคํƒ€์ผ์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•œ ๋’ค create style์„ ๋ˆŒ๋Ÿฌ ์ €์žฅ

  • ์ตœ์ข… ํ”ผ๊ทธ๋งˆ ๋””์ž์ธ์€ ์ด๋Ÿฐ ํ˜•ํƒœ๋กœ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ „๋‹ฌ

 

๊ฐœ๋ฐœ

  • ํฐํŠธ๋ฅผ ๋„ฃ์–ด ์ค„ ํด๋”๋ฅผ ์ƒ์„ฑ
  • ํ”ผ๊ทธ๋งˆ์—์„œ ์‚ฌ์šฉ๋œ ํฐํŠธ๋ฅผ ํ•ด๋‹น ํด๋”์— ์ž„ํฌํŠธ
    • ํ”ผ๊ทธ๋งˆ์—์„œ ์‚ฌ์šฉ๋œ(๋””์ž์ด๋„ˆ์™€ ์ด๋ฏธ ์ด์•ผ๊ธฐ ๋œ ํฐํŠธ๋งŒ) ๋„ฃ์–ด์คŒ

  • ์ž„ํฌํŠธ์‹œ์— Copy items if needed ๋ฅผ ์ฒดํฌํ•ด์„œ ํด๋”๋กœ ๋ณต์‚ฌํ•ด์ฃผ๊ณ  targets๋„ ์ฒดํฌํ•ด์„œ ์ง€์ •

  • project > TARGETS > Info ํƒญ์œผ๋กœ ๊ฐ€์„œ "Fonts provided by application" ํ•„๋“œ๋ฅผ ์ƒ์„ฑ
    • ํŠน์ • ํ•„๋“œ ์œ„์—์„œ ๋งˆ์šฐ์Šค ํ˜ธ๋ฒ„ํ•  ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” + ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋จ
    • ์ƒˆ๋กœ์šด ํ•„๋“œ๊ฐ€ ๋‚˜ํƒ€๋‚˜๋ฉด Fonts provided by application ์ž…๋ ฅ

  • ์ถ”๊ฐ€ํ•ด ์ค€ ํฐํŠธ ํŒŒ์ผ๋ช…์„ ํ™•์žฅ์ž์™€ ํ•จ๊ป˜ ๊ทธ๋Œ€๋กœ ์ž…๋ ฅํ•จ
    private func getFontName() {
        for family in UIFont.familyNames {

            let sName: String = family as String
            print("family: \(sName)")
                    
            for name in UIFont.fontNames(forFamilyName: sName) {
                print("name: \(name as String)")
            }
        }
    }
  • ContentView๋กœ ์ด๋™ํ•œ ๋’ค ํ•ด๋‹น ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑ
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .padding()
        .onAppear {
            getFontName()
        }
    }
  • onAppear modifier๋ฅผ ํ†ตํ•ด ํฐํŠธ์˜ ์‹ค์ œ ์ด๋ฆ„์„ ์ฝ˜์†”์— ์ฐ์„ ์ˆ˜ ์žˆ์Œ

  • info.plist์— ํฐํŠธ ํŒŒ์ผ์„ ๋“ฑ๋กํ•˜์ง€ ์•Š์œผ๋ฉด ๋œจ์ง€ ์•Š์œผ๋ฏ€๋กœ info.plist์— ์ •๋ณด ๋“ฑ๋ก ํ›„ ์ด๋ฆ„ ํ™•์ธ ์ฝ”๋“œ ์ž‘์„ฑํ•ด์•ผ ํ•จ
  • ํŠน์ • ํฐํŠธ์˜ ๊ฒฝ์šฐ ํŒŒ์ผ ์ด๋ฆ„๊ณผ ์‹ค์ œ ํฐํŠธ์ด๋ฆ„์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ํ™•์ธํ•˜๋Š” ๊ณผ์ •์ด ๊ผญ ํ•„์š”ํ•จ
  • ํ•œ๋ฒˆ ์ด๋ฆ„์„ ์•Œ์•˜์œผ๋‹ˆ ํ•ด๋‹น ์ฝ”๋“œ๋Š” ์ฃผ์„ ์ฒ˜๋ฆฌํ•ด๋„ ๋ฌด๊ด€
enum CustomFontName: String {
    case light = "Pretendard-Light"
    case medium = "Pretendard-Medium"
    case extraBold = "Pretendard-ExtraBold"
}
  • ํฐํŠธ ์‹ค์ œ ์ด๋ฆ„์„ ๋Œ€์น˜ํ•  enum ์ƒ์„ฑ
enum CustomFontStyle {
    case header
    case caption
    case content
}
  • ํ”ผ๊ทธ๋งˆ์—์„œ ๋„˜์–ด์˜จ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ ๋Œ€๋กœ ์ •์˜
struct CustomFontViewModifier: ViewModifier {
    var style: CustomFontStyle
    
    @ViewBuilder // ์—ฌ๋Ÿฌ viewModifier๋ฅผ ์œ„ํ•ด์„œ some View๋ฅผ ๋ฐ˜ํ™˜ํ•จ
    func body(content: Content) -> some View {
        switch style {
        case .content:
            content
                .font(.custom(CustomFontName.medium.rawValue, size: 16))
                .lineSpacing(25 - 16) // ํ–‰๊ฐ„ ์ง€์ • : ํ”ผ๊ทธ๋งˆ์˜ ํ–‰๊ฐ„์€ ํฐํŠธ์˜ ํฌ๊ธฐ๊นŒ์ง€ ๋”ํ•ด์„œ ๊ณ„์‚ฐํ•˜๊ณ  SwiftUI๋Š” ํ–‰๊ณผ ํ–‰ ์‚ฌ์ด์˜ ๊ณต๊ฐ„์„ ์˜๋ฏธํ•จ
                .kerning(16 * 0.05)
        case .caption:
            content
                .font(.custom(CustomFontName.light.rawValue, size: 14))
                .lineSpacing(16)
                .kerning(0)
        case .header:
            content
                .font(.custom(CustomFontName.extraBold.rawValue, size: 36))
                .kerning(36 * 0.07)
        }
    }
}
  • ViewModifer๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๊ฐ ์Šคํƒ€์ผ ๊ฐ€์ด๋“œ ์ •์˜๋Œ€๋กœ ์ •์˜ํ•ด ์คŒ
  • ํ–‰๊ฐ„ ์ง€์ •์€ lineSpacing์„ ์‚ฌ์šฉ
    • ํ”ผ๊ทธ๋งˆ์—์„œ๋Š” ํฐํŠธ์˜ ํฌ๊ธฐ + ํ–‰๊ฐ„
    • Xcode์—์„œ๋Š” ๋‹จ์ˆœ ํ–‰๊ฐ„ ํฌ๊ธฐ๋งŒ
    • kerning์˜ ๊ฒฝ์šฐ px, % ๋ชจ๋‘ ๋Œ€์‘ ๊ฐ€๋Šฅํ•˜๋ฉฐ %์ผ ๊ฒฝ์šฐ ํฐํŠธ์‚ฌ์ด์ฆˆ * ํผ์„ผํŠธ
extension View {
    func customFont(_ style: CustomFontStyle) -> some View {
        self.modifier(CustomFontViewModifier(style: style))
    }
}
  • Text์—์„œ modifier๋ฅผ ์ด์šฉํ•ด์„œ ViewModifier๋ฅผ ๋„˜๊ธฐ์ง€ ์•Š๊ณ  customFont๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ViewModifier๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์ž‡๋„๋ก ์ง€์ •
        VStack(spacing: 0) {
            Group {
                Text("์ƒ๋‹จ ํฐํŠธ์ž…๋‹ˆ๋‹ค.")
                    .customFont(.header)
                    .padding(.top, 32)
                    .multilineTextAlignment(.center)
                
                Text("์บก์…˜์€ ์ฃผ๋กœ ์„ค๋ช…ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค")
                    .customFont(.caption)
                    .multilineTextAlignment(.center)
                    .padding(.top, 5)
                
                Text("๊ทธ๊ฑฐ ์•„์‹œ๋‚˜์š”? ์—ฌ๋Ÿฌ์ค„๋กœ ํ‘œ์‹œ๋˜๋Š” ํฐํŠธ๋ฅผ ๊ทธ๋ฆด ๋•Œ๋Š” ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋””์ž์ธ๊ณผ ๋™์ผํ•˜๊ฒŒ ๊ทธ๋ฆฌ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? โ€จ๋””์ž์ด๋„ˆ์™€ ๊ฐœ๋ฐœ์ž ๊ฐ„์— ํ…์ŠคํŠธ ์Šคํƒ€์ผ์„ ์ •์˜ํ•˜๊ณ  ๊ณต์œ ํ•˜๋Š” ๊ณผ์ •์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ")
                    .multilineTextAlignment(.leading)
                    .customFont(.content)
                    .padding(.top, 40)
                
            }
            .frame(maxWidth: .infinity)
            
            Spacer()
        }
  • ํ…์ŠคํŠธ์— customFont modifier๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ”ผ๊ทธ๋งˆ์—์„œ ์ง€์ •ํ•œ style guide๋ฅผ ์ง€์ •ํ•ด์คŒ

  • ์™ผ์ชฝ์€ SwiftUI ์ž‘์—… ํ™”๋ฉด, ์˜ค๋ฅธ์ชฝ์€ ํ”ผ๊ทธ๋งˆ ๊ฒฐ๊ณผ
  • ํ”ผ๊ทธ๋งˆ์—์„œ ํ…์ŠคํŠธ์˜ ์˜์—ญ๊ณผ SwiftUI์˜ Text์˜ ์˜์—ญ์ด ๋‹ค๋ฆ„. SwiftUI์˜ Text๋Š” ํ…์ŠคํŠธ์— ๋”ฑ ๋งž๊ฒŒ ๋‚˜์˜ค์ง€๋งŒ Figma๋Š” ํ…์ŠคํŠธ ์˜์—ญ์˜ ์ค‘๊ฐ„์— ํ…์ŠคํŠธ๊ฐ€ ์œ„์น˜ํ•ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์˜คํ”„์…‹์„ ๋””์ž์ด๋„ˆ์™€ ํ•จ๊ป˜ ์ด์•ผ๊ธฐ ํ•ด์„œ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ํ•„์š”