Burt.K

Awesome Discovery

[SE-0009] 인스턴스 멤버 접근 시 self 사용 강제화(Rejected)

작성일 — 2025년 3월 9일

Table of Contents

인스턴스 멤버 접근 시 self 사용 강제화

소개

현재 Swift 버전(2.1)에서는 클로저 내에서 인스턴스 멤버에 접근할 때 self를 사용해야 한다. 이 제안은 이를 모든 멤버 접근으로 확장하는 것을 제안한다(이것은 Objective-C에서 본질적으로 그렇듯이). 이는 인스턴스 프로퍼티와 로컬 변수를 구분하고, 인스턴스 함수와 로컬 함수 또는 클로저를 구분하는 데 유용하다.

Swift Evolution 토론 스레드

동기

이 제안은 인스턴스 프로퍼티와 로컬 변수, 그리고 인스턴스 함수와 로컬 함수/클로저를 명확히 구분한다. 이는 여러 가지 장점을 가진다:

이 제안으로 방지할 수 있는 버그의 예시(Rudolf Adamkovic 제공):

class MyViewController : UIViewController {
	@IBOutlet var button: UIButton!
        var name: String = "David"

	func updateButton() {
		// var title = "Hello \(name)"
		button.setTitle(title, forState: .Normal) // 이 줄을 주석 처리하지 않았지만 컴파일러는 경고하지 않고, 실수로 UIViewController의 title을 참조하게 됨
		button.setTitleColor(UIColor.blackColor(), forState: .Normal)
	}
}

API 디자인 가이드라인은 API 작성용이지만, 여전히 Swift의 기본 원칙을 대표한다고 생각한다. 첫 두 가지 원칙은 다음과 같다:

이 제안은 이러한 목표와 직접적으로 일치한다고 믿는다.

반론

커뮤니티의 두 멤버가 제기한 반론은 현재 동작이 “클로저 내에서 self의 캡처 의미를 더 두드러지게 만든다”는 것이다. 이는 사실이지만, 저자는 그 유용성이 부족하다고 생각한다.

다음 코드에서 우리는 foobar가 예외를 던지는 함수이고 barfoo는 예외를 던지지 않는다는 것을 명확히 알 수 있다.

try foobar()
barfoo()

그러나 클로저 내에서 self를 사용하는 예제를 보자:

foobar({
	print(self.description)
})

위 코드에서 self 키워드는 힌트를 제공하지만 확실한 정보를 제공하지는 않는다:

반대 예제를 살펴보자:

barfoo({
	print(description)
})

이 두 예제에서 self 키워드는 호출된 함수의 시그니처를 확인하지 않고서는 참조 순환 문제에 대해 주의해야 하는지 여부를 확실히 알려주지 않는다. 단지 self가 캡처되었음을 알려줄 뿐이다. 제안하는 방식에서는 self가 다시 의미를 갖게 된다: 어떤 것이 지역 프로퍼티이고 어떤 것이 인스턴스 프로퍼티인지 나타낸다.

제안하는 해결책

인스턴스 프로퍼티와 함수에 접근할 때 self를 사용하지 않는 방식은 두 단계로 적용할 것을 제안한다. Swift 2.x에서는 경고로 시작하고, Xcode가 Fix-It을 제공할 수 있다. 그런 다음 Swift 3에서는 컴파일러 오류로 변경되고, 마이그레이터가 코드를 전환하는 데 도움을 줄 수 있다.

다음 코드는 이전에는 컴파일되었지만, 주석이 달린 줄에서 오류를 발생시킨다:

class Person {
	var name: String = "David"
	
	func foo() {
		print("Hello \(name)") // 컴파일되지 않음
	}
	
	func bar() {
		foo() // 컴파일되지 않음
	}
}

이 코드는 다음과 같이 수정해야 정상적으로 컴파일된다:

class Person {
	var name: String = "David"
	
	func foo() {
		print("Hello \(self.name)")
	}
	
	func bar() {
		self.foo()
	}
}

기존 코드에 미치는 영향

이 제안은 기존 코드에 상당한 영향을 미친다. 하지만 마이그레이션 도구와 Xcode의 Fix-It 기능으로 쉽게 해결할 수 있다.

고려된 대안들

현재 동작을 유지하는 방법도 하나의 대안이다. 하지만 이 경우 앞서 언급한 단점들이 여전히 존재한다.

다른 대안으로는 컴파일 오류를 경고 수준으로 낮추는 방법이 있다.

커뮤니티 반응