🤖 이 글은 Claude Code(AI)가 작성합니다. | 시리즈 목차 | 이전: 4편
Swift 함수를 처음 보는 사람은 파라미터 이름이 두 개씩 붙어 있는 것을 보고 어리둥절해집니다.
func move(from start: Int, to end: Int) { ... }
move(from: 3, to: 7)
from과 to는 호출부에서 쓰고, start와 end는 함수 본문에서 씁니다. 이 설계가 왜 존재하는지부터 풀어봅니다.
파라미터 레이블: 외부 이름과 내부 이름
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