-
일급객체가 뭔데?Apple🍎/Swift 2025. 2. 18. 23:03
프로그래밍을 하다 보면 '일급 객체'라는 단어를 접하곤 하는데요.
이 '일급'이라는 어감과 실제 설명하는 내용 사이에 간극이 있습니다.
그래서 오늘은 어원부터 출발해서 일급객체가 실질적으로 의미하는 것이 뭔지 알아보려고 합니다.
역사적 배경
옛날 옛적 영국에 '크리스토퍼 스트레이치'라는 아저씨가 살고 있었어요.
그 당시 영국에는 본토 출신과 식민지 출신 사이에 차별이 있었고 1등 시민, 2등 시민으로 나누어 법적, 사회적으로 권리를 제한했어요.
일등시민은 투표권, 재산권등의 모든 권리를 가진 사람들이었고, 이등시민은 제한된 권리만 가진 사람들이었지요.
우리 프로그래밍 언어 설계에 푹 빠져 있던 크리스토퍼 아저씨는 프로그래밍 언어에도 이와 같은 차별이 있다는 것을 발견했어요.
// 숫자는 변수에 저장할 수 있고 let number = 42 // 다른 함수에 전달할 수 있고 print(number) // 배열에 담을 수 있습니다 let numbers = [1, 2, 3] // 하지만 초기 프로그래밍 언어들에서 함수는 이런 것들을 할 수 없었습니다 // 함수를 변수에 저장하거나 // 함수를 다른 함수에 전달하거나 // 함수를 배열에 담는 것이 불가능했죠
그 당시 프로그래밍 언어에서는 숫자와 같은 '값'은
- 변수에 저장도 할 수 있고
- 다른 함수에 전달할 수 있고
- 배열에 담을 수도 있었어요.
하지만 함수와 같은 '동작'은 위의 것들이 불가능했답니다.
이러한 제약을 두고 크리스토퍼 아저씨는 숫자나 문자열 같은 데이터 타입은 '일급' 대우를 받고, 함수는 '이급' 취급을 한다고 생각했어요.
일급 객체가 되려면
프로그래밍 언어에서 일급 객체가 되기 위해서는 다음과 같은 특권을 가져야해요.
- 변수나 데이터 구조(ex.array)에 저장될 수 있어야 해요.
- 함수의 매개변수로 전달될 수 있어야해요.
- 함수의 반환값이 될 수 있어야해요.
- 실행(런타임)중에 생성될 수 있어야해요.
Swift에서 일급 객체
Swift는 현대적인 프로그래밍 언어로서, 거의 모든 타입(값타입, 참조 타입, 컬렉션, 클로저(함수)등)을 일급 객체로 취급해요.
특히 '일급 객체'라는 용어는 클로저 개념을 볼 때 자주 접하곤 하는데요.
클로저가 어떻게 일급 객체가 될 수 있는지 다음 코드들을 통해 살펴봅시다.
일단 클로저는 변수에 할당이 가능해요.
// 1. 클로저(함수)를 변수에 저장 let greet = { (name: String) in print("안녕하세요, \(name)님!") } // 호출 greet()
다음으로 방금 정의한 greet클로저를 다른 함수의 매개변수로 전달할 수도 있어요.
// 2. 클로저를 함수의 매개변수로 전달 func performGreeting(greeter: (String) -> Void, person: String) { greeter(person) } performGreeting(greeter: greet, person: "Kim")
그리고 다음과 같이 함수의 반환값이 되어 활용될 수도 있고요.
// 3. 클로저를 반환하는 함수 func makeAdder(base: Int) -> (Int) -> Int { return { number in return base + number } } let addFive = makeAdder(base: 5) addFive(3) // 5 + 3 = 8
마지막으로 아래 예제를 통해 실행(런타임)에 동적으로 생성될 수 있음을 좀 더 구체적으로 살펴 볼 수 있어요.
// 사용자의 주문을 처리하는 시스템을 가정해봅시다 struct Order { let price: Double let quantity: Int } // 주문 목록 (런타임에 사용자로부터 입력받는다고 가정) var orders: [Order] = [ Order(price: 1000, quantity: 2), Order(price: 2000, quantity: 1), Order(price: 3000, quantity: 3) ] // 할인율은 시간대나 프로모션에 따라 런타임에 결정됩니다 func getCurrentDiscount() -> Double { // 실제로는 현재 시간이나 프로모션 상태를 확인 let currentHour = Calendar.current.component(.hour, from: Date()) switch currentHour { case 9...11: // 오전 할인 return 0.1 case 14...16: // 오후 할인 return 0.2 default: return 0.0 } } // 주문 처리 함수 func processOrders(_ orders: [Order]) { // 현재 할인율을 확인 (런타임에 결정됨) let discount = getCurrentDiscount() // 각 주문에 대해 할인이 적용된 최종 가격을 계산하는 클로저를 생성 let finalPrices = orders.map { order in // 이 클로저는 런타임에 결정된 할인율을 사용합니다 let totalPrice = order.price * Double(order.quantity) let discountedPrice = totalPrice * (1 - discount) return discountedPrice } // 결과 출력 print("현재 할인율: \(discount * 100)%") print("최종 가격들: \(finalPrices)") } // 주문 처리 실행 processOrders(orders)
1. 동적 입력 데이터 : orders 배열은 실제로는 사용자 주문에 따라 런타임에 채워지고
2. 런타임 조건문 : 할인율이 현재 시간에 따라 동적으로 결정되며
3. 클로저의 동적 동작 : map 함수에 전달되는 클로저는
- 런타임에 결정된 주문 데이터와 할인율을 사용해서
- 각 주문에 맞춰 새롭게 '생성'되어 실행되요.
따라서 클로저는 런타임에 동적으로 생성될 수 있다는 조건을 만족함으로써 '일급 객체'가 될 수 있지요.
오늘 배운 일급 객체 개념은 현대 프로그래밍에서 매우 중요해요.
함수를 일급 객체로 취급함으로써 동일한 함수를 다양한 상황에서 유연하게 활용할 수 있게 되고
복잡한 로직을 함수로 캡슐화하고 이를 다른 함수에 전달하는 형태로 사용할 수 있게 되었어요.
이에 따라 함수형 프로그래밍 패러다임을 적용이 가능해져 map, filter, reduce와 같은 고차함수를 사용하여 더 선언적인 코드를 작성할 수 있어요.
'Apple🍎 > Swift' 카테고리의 다른 글
Swift를 위한 람다 계산법 핵심 (0) 2025.02.25 고차함수 for Swift (0) 2025.02.25 클로저 종결판 (0) 2025.02.23 [Swift] Property 제대로 써보자. (0) 2023.12.12 [Swift] Enum을 다양하게 활용해보자. (0) 2023.12.11