포스트

문자열 보간을 확장하는 방법

문자열 보간을 확장하는 방법

문자열 보간(String Interpolation)은 일정한 서식의 문자열에 임의의 정수, 실수 혹은 문자열을 손쉽게 추가할 수 있는 방법 중 하나입니다.

1
2
let name = "김소월"
print("My name is \(name)")

놀랍게도, 문자열 보간을 확장하여 원하는 형식의 문자열을 출력하도록 할 수 있습니다! 우리는 일반적으로 아래 예제처럼 문자열 보간을 많이 사용해 왔습니다. 문자열 보간은 StringInterpolation(DefaultStringInterpolation의 타입 별칭) 구조체에 의해 수행됩니다. StringInterpolation 구조체를 확장함으로서 시스템이 문자열 보간 시 주어지는 값을 어떻게 지지고 볶아서 문자열에 삽입하게 할지 정할 수 있습니다.

문자열 보간의 커스터마이징을 위해 StringInterpolation 구조체는 아래와 같은 메소드를 포함하고 있습니다.

메서드설명
appendInterpolation(_:)이 메소드는 매개변수로 주어진 값을 문자열에 보간합니다. 이 메소드는 컴파일러에 의해 관리되는 메소드이기에, 직접 호출하면 안됩니다.
appendLiteral(String)이 메소드는 매개변수로 주어진 문자열을 보간에 추가합니다. 이 메소드는 컴파일러에 의해 관리되는 메소드이기에, 직접 호출하면 안됩니다.

우리는 아무 생각없이 위 예제와 같이 문자열을 보간해왔는데, 내부적으로 StringInterpolation 구조체의 appendInterpolation() 메소드가 호출되어 실질적인 문자열 대체가 이루어지게 됩니다. StringInterpolation 구조체에 정의되어 있는 메소드를 보면 더 쉽게 이해할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    /// Appends a literal segment of a string interpolation.
    /// 
    /// Do not call this method directly. It is used by the compiler when
    /// interpreting string interpolations.
    @inlinable public mutating func appendLiteral(_ literal: String)
    
	/// Interpolates the given value's textual representation into the
    /// string literal being created.
    /// 
    /// Do not call this method directly. It is used by the compiler when
    /// interpreting string interpolations. Instead, use string
    /// interpolation to create a new string by including values, literals,
    /// variables, or expressions enclosed in parentheses, prefixed by a
    /// backslash (`\(`...`)`).
    ///
    ///     let price = 2
    ///     let number = 3
    ///     let message = """
    ///                   If one cookie costs \(price) dollars, \
    ///                   \(number) cookies cost \(price * number) dollars.
    ///                   """
    ///     print(message)
    ///     // Prints "If one cookie costs 2 dollars, 3 cookies cost 6 dollars."
    @inlinable public mutating func appendInterpolation<T>(_ value: T)

우리가 \(name)과 같은 문자열 보간을 사용할 수 있었던 이유가 바로 appendInterpolation() 메소드가 제네릭 타입의 매개변수 하나를 인자로 받기 때문입니다.

문자열 보간의 커스터마이징을 위해 StringInterpolation 구조체를 확장하여 appendInterpolation() 메소드를 오버로드(Overload)합니다. 그리고 매개변수로 주어진 값을 지지고 볶아 appendLiteral() 메소드를 호출해 최종 문자열에 삽입하면 됩니다. 아래 예제는 문자열 보간을 커스터마이징해 섭씨를 화씨로 변환하는 방법을 보여줍니다.

1
2
3
4
5
6
7
8
extension String.StringInterpolation {
    mutating func appendInterpolation(celcius value: Double) {
        let farenheit = ((value * 9)/5) + 32
        appendLiteral(String(farenheit))
    }
}
print("Temperature in Farenheit: \(celcius: 25)")
// Temperature in Farenheit: 77.0

appendInterpolation() 메소드는 아래 예제와 같이 우리가 필요한 만큼 충분한 개수의 매개변수를 가질 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
extension String.StringInterpolation {
    mutating func appendInterpolation(_ date: Date, locale: Locale) {
        let dateFormat = date.formatted(.dateTime.year().month().day().locale(locale))
        appendLiteral(dateFormat)
    }
}
let today = Date()
let krLocale = Locale(identifier: "ko_kr")
let enLocale = Locale(identifier: "en_us")
print("\(today, locale: krLocale)")
print("\(today, locale: enLocale)")
// 2023년 7월 5일
// Jul 5, 2023

참고 자료

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.