본문 바로가기
iOS, Swift/Swift

Swift inout parameter(파라미터) 함수 마스터하기

by Developer88 2025. 3. 13.
반응형

오늘은 Swift의 inout parameter(파라미터)를 사용하는 함수에 대해 정리하고 마스터해 보겠습니다.

 

1. inout 파라미터

1-1. inout 파라미터

원래 Swift에서 함수나 메서드에 전달되는 파라미터는,
상수(constants)로 취급되어 함수 내에서 수정할 수 없습니다.

하지만 파라미터를 아래와 같이 inout 키워드와 함께 표시하면,

원래 상수라면 안 되는 다음의 일들이 가능해집니다.

  • 함수 내에서 파라미터를 수정 가능
  • 함수가 호출될 때 값을 전달받아 함수 내부에서 수정한 후, 수정된 값을 다시 원래 변수에 반영
func makeDouble(number: inout Int) {
    number *= 2
}

 

 

위 함수는 아래와 같이 사용해 주어야 합니다.

주의할 점은, inout 파라미터를 전달할 때,

'&' 기호를 붙여야 하는데요.

이것은 '이 인자를 inout 파라미터로 전달한다'는 의미를 가집니다.

이 함수를 거쳐 변경될 수 있는 값이라는 의미로 보면 되겠지요.

 

var testNum = 10 
makeDouble(number: &testNum)

 

 

2. 일반 함수 vs inout 파라미터 함수

일반함수와 inout 파라미터를 사용하는 함수를 비교하며 익혀 보겠습니다.

 

2-1. 일반 함수

먼저 inout 없이 일반파라미터를 사용하는 함수를 볼까요.
아래 코드에서, incrementNormal함수 호출 후에도,

myNumber는 상수로 취급하므로 변경 없이 5가 됩니다.

 

func incrementNormal(number: Int) {
    var copy = number
    copy += 1
    print("함수 내부: \(copy)")
    // 원본 변수는 수정되지 않음
}

var myNumber = 5
incrementNormal(number: myNumber)
print("일반 함수 호출 후: \(myNumber)") // 여전히 5

 

 

1-2. inout 파라미터 사용한 함수

반면, inout파라미터를 사용하는 함수를 보죠.

아래에서 incrementInout 함수 호출 후,

myNumber는 5가 아니라, 함수에 의해 변경된 6이 됩니다.

 

// inout 파라미터를 사용한 함수
func incrementInout(number: inout Int) {
    number += 1
    print("함수 내부: \(number)")
    // 원본 변수가 수정됨
}

var myNumber = 5
incrementInout(number: &myNumber)
print("inout 함수 호출 후: \(myNumber)") // 6으로 변경됨

 

3. 다른 예제 코드

여러 가지 예제 코드를 보면서 어떻게 사용하는지 익혀보겠습니다.

 

3-1. 두 변수 값 교환

아래는 inout 파라미터를 이용해서,

파라미터에 집어넣는 두 변수의 값을 서로 교환하는 코드입니다.

func swapValues<T>(a: inout T, b: inout T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var first = 30
var second = 50

print("교환 전: first = \(first), second = \(second)")
swapValues(a: &first, b: &second)
print("교환 후: first = \(first), second = \(second)")

//교환 전: first = 30, second = 50
//교환 후: first = 50, second = 30

 

 

3-2. 컬렉션 수정

inout파라미터를 이용해서,

array를 전달한 후, 

아래와 같이 추가할 수도 있습니다.

이럴 때는 꼭 inout 파라미터를 사용해야 하지요.

 

func addItemsToArray(array: inout [String], newItems: [String]) {
    for item in newItems {
        array.append(item)
    }
}

var fruits = ["사과", "바나나"]
let moreFruits = ["딸기", "포도"]

print("추가 전 과일: \(fruits)")
addItemsToArray(array: &fruits, newItems: moreFruits)
print("추가 후 과일: \(fruits)")

// 추가 전 과일: ["사과", "바나나"]
// 추가 후 과일: ["사과", "바나나", "딸기", "포도"]

 

3-3. Combine에서 구독 객체를 제공된 컬렉션에 저장하기

조금 복잡해 보이지만,

Combine에서 사용하는 사례를 볼까요?

 

아래 코드에서는, 

'.store(in: &subscriptions)'를 마지막에 추가함으로써,

생성된 구독을 subscriptions Set에 저장합니다.

inout 파라미터를 추가하므로,

subscriptions앞에 &를 붙여서 사용한 것이지요.

 

class SubscriptionExample: ObservableObject {
    // 구독을 저장할 Set 컬렉션
    private var subscriptions = Set<AnyCancellable>()
    
    init() {
        // 타이머 생성 (1초마다 값 발행)
        let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
        
        // 타이머 구독
        timer
            .sink { time in
                print("현재 시간: \(time)")
            }
            .store(in: &subscriptions) // 생성된 구독을 저장
        
        // 다른 Publisher도 간단히 구독
        Just("안녕하세요")
            .sink { message in
                print(message)
            }
            .store(in: &subscriptions) // 이 구독도 저장
    }
    
    // 객체가 해제될 때 subscriptions Set도 해제되면서
    // 자동으로 모든 구독이 취소됩니다
}

 

728x90

댓글