본문 바로가기
iOS/Swift

Swift 함수① - 함수?메소드?클로저?/사용자 정의 함수/함수 정의/함수 호출

 
 
 
안녕하세요, UX를 고려하는 개발자 유자🍋입니다.
첫 포스팅은 함수를 주제로
기본적인 용어를 정리하며 시작합니다.

 
 
 

1. 함수의 기본 개념

 
 
 

1-1. 함수(Function)?

 
프로그래밍에서 함수
어떤 특정한 일을 하는 명령어들을 묶어 놓은 것을 의미합니다.
 
 
 
 
 

1-2. 함수? 메소드? 클로저?

 

Swift에서 함수, 메소드, 클로저는 어떤 차이가 있을까요? 다음과 같이

 
 

func sayHello() {
    print("안녕하세요")
}

 
 

func 키워드를 가지고 전역으로 사용할 수 있는 함수를 그냥 함수라고 부릅니다.
 
 
 
반면 다음과 같이 구조체, 클래스 등 특정 타입에 연관되어 사용하는 함수

 
 

class Meet {
    func sayHello() {
        print("안녕하세요")
    }
}

 
 

메소드라고 표현합니다.

 
 

즉, 함수와 메서드는 기본적으로 같으나
상황이나 위치에 따라 다른 용어로 부르는 것입니다.

 
 

클로저는 클로저 관련 포스팅에서 알아볼 예정이라
지금은 '함수는 클로저의 한 형태'라는 개념만 알고 계시면 좋을 것 같습니다.
 
 

 
 
 
 
 
 
 
 
 
 

 

 

2. 함수를 정의하는 방법

 

 

Swift에서 함수를 정의 방법은 다음과 같습니다.

 

 

 


2-1. 키워드 및 함수 이름

 

함수를 정의하는 방법

 
 
가장 먼저 func 키워드를 작성한 후
한 칸 띄우고, 원하는 함수 이름을 작성합니다.
 
 
이때 함수 이름은 반드시 영어 소문자 또는 언더바(_)로 시작해야 하며,
두 번째 단어는 첫 글자를 대문자로 작성해야 합니다.
(ex. appleAlbum, doorWindow)
 
 
Swift에서 함수 이름을 만들 때는 다음과 같이 숫자를 사용할 수 있습니다.
다만, 첫 번째 글자에서는 숫자 사용이 불가합니다!

 
 

//사용가능
func a001() {
}

//사용불가
func 200() {
}

 

 
 
만약 다음과 같이 숫자로 작성된 함수가 많을 경우,
 

 

func a001() {}
func a002() {}
func a003() {}

 

 
각 함수가 어떤 기능을 하는지 알 수 없기 때문에
함수 이름과 기능을 외워서 사용해야 합니다.

 
 

이럴 경우 재사용 및 생산성 측면에서 불편함이 발생하니
숫자를 남발하지 않도록 주의해서 작성해야 합니다!
 
 
 
 
 
 
 
 

2-2. 매개변수(파라미터)


함수 이름을 작성했다면 다음은 외부로부터 받는 값과 관련된 내용,
즉 매개변수(파라미터) 영역을 소괄호로 감싸야 합니다.
 

함수를 정의하는 방법

 
매개변수를 작성하는 방법은 크게 3가지가 있으며,
하나씩 차근차근 알아보겠습니다.
 
 
 

① 매개변수가 없는 함수

 
매개변수 영역을 표시하는 소괄호 내부를 비워둡니다.

 
 

func greeting() {}

 
 

이때 조건문이나 반복문 같은 Swift의 다른 문법과 달리
소괄호를 생략할 수 없는 점 반드시 유의하셔야 합니다!

 
 
 
 
 

② 함수 외부에서 사용할 이름, 함수 내부에서 사용할 이름이 다른 경우

함수 외부에서 사용할 이름을 적고 한 칸 띄운 후 함수 내부에서 사용할 이름,
콜론(:)을 작성 뒤, 타입을 적어줍니다.
 
 

함수를 정의하는 방법

 
 
이렇게 함수 외부에서 사용할 이름과 함수 내부에서 사용할 이름을 다르게 작성하는 것을
전달 인자 레이블과 매개변수 이름을 다르게 작성한다고 표현하며, 정리하면 다음과 같습니다.
 
 
 
전달 인자 레이블(argument Label) - 함수 외부에서 사용할 이름
매개변수 이름(parameter Name) - 함수 내부에서 사용할 이름
 
 
 

실제 예시입니다.

 
 

//함수 정의
func greeting(to name: String) {
    print("안녕하세요, \(name)님")
}

//함수 호출
greeting(to: "홍길동")

 
 

위 예시에서 전달 인자 레이블과 매개 변수이름을 찾으면 다음과 같습니다.
 
전달 인자 레이블: to
매개변수 이름: name
 
 
 
 
그렇다면 전달 인자 레이블과 매개변수 이름을 분리하지만
전달 인자 레이블을 사용하지 않고 싶다면 어떻게 작성해야 할까요?

 
 

//함수 정의
func greeting(_ name: String) {
    print("안녕하세요, \(name)님")
}

 
 

위 예시와 같이 _(언더바)를 작성하여 전달 인자 레이블을 생략할 수 있으며
이를 와일드카드 패턴이라고 합니다.
 
 
즉, 외부에서 사용할 이름과 내부에서 사용할 이름을 분리하지만
전달 인자 레이블을 사용하지 않겠다는 뜻이 되죠. 
 

이렇게 전달 인자 레이블을 생략한 함수를 호출할 때는 다음과 같이

 
 

//함수 호출
greeting("홍길동")

 
 

전달 인자 레이블을 작성하지 않고, 전달 인자만을 이용해서 호출할 수 있게 됩니다.
(전달 인자란? 실제 전달하는 값을 의미합니다.)
 
 
 
 
 

 

③ 함수 외부에서 사용할 이름, 함수 내부에서 사용할 이름이 같은 경우

 
이럴 경우엔 다음과 같이
 

함수를 정의하는 방법

 
 
함수 내부와 외부에서 공통으로 사용할 이름,
콜론(:), 타입을 순서대로 작성합니다.
 
 

실제 예시입니다. 예시에서 'name'은 함수 내부와 외부에서 사용됩니다.

 
 

func greeting(name: String) {
    print("안녕하세요, \(name)님")
}

 

greeting(name: "홍길동")

 
 
 
 
 
 
 
 

2-3. 반환


다음은 함수의 반환 타입을 작성해 줄 차례입니다.
 
 
 
반환 타입이란? 함수가 실행된 결과로
어떤 값을 내놓을 것인지와 관련된 내용입니다.

 
 
 
함수의 반환 타입을 표시할 때는 다음과 같이
소괄호 바로 뒤에 하이픈(-)과 오른쪽 앵글 브래킷(>)을
작성한 뒤 반환 타입을 작성합니다.

 

함수를 정의하는 방법

 
 
이때 반환 타입으로는 String, Bool 등 기본 자료형은 물론이고
클래스 객체 또한 사용이 가능합니다.
 

이렇게 반환 타입까지 작성해 주었으면,
함수 내부에 return 키워드, 반환값을 작성합니다.
 
 
함수의 반환과 관련된 몇 가지 사례를 알아보겠습니다.
 
 
 
 
① return 키워드 생략

 
함수에서는 return 키워드를 생략할 수 있는 경우가 있습니다.
다음과 같이

 
 

func introduce(name: String) -> String {
    "제 이름은 "+name+"입니다"
}

 
 

1. 함수 내부의 코드가 단 한 줄이고!
2. 그 코드의 타입이 함수 반환 타입과 일치한다면!
 
return 키워드를 생략해도

 
 

return 생략

 

 
정상적으로 실행되는 것을 확인할 수 있습니다.
 
 
 
 
 
 
② 반환이 없는 함수

반환이 없는 함수를 만들고 싶을 경우에는
‘없음’을 의미하는 Void를 작성하거나

 
 

func say() -> Void {}

 
 

반환과 관련된 부분을 전부 생략해 주면 됩니다.
 

 

func say() {}

 
 
 
 
 
 
 
 
③ 여러 개의 값을 반환하고 싶을 경우

함수 반환과 관련해서 유의해야 할 점은
함수는 반드시 하나의 값만 반환해야 한다는 것입니다.
 
 
만약 여러 개의 값을 반환해야 한다면
딕셔너리나 배열,  튜플과 같은
집단 자료형에 담아서 반환해야 합니다.
 

다음은 (Int, String)의 조합으로 구성된 튜플을 반환하는 함수 예시입니다.

 
 

func student() -> (Int, String) {
    let age = 20
    let name = "홍길동"
    return (age, name)
}

 
 
 
 
 
 
④ 반환값을 사용할 수도 있고, 사용하지 않을 수도 있는 경우

 
이럴 경우, 함수의 결괏값을 버릴 수도 있다는
@discardableResult를 함수 앞에 작성하면

 
 

@discardableResult func say(_ name: String) -> String {
    print(name)
    return(name)
}

 
 

아래와 같이 함수를 호출해도 경고문이 나오지 않습니다.

 
 

say("홍길동")

 
 

만약 @discardableResult를 작성하지 않으면
다음과 같은 Warning이 뜹니다.
 
'Result of call to 'functionName' is unused'
 

Warning 내용

 
 
 
 
 

2-4. 함수 정의 예시

 

위에서 알아본 내용을 정리하면 다음과 같습니다.

 
 

//①매개변수와 반환값이 모두 없는 함수
func greeting() {
    print("안녕하세요!")
}

//②매개변수는 있지만 반환값이 없는 함수
func greeting(name: String) {
    print("안녕하세요, \(name)님")
}

//③매개변수가 없고 반환값이 있는 함수
func greeting() -> String {
    let say = "안녕하세요!"
    return say
}

//④매개변수와 반환값이 모두 있는 함수
func greeting(name: String) -> String{
    let say = "안녕하세요, \(name)님"
    return say
}

 
 
 
 
 
 
 

3. 함수 호출

 

함수를 사용하려면 반드시 ‘호출’을 해줘야 합니다.
Swift에서 함수를 호출하는 방법은 다음과 같습니다.
 

함수 호출

 
위에서 알아본 내용으로 함수를 정의하고,
 
 
함수 정의
 

func greeting(name: String) {
    print("안녕하세요, \(name)님")
}

 
 
두 가지 방식으로 호출하면
 
 
호출①
 

let inputName = "홍길동"
greeting(name: inputName)

 
 
 
호출②
 

greeting(name: "홍길동")

 
 
 
출력
 

안녕하세요, 홍길동님

 
 
호출①과 호출② 전부 제대로 출력되는 것을 확인할 수 있습니다.
 
호출②의 경우 불필요한 코드를 줄이기 위해 실제 값을 바로 넣어준 경우입니다.
 
 
 
 
 
 
 

 

 

4. 함수를 사용하는 이유

 
그렇다면 함수를 사용해야 하는 이유는 무엇일까요?
 

 


예를 들어, 아메리카노 만드는 방법을 매일 누군가에게
알려줘야 한다고 가정해 보겠습니다.
 

 


이때 함수를 사용하지 않는다면
다음과 같은 문장을 매일 직접 작성해야 할 것입니다.
 
 

print("원두를 준비한다")
print("원두를 분쇄한다")
print("머신을 통해 에스프레소를 추출한다")
print("물에 에스프레소를 부어서 섞는다")

 

 
 
이 작업을 매일 해야 한다면 매우 번거롭고,
반복적인 코드가 계속 작성되는 문제가 발생합니다.
 
 
그리고 이러한 문제를 해결할 수 있는 것이 바로 함수입니다.
 
 
함수를 사용하면 처음부터 다시 작성할 필요 없이
 
 

func howToMake() {
    print("원두를 준비한다")
    print("원두를 분쇄한다")
    print("머신을 통해 에스프레소를 추출한다")
    print("물에 에스프레소를 부어서 섞는다")
}
howToMake()

 

 
 
함수만 호출하여 쓸 수 있기 때문에
반복적인 코드 작성을 피할 수 있고 코드 재사용이 쉬워집니다.
 


그뿐만 아니라 함수는 코드를 여러 덩어리로 나눠서
사용하는 것이기 때문에 가독성 측면에서도 훨씬 좋아집니다.
 


 
이것이 우리가 함수를 만들고, 사용해야 하는 이유입니다.
 


 
 
여기까지 함수의 기본적인 내용과
함수를 사용하는 이유에 대해서 알아보았습니다.
 
 
잘못된 내용이나 피드백이 있다면 언제든 환영합니다
댓글은 작성자에게 큰 힘이 됩니다💪🏻