[5편] 함수 — 파라미터 레이블이 두 개인 이유

🤖 이 글은 Claude Code(AI)가 작성합니다. | 시리즈 목차 | 이전: 4편

Swift 함수를 처음 보는 사람은 파라미터 이름이 두 개씩 붙어 있는 것을 보고 어리둥절해집니다.

func move(from start: Int, to end: Int) { ... }
move(from: 3, to: 7)

fromto는 호출부에서 쓰고, startend는 함수 본문에서 씁니다. 이 설계가 왜 존재하는지부터 풀어봅니다.


파라미터 레이블: 외부 이름과 내부 이름

Swift 함수의 파라미터는 외부 이름(argument label)내부 이름(parameter name)을 따로 가질 수 있습니다.

func greet(person name: String) {
    print("안녕하세요, \(name)!")  // 내부에서는 name 사용
}

greet(person: "철수")  // 호출부에서는 person 사용

외부 이름은 호출 코드를 영어 문장처럼 읽히게 만들기 위한 장치입니다. greet(person: "철수")는 “철수라는 사람에게 인사해”라고 읽힙니다. 내부 이름은 함수 본문에서 실제로 쓰기 편한 짧은 이름을 쓸 수 있게 합니다.

외부 이름을 생략하고 싶을 때는 _를 씁니다. 이 경우 호출부에서 레이블 없이 값만 씁니다.

func square(_ n: Int) -> Int {
    return n * n
}

square(5)   // 레이블 없이 호출
// square(n: 5) 는 오류

외부 이름과 내부 이름을 따로 쓰지 않으면 같은 이름이 두 역할을 모두 합니다.

func add(a: Int, b: Int) -> Int {
    return a + b
}

add(a: 3, b: 4)  // 외부 이름 = 내부 이름 = a, b

반환 타입

반환 타입은 -> 뒤에 씁니다.

func celsius(from fahrenheit: Double) -> Double {
    return (fahrenheit - 32) * 5 / 9
}

let temp = celsius(from: 98.6)  // 37.0

반환값이 없으면 -> Void를 쓰거나 아예 생략합니다. 둘은 동일합니다.

func log(_ message: String) {
    print(message)
}

함수 본문이 표현식 하나로만 이루어진 경우 return을 생략할 수 있습니다.

func square(_ n: Int) -> Int { n * n }

튜플로 여러 값 반환

Swift는 튜플(tuple)을 이용해 여러 값을 한 번에 반환할 수 있습니다.

func minMax(of array: [Int]) -> (min: Int, max: Int) {
    var min = array[0]
    var max = array[0]
    for n in array {
        if n < min { min = n }
        if n > max { max = n }
    }
    return (min, max)
}

let result = minMax(of: [3, 1, 8, 2, 5])
print(result.min)  // 1
print(result.max)  // 8

기본값 파라미터

파라미터에 기본값을 지정하면, 호출 시 그 인자를 생략할 수 있습니다.

func repeat(text: String, times: Int = 3) -> String {
    return String(repeating: text, count: times)
}

repeat(text: "안녕")        // "안녕안녕안녕"
repeat(text: "안녕", times: 5)  // "안녕안녕안녕안녕안녕"

기본값이 있는 파라미터는 보통 뒤쪽에 배치하는 것이 관례입니다.


가변 인자

타입 뒤에 ...을 붙이면 같은 타입의 값을 개수 제한 없이 받습니다. 함수 내부에서는 배열로 취급됩니다.

func sum(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
}

sum(1, 2, 3)         // 6
sum(10, 20, 30, 40)  // 100

inout — 함수 안에서 외부 값 변경

Swift 함수는 기본적으로 인자를 복사해서 받습니다. 함수 내부에서 파라미터를 바꿔도 원본에는 영향이 없습니다.

func double(_ n: Int) {
    var n = n
    n *= 2
    // 원본은 그대로
}

var x = 5
double(x)
print(x)  // 5 (변하지 않음)

원본을 변경하고 싶다면 inout을 씁니다. 호출부에서는 변수 앞에 &를 붙입니다.

func doubleInPlace(_ n: inout Int) {
    n *= 2
}

var x = 5
doubleInPlace(&x)
print(x)  // 10

&는 “이 변수의 주소를 넘긴다”는 신호입니다. 함수가 원본을 바꿀 수 있다는 사실을 호출부에서도 명시적으로 표시하게 합니다. 표준 라이브러리의 swap(_:_:)이 이 패턴으로 구현됩니다.


함수는 일급 시민이다

Swift에서 함수는 일급 시민(first-class citizen)입니다. 이는 함수를 값처럼 다룰 수 있다는 의미입니다.

  • 변수에 담을 수 있다
  • 다른 함수의 인자로 넘길 수 있다
  • 함수의 반환값으로 돌려줄 수 있다
func add(_ a: Int, _ b: Int) -> Int { a + b }
func multiply(_ a: Int, _ b: Int) -> Int { a * b }

// 함수를 변수에 담기
var operation: (Int, Int) -> Int = add
print(operation(3, 4))  // 7

operation = multiply
print(operation(3, 4))  // 12

// 함수를 인자로 넘기기
func apply(_ op: (Int, Int) -> Int, to a: Int, and b: Int) -> Int {
    return op(a, b)
}

apply(add, to: 3, and: 4)       // 7
apply(multiply, to: 3, and: 4)  // 12

함수 타입은 (파라미터 타입들) -> 반환 타입으로 표기합니다. (Int, Int) -> Int는 “두 Int를 받아 Int를 반환하는 함수 타입”입니다.

이 개념이 왜 중요한지는 다음 편의 클로저에서 본격적으로 드러납니다.


다른 언어와 비교

Python JavaScript Swift
파라미터 레이블 키워드 인자 (def f(*, name)) 없음 외부/내부 이름 분리
기본값 있음 있음 있음
가변 인자 *args ...args 타입...
참조 전달 객체는 기본 참조 객체는 기본 참조 명시적 inout
다중 반환 튜플/리스트 객체/배열 이름 있는 튜플
함수 일급 시민 있음 있음 있음

핵심 요약

  • 파라미터는 외부 이름(호출부)과 내부 이름(본문)을 따로 가질 수 있다. 호출 코드를 자연어처럼 읽히게 만들기 위한 설계다.
  • _로 외부 이름을 생략하면 호출 시 레이블 없이 값만 넘긴다.
  • 튜플로 여러 값을 한 번에 반환할 수 있다.
  • inout은 함수가 원본 변수를 직접 수정할 수 있게 한다. 호출부에서 &로 표시한다.
  • 함수는 일급 시민이다. 변수에 담고, 인자로 넘기고, 반환값으로 돌려줄 수 있다.

다음 편은 6편 — 클로저: 함수를 변수에 담기입니다. 5편에서 잠깐 나온 함수 타입을 발전시켜, 이름 없는 함수 블록인 클로저와 Swift의 간결한 축약 문법을 다룹니다.

🤖 Generated with Claude Code

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다