Swift 익스텐션 활용법: 연산 프로퍼티, 메서드, 서브스크립트 추가하기
익스텐션이란?
익스텐션(Extension) 은 말 그대로 기존에 존재하는 타입에 기능을 ‘확장’해주는 기능이다. 마치 기존에 완성되어 있는 레고 블록에 다른 블록을 덧붙여서 새로운 기능을 붙이는 것과 비슷하다.
익스텐션은 구조체(struct), 클래스(class), 열거형(enum), 프로토콜(protocol) 등의 타입에 새로운 기능을 추가하는 문법이다.
중요한 점은, 원래의 코드에 손대지 않고도 기능을 더할 수 있다는 것이다. 즉, 다른 사람이 만든 타입이더라도, 혹은 애플이 만든 타입이더라도 익스텐션을 통해 기능을 추가할 수 있다. 이게 바로 익스텐션의 매력이다.
익스텐션으로 할 수 있는 것들
익스텐션을 통해 어떤 기능을 추가할 수 있을까?(: 아래와 같은 것들이 가능하다.
- 연산 프로퍼티 (계산해서 값을 반환해주는 속성)
- 인스턴스 메서드 (객체가 호출하는 메서드)
- 타입 메서드 (static 키워드를 사용하는 메서드)
- 이니셜라이저 (초기화 함수)
- 서브스크립트 (배열처럼 인덱스로 접근하는 기능)
- 중첩 타입 (타입 안에 타입을 넣는 것)
- 프로토콜 채택 및 구현
단, 기존에 있는 기능을 수정하거나 재정의(override) 하는 것은 절대 불가능하다. 이건 익스텐션이 ‘추가’만 가능하지 ‘변경’은 안 된다는 의미다.
클래스 상속 vs 익스텐션
익스텐션은 자칫 클래스의 상속과 비슷해 보일 수 있다. 둘 다 어떤 타입에 기능을 더할 수 있기 때문이다. 하지만 두 기능은 매우 다르다.
항목 | 상속 | 익스텐션 |
확장 방향 | 수직 확장 (상속 구조) | 수평 확장 (기능 추가) |
적용 대상 | 클래스만 가능 | 모든 타입 가능 (struct, enum 등 포함) |
기능 재정의 | 가능 (override) | 불가능 |
간단히 말해서 상속은 타입 자체를 새로 만드는 것, 익스텐션은 기존 타입에 기능만 살짝 얹는 것이다.
왜 익스텐션을 사용할까?
만약 내가 어떤 외부 라이브러리를 쓰고 있는데, 거기에 있는 타입에 기능 하나를 추가하고 싶다고 해보자. 그런데 그 라이브러리의 코드는 내가 수정할 수 없다. 이럴 때 익스텐션을 사용하면, 간단하게 원하는 기능을 덧붙일 수 있다.
또한, 코드의 가독성과 관리 효율을 높이기 위해서도 익스텐션을 사용한다. 하나의 타입에 여러 기능이 있을 때, 관련 기능별로 익스텐션을 분리해서 작성하면 구조가 훨씬 깔끔해진다.
실전 예제: 진짜 쉬운 익스텐션 사용법
1. 연산 프로퍼티 추가하기
extension Int {
var isEven: Bool {
return self % 2 == 0
}
var isOdd: Bool {
return self % 2 == 1
}
}
print(4.isEven) // true
print(3.isOdd) // true
이건 단순하지만 정말 많이 쓰는 패턴이다.
2. 메서드 추가하기
extension Int {
func multiply(by n: Int) -> Int {
return self * n
}
}
print(5.multiply(by: 3)) // 15
자주 사용하는 연산이나 기능을 메서드로 만들어두면 코딩이 훨씬 빨라진다.
3. 이니셜라이저 추가하기
extension String {
init(int: Int) {
self = "\(int)"
}
init(double: Double) {
self = "\(double)"
}
}
let str1 = String(int: 42) // "42"
let str2 = String(double: 3.14) // "3.14"
숫자를 문자열로 초기화할 때, 더 읽기 쉬운 코드로 바꿀 수 있다.
🧠 보충 설명: 클래스에서 이니셜라이저 추가는 어떻게?
클래스의 경우 익스텐션에서는 반드시 convenience initializer만 추가할 수 있다.
왜냐하면 클래스 내부의 저장 프로퍼티에 익스텐션 바깥에서는 직접 접근이 불가능하기 때문이다. 따라서 새로 만드는 생성자에서는 반드시 기존에 클래스 내부에서 정의된 생성자(= 기존 생성자)를 self.init(...) 방식으로 호출해야 한다.
"기존 생성자"란 클래스 내부에 정의된 지정(initial) 생성자를 의미한다. 익스텐션에서는 이 지정 생성자를 직접 작성할 수는 없고, 단지 호출만 가능하다.
예시:
class User {
let name: String
init(name: String) {
self.name = name
}
}
extension User {
convenience init(id: Int) {
self.init(name: "User\(id)")
}
}
여기서 self.init(name:)는 클래스 내부에 이미 정의된 기존 생성자를 호출하는 것이다. 익스텐션에서는 이렇게 기존 생성자만 이용해 새로운 생성자를 만들 수 있으며, 프로퍼티를 직접 초기화할 수는 없다.
💡 참고로 구조체(struct)의 경우엔 익스텐션에서도 저장 프로퍼티 초기화가 가능하므로, 지정 생성자도 만들 수 있다. 따라서 구조체는 convenience 키워드 자체를 쓸 필요도 없다.
4. 문자열 꾸미기 - withBrackets 예제
extension String {
var withBrackets: String {
return "[\(self)]"
}
}
let title = "Notice"
print(title.withBrackets) // [Notice]
반복해서 쓰는 포맷은 익스텐션으로 빼두면 훨씬 깔끔해진다.
5. 서브스크립트(subscript) 추가하기
Swift에서는 기본적으로 문자열에 숫자 인덱스로 바로 접근할 수 없다. 예를 들어:
let word = "Swift"
print(word[2]) // ❌ 오류 발생
그 이유는 Swift 문자열이 유니코드 기반이라 문자마다 길이가 다를 수 있기 때문이다. 그래서 Swift는 "몇 번째 문자"를 안전하게 찾으려면 복잡한 문법을 써야 한다.
이를 간단하게 하기 위해 아래처럼 익스텐션을 사용해 subscript를 추가할 수 있다:
extension String {
subscript(index: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: index)]
}
}
let word = "Swift"
print(word[0]) // S
print(word[2]) // i
위 코드는 word[2]처럼 인덱스로 문자열에 접근 가능하게 만들어준다. 내부적으로는 startIndex에서 offsetBy만큼 이동한 위치의 문자를 반환하는 것이다. Python이나 JavaScript 스타일로 문자열을 쓰고 싶을 때 매우 유용하다.
실무에서 자주 쓰는 익스텐션 예제
▸ UIViewController에서 알림창 보여주기
extension UIViewController {
func showAlert(message: String) {
let alert = UIAlertController(title: "알림", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "확인", style: .default))
present(alert, animated: true)
}
}
▸ UIColor에 앱 고유 색상 추가
extension UIColor {
static let mainColor = UIColor(red: 0.2, green: 0.6, blue: 0.9, alpha: 1)
}
▸ 날짜 포맷 정리하기
extension Date {
var formatted: String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: self)
}
}
이처럼 공통 기능을 익스텐션으로 정리하면 유지 보수도 쉬워지고, 코드도 훨씬 깔끔해진다.
✅ 정리
구분 | 구조체 (Struct) | 클래스 (Class) |
익스텐션에서 저장 프로퍼티 직접 초기화 | ✅ 가능 | ❌ 불가능 |
익스텐션에서 지정 생성자 추가 | ✅ 가능 | ❌ 불가능 |
익스텐션에서 편의 생성자(convenience) 추가 | ❌ 필요 없음 | ✅ 가능 (필수 조건) |
익스텐션은 코드를 '읽기 좋게' 만드는 힘
익스텐션은 단순히 기능을 추가하는 것뿐만 아니라, 코드를 더 명확하고, 재사용 가능하게 만드는 강력한 도구다.
- 반복되는 코드를 줄이고,
- 공통 기능을 한곳에 모으며,
- 타입별로 기능을 분리해서 관리할 수 있다.
특히 프로토콜 + 익스텐션 조합은 Swift의 철학인 프로토콜 지향 프로그래밍의 핵심이다.
처음엔 생소할 수 있지만, 조금씩 적용해보면 실무에서 얼마나 유용한 기능인지 금방 느끼게 될 것이다:)
'IT' 카테고리의 다른 글
Swift 고차 함수 쉽게 배우기: map, filter, reduce 실전 예제 (0) | 2025.05.22 |
---|---|
Swift 오류처리 : 자판기 예제로 배우는 throw, throws, try, do-catch, switch-case, defer (0) | 2025.05.21 |
스위프트 프로토콜 vs 클래스 상속: 유연한 기능 구현을 위한 최적의 선택 (0) | 2025.05.11 |
Swift : assert, guard, 그리고 제어 흐름 제어문 (0) | 2025.05.11 |
Swift에서 is와 as로 배우는 타입 확인과 변환의 핵심 (0) | 2025.05.11 |
댓글
이 글 공유하기
다른 글
-
Swift 고차 함수 쉽게 배우기: map, filter, reduce 실전 예제
Swift 고차 함수 쉽게 배우기: map, filter, reduce 실전 예제
2025.05.22 -
Swift 오류처리 : 자판기 예제로 배우는 throw, throws, try, do-catch, switch-case, defer
Swift 오류처리 : 자판기 예제로 배우는 throw, throws, try, do-catch, switch-case, defer
2025.05.21 -
스위프트 프로토콜 vs 클래스 상속: 유연한 기능 구현을 위한 최적의 선택
스위프트 프로토콜 vs 클래스 상속: 유연한 기능 구현을 위한 최적의 선택
2025.05.11 -
Swift : assert, guard, 그리고 제어 흐름 제어문
Swift : assert, guard, 그리고 제어 흐름 제어문
2025.05.11