2025/07/21

14. Swift 익스텐션(Extension): 기존 타입에 새로운 기능 추가하기

안녕하세요! 오늘은 Swift의 또 다른 강력한 기능으로, 이미 존재하는 타입에 새로운 숨겨진 능력을 부여하는 마법과 같은 도구인 익스텐션(Extension)에 대해 알아 보겠습니다. ✨

개발을 하다 보면 기존에 정의된 클래스, 구조체, 열거형, 또는 심지어 기본 타입(Int, String 등)에 새로운 기능을 추가하고 싶을 때가 있습니다. 하지만 원본 소스 코드를 수정할 수 없거나, 수정하는 것이 바람직하지 않은 경우가 많죠. 이럴 때 익스텐션이 빛을 발합니다. 익스텐션은 기존 타입의 기능을 확장하여, 마치 원래부터 그 타입에 있었던 것처럼 사용할 수 있게 해주는 아주 유용한 방법입니다.


1. 익스텐션(Extension)이란 무엇인가요?

익스텐션은 기존 클래스, 구조체, 열거형 또는 프로토콜 타입에 새로운 기능(메서드, 연산 프로퍼티, 초기화 메서드, 서브스크립트, 중첩 타입 등)을 추가하는 기능입니다. 중요한 점은 원본 소스 코드를 수정하지 않고도 기능을 확장할 수 있다는 것입니다.

💡 익스텐션을 사용하는 이유:

  • 코드 조직화: 관련 기능을 한데 모아 코드를 더 잘 조직할 수 있습니다. 예를 들어, 특정 타입에 대한 네트워크 관련 기능은 네트워크 익스텐션에, UI 관련 기능은 UI 익스텐션에 분리하여 관리할 수 있습니다.
  • 기존 타입 확장: 다른 개발자가 만들었거나 Swift 표준 라이브러리에 있는 타입에 커스텀 기능을 추가할 수 있습니다.
  • 가독성 향상: 특정 기능이 어디에 정의되어 있는지 찾기 쉬워 코드 가독성과 유지보수성이 향상됩니다.
  • 프로토콜 채택: 기존 타입이 특정 프로토콜을 준수하도록 익스텐션을 통해 만들 수 있습니다.

1.1. 익스텐션의 기본 문법

extension 키워드를 사용하고, 확장하려는 타입의 이름을 명시합니다.

extension SomeType {
    // 새로운 기능 추가
}

2. 익스텐션으로 추가할 수 있는 기능들

익스텐션으로 다음과 같은 기능들을 기존 타입에 추가할 수 있습니다.

2.1. 연산 프로퍼티 추가

저장 프로퍼티는 추가할 수 없지만, 연산 프로퍼티는 추가할 수 있습니다.


extension Double {
    var km: Double { return self * 1_000.0 }
    var m: Double { return self }
    var cm: Double { return self / 100.0 }
    var mm: Double { return self / 1_000.0 }
    var ft: Double { return self / 3.28084 } // 피트를 미터로 변환

    var `in`: Double { return self * 2.54 } // 인치를 cm로
    var pounds: Double { return self * 0.453592 } // 파운드를 kg으로
}

let oneInch = 2.54.cm
print("1인치는 \(oneInch)cm 입니다.") // 출력: 1인치는 2.54cm 입니다.

let threeFeet = 3.ft
print("3피트는 \(threeFeet)m 입니다.") // 출력: 3피트는 0.9144m 입니다.

let aMarathon = 42.km + 195.m
print("마라톤 코스: \(aMarathon)m") // 출력: 마라톤 코스: 42195.0m

위 예시에서 Double 타입에 길이 및 무게 단위를 나타내는 연산 프로퍼티를 추가했습니다. 이제 2.54.cm와 같이 마치 Double이 원래 가지고 있던 기능처럼 사용할 수 있습니다.

2.2. 인스턴스 메서드 및 타입 메서드 추가

기존 타입에 새로운 인스턴스 메서드나 타입 메서드를 추가할 수 있습니다.

extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }

    // 타입 메서드 (static)
    static func random(in range: ClosedRange<Int>) -> Int {
        return Int.random(in: range)
    }
}

// 인스턴스 메서드 사용
3.repetitions { // 3이라는 Int 인스턴스에 repetitions 메서드 호출
    print("안녕하세요!")
}
// 출력:
// 안녕하세요!
// 안녕하세요!
// 안녕하세요!

// 타입 메서드 사용
let randomNumber = Int.random(in: 1...10)
print("랜덤 숫자: \(randomNumber)") // 출력: 랜덤 숫자: (1~10 사이의 임의의 정수)
2.2

Int 타입에 반복 작업을 수행하는 repetitions 메서드와 임의의 숫자를 생성하는 random 타입 메서드를 추가하여 코드를 더욱 직관적으로 만들었습니다.

2.3. 초기화 메서드(Initializer) 추가

기존 타입에 새로운 초기화 메서드를 추가할 수 있습니다. 이는 기존 초기화 메서드를 오버라이드하는 것이 아니라, 새로운 초기화 방식을 추가하는 것입니다.


struct Point {
    var x = 0.0, y = 0.0
}

extension Point {
    // 앵글과 반지름으로 Point를 초기화하는 메서드 추가
    init(angle: Double, radius: Double) {
        self.x = radius * cos(angle)
        self.y = radius * sin(angle)
    }
}

let originPoint = Point(x: 0.0, y: 0.0) // 기존 초기화 사용
let customPoint = Point(angle: .pi / 2, radius: 5.0) // 새로운 초기화 사용
print("커스텀 포인트: (\(customPoint.x), \(customPoint.y))")
// 출력: 커스텀 포인트: (3.061616997868383e-16, 5.0) (부동 소수점 오차 감안)

Point 구조체에 각도와 반지름을 이용한 새로운 초기화 방법을 익스텐션으로 추가했습니다.

2.4. 서브스크립트(Subscript) 추가

기존 타입에 새로운 서브스크립트를 추가하여 컬렉션 요소에 접근하는 방식을 확장할 수 있습니다.

extension String {
    // 문자열의 특정 인덱스에 해당하는 Character를 반환하는 서브스크립트
    subscript(i: Int) -> Character {
        return self[index(startIndex, offsetBy: i)]
    }

    // 특정 범위의 부분 문자열을 반환하는 서브스크립트
    subscript(range: Range<Int>) -> String {
        let startIndex = self.index(self.startIndex, offsetBy: range.lowerBound)
        let endIndex = self.index(self.startIndex, offsetBy: range.upperBound)
        return String(self[startIndex..<endIndex])
    }
}

let myString = "Hello, Swift"
print(myString[0])         // 출력: H
print(myString[7])         // 출력: S
print(myString[0..<5])     // 출력: Hello
print(myString[7..<12])    // 출력: Swift

CustomPoint 구조체에 Equatable 프로토콜을 채택하고 == 연산자를 구현하여, 두 CustomPoint 인스턴스를 직접 비교할 수 있게 되었습니다.

정리하며

오늘은 Swift에서 기존 타입에 새로운 기능을 추가하는 강력한 방법인 익스텐션(Extension)에 대해 자세히 알아보았습니다.

  • 익스텐션: 기존 클래스, 구조체, 열거형, 프로토콜에 메서드, 연산 프로퍼티, 초기화 메서드, 서브스크립트, 중첩 타입, 프로토콜 채택 등의 기능을 추가합니다.
  • 원본 코드 수정 없이 확장: 외부 라이브러리나 Swift 기본 타입 등 수정할 수 없는 타입에 기능을 추가할 때 유용합니다.
  • 코드 조직화 및 재사용성: 관련 기능을 모듈화하여 관리하고, 코드의 가독성을 높입니다.

익스텐션은 Swift 개발에서 코드를 깔끔하게 유지하고, 기능적으로 풍부한 API를 구성하는 데 필수적인 도구입니다. 복잡한 기능을 여러 익스텐션으로 나누어 구현하면 코드베이스를 훨씬 더 관리하기 쉽게 만들 수 있습니다. 오늘 배운 내용을 바탕으로 여러분의 코드에 익스텐션을 적극적으로 활용해 보세요!

다음 시간에는 Swift의 강력한 타입 시스템을 완성하는 제네릭(Generics)에 대해 알아보겠습니다.

궁금한 점이 있다면 언제든지 댓글로 남겨주세요! 감사합니다.





0 comments:

댓글 쓰기