Swift

Hits

함수(Function)는 대부분의 프로그래밍 언어에서 지원하는 개념으로 프로그램의 실행 과정 중에서 독립적으로 처리될 수 있는 부분을 분리하여 구조화한 객체를 의미한다. 즉, 외부에 의존하는 부분 없이 툭 떼어 분리할 수 있는 실행 단위를 일종의 캡슐처럼 포장해놓은 것이다. 이렇게 독립적으로 작성된 함수는 간단한 방식으로 여러 번 호출하여 사용할 수 있어서 같은 코드를 반복해서 작성할 필요가 없다.

스위프트는 함수를 지원하므로, 이를 통해 한번 작성된 코드를 여러 곳에서 호출하여 사용할 수 있다. 특히 스위프트는 함수형 프로그래밍 패러다임을 채택하고 있는 언어이므로 함수형 프로그래밍의 특성을 이해하는 것은 매우 중요하다.

1. 함수의 기본 개념

일반적으로 함수를 표현할 때에는 다음과 같은 모습으로 표현하는 경우가 많다. 함수의 성격과 특성을 가장 잘 나타내는 모습이기 때문일 것이다.

함수의 모식도

함수는 위 그림처럼 입력값을 받아 내부 처리 과정(그림에서는 입력값에 4를 더하는 처리)을 거친 후 그 결과값을 내어 놓는 형태를 기본으로 한다. 입력값을 인자값 혹은 파라미터라고 하고, 내어놓는 결과값을 반환값 혹은 리턴값이라고 한다.

함수의 인자값은 하나도 없을 수도 있고, 하나 이상일 수도 있다. 특별한 경우에는 인자값의 개수가 제한되지 않는 형태를 가지기도 한다.

함수의 반환값은 특정 값을 반환하는 형태와 반환하는 값이 없는 형태 두 가지로 나눌 수 있다. 다만 특정 값을 반환하더라도 그 값의 갯수는 일반적으로 하나이다. 만약 둘 이상의 값을 반환해야 할 필요가 있다면 반환할 값들을 집단 자료형 하나에 담아 반환해야 한다. 즉, 실질적으로 반환하는 값이 여러 개더라도, 반환하는 단위는 하나라는 것이다.

함수는 일반 함수사용자 정의 함수로 나눌 수 있따. 일반 함수는 프로그래밍 언어나 프레임워크 수준에서 제공하는 함수로 기본적인 데이터의 처리나 연산 등을 수행하기 위한 목적으로 사용된다. 대표적으로 출력에 사용하는 함수인 print()를 들 수 있다.

하지만 실제로 애플리케이션을 개발하다 보면 언어나 프레임워크가 제공하는 함수만으로는 충반하지 않은 경우가 많다. 이때에는 우리가 원하는 기능을 실행해 줄 함수를 직접 만들어 사용해야 하는데, 이를 사용자 정의 함수라고 부른다. 이때 말하는 정의란 옳고 그름의 Justice가 아니라 Definition을 의미한다. 이번 장에서 배울 대부분의 내용은 이같은 사용자 정의 함수에 관련된 것들이다.

기본적으로 함수는 의존성 없이 독립적으로 실행 가능한 코드를 모듈 단위로 분리해 놓은 것에 불과하므로, 함수를 사용하지 않고 함수 내부의 실행 코드만 가져다 전체 코드에 넣고 사용해도 된다. 다시 말해 프로그래밍에서 함수가 필수 요소는 아니라는 것이다. 그럼에도 함수가 중요한 의미를 가지는 것은 다음과 같은 이점들 때문이라고 할 수 있다.

  • 동일한 코드가 여러 곳에서 사용될 때 이를 함수화하면 재작성을 할 필요 없이 함수 호출만으로 처리할 수 있다.
  • 전체 프로세스를 하나의 소스 코드에서 연속적으로 작성하는 것보다 기능 단위로 함수화하면 가독성이 좋아지고, 코드와 로직을 이해하기 쉽다.
  • 비즈니스 로직을 변경해야 할 때 함수 내부만 수정하면 되므로 유지보수가 용이하다.

1.1 사용자 정의 함수

사용자 정의 함수를 만드는 방법을 알아보자. 스위프트에서 함수를 정의하는 형식은 다음과 같다.

1
2
3
4
func 함수명(매개변수1: 타입, 매개변수2: 타입, ...) -> 반환타입 {
    실행내용
    return 반환값
}

스위프트에서 함수를 정의할 때 func 키워드를 사용한다. 함수를 선언할 때 키워드를 사용하지 않는 언어들도 많지만 스위프트는 명시적으로 func 키워드를 사용하여 함수를 선언해야 한다. func 키워드 다음에는 함수의 이름을 작성하는데, 이때 [+, -, *, /] 같은 연산자와 예약어는 사용할 수 없다.

함수의 이름에 사용할 수 있는 문자들은 영어나 숫자, 한자, 바이너리 이미지 등으로 다양하지만, 첫 글자는 반드시 영어 또는 언더바(_)로 시작해야 한다. 언더바 이외의 특수문자나 숫자로 시작할 경우 컴파일러에 의해 오류가 발생한다. 대신 두 번째 글자부터는 이런 제약이 없으므로 영어, 숫자, 일부 특수문자를 충분히 활용할 수 있다. 단, 숫자나 특수 문자 등을 너무 남발하면 함수의 핵심인 재사용성과 생산성 측면에서 불편함이 야기될 수 있으므로 주의해야 한다.

1
2
3
func s0110() {
    print("사당역 5번 출구")
}

이 함수는 스위프트에서 함수명에 적용되는 규칙을 정확하게 지키고 있어 아무런 문제가 없다. 하지만 실제로 사용하기에 적절하지는 않다. 여러 개의 숫자로 이루어져 있어 쉽게 헷갈릴 수 있기 때문이다. 무엇보다 함수를 작성한 사람 이외에는 함수의 기능과 함수명을 연관 짓기 어렵다는 것이 치명적인 단점이다. 이 함수 하나만 사용한다면 외워서 사용할 수도 있겠지만, 이같은 함수들이 백 개쯤 된다고 생각해보자. 그것은 악몽이다.

이름에 특수문자가 포함되어 있는 함수도 마찬가지이다. 앞에서 이미지를 사용한 변수명의 불편함에 대해 잠깐 이야기한 적이 있는데, 비슷한 이유로 함수명에 특수문자가 포함되면 충분히 불편하다. 함수를 호출할 때마다 특수문자를 입력하는 복잡한 과정을 거쳐야 하기 때문이다.

숫자도 마찬가지이다. 숫자를 너무 남발하면 함수의 이름을 외우기 쉽지 않다. 과자 포장지 뒤에 있는 바코드 숫자 외우고 있는 사람이 있을까? 아마 없을 것이다. 너무 외우기 어려우니까. 그러므로 함수에서 숫자나 특수기호는 꼭 필요할 때 의미를 구분하는 용도로 적당한 선만큼만 사용하는 것이 좋다.


참고

이름 지을 땐 왠만하면 숫자를 자제하자.

예전에 필자가 어떤 회사의 내부 시스템 리뉴얼을 진행할 때의 이야기이다.(리뉴얼은 ‘개편’이라는 뜻으로, 기존에 있던 시스템을 업그레이드하거나 바꿀 때 사용하는 현장 용어이다.) 리뉴얼을 위한 미팅에서 데이터를 저장하고 있는 데이터베이스의 명세서를 받아보고는 이내 당황해 버렸는데, 데이터베이스에서 수백 개 되는 테이블의 이름이 모조리 의미를 쉽게 짐작하기 어려운 숫자와 코드로 이루어져 있었기 때문이다.

물론 최초 개발 당시에는 테이블에 저장하는 데이터의 성격에 따라 분류하려는 의도였겠지만, 이후 데이터베이스의 내용을 정리한 문서 관리가 제대로 되지 않고, 담당자까지 교체되면서 복잡한 코드로 이루어진 테이블명들은 개발자들에게 마치 다빈치 코드 같은 존재가 되어 버렸다. 실제로 운영을 담당하고 있던 기존 개발자들도 주로 사용하는 몇 개의 테이블명만 표로 정리해서 출력하여 참조하고 있었다. 매번 데이터베이스를 다루어야 할 때마다 테이블을 찾기가 정말 힘들었던 기억이 새록새록하다.

이런 의미에서 회사가 여러분을 해고하지 못하도록 하려면 변수명이나 함수명을 모두 숫자나 코드로 작성하면된다. 후임자가 와서 코드를 보고 나면 바로 도망칠 테니까. 유지보수해야 하는 여러분들에게도 악몽과 같다는 건 함정. 단, 개발이 끝날 때까지는 들키지 말아야 할 것이다. 개발 도중에 들키면 일찍 집에 가는 수가 있다.


함수명을 작성하고 나면 다음으로 해야 할 것은 함수의 인자값 개수와 형태를 정의하기 위해 소괄호로 영역을 표시해 주는 것이다. 이 공간에는 함수가 호출될 때 전달되는 입력값을 대입 받기 위한 변수의 이름과 타입이 정의되는데, 이를 매개변수라고 한다. 영어로는 파라미터(Parameter)라고도 부른다. 오브젝티브-C에서 콜론(;) 다음에 매개변수명이 작성되던 것과 달리 스위프트에서는 괄호 내부에 쉼표(,)로 구분된 매개변수가 차례로 정의된다. 함수의 인자값이 필요 없는 경우라면 매개변수를 생략할 수 있으며, 이때 함수를 정의하는 형식은 다음과 같이 변경된다. 위의 함수 정의 구문과 비교해 보자.

1
2
3
4
func 함수명( ) -> 반환타입 {
    실행내용
    return 반환값
}

매개변수가 없는 함수를 작성할 때는 함수명 뒤의 매개변수 영역을 표시하는 괄호 내부를 비워두면 된다. 일부 언어에서는 매개변수를 사용하지 않는 함수의 경우 매개변수 영역을 비워두는 대신 void라는 키워드를 명시적으로 작성할 것을 강제하기도 하지만, 스위프트에서는 그냥 빈칸으로 두면 된다. 하지만 매개변수가 없더라도 괄호는 생략할 수 없다.

매개변수의 이름과 타입까지 작성이 완료되었으면 이제 이 함수의 반환 타입을 작성해 줄 차례이다. 반환타입이라는 것은 함수가 실행된 결과로 어떤 값을 내놓을 것이냐 하는 것이다. 함수의 기본은 인자값을 입력받아 내부적으로 처리하고, 그 결과를 외부로 다시 반환하는 과정에 있다. 따라서 반환값이라는 요소는 함수 내부에서 생성된 값을 외부로 전달하는 역할을 한다. 이를 함수가 값을 반환한다고 표현한다. 실무에서는 함수가 값을 리턴한다라는 표현을 더 많이 사용하기도 한다.

함수의 반환 타입을 표시할 때에는 -> 기호와 함께 사용한다. 이 기호 다음에 작성된 자료형이 함수가 반환하는 값의 타입인 것이다. 함수의 반환 타입으로 사용될 수 있는 자료형에는 제약이 없다. String이나 Int, Double, Bool 등 기본 자료형은 물론이거니와 AnyObject, UITableCell 등과 같은 클래스 객체도 사용할 수 있으며, 사용자가 정의한 커스텀 클래스도 가능하다. 구조체 역시 사용할 수 있다. 하지만 반환 타입이 지정되면 반드시 그 타입에 맞는 값을 반환해야 한다. 반환 타입을 문자열로 정의했는데 실수를 반환해서는 안 된다. 또한 nil을 반환하려면 함수의 반환타입이 반스듸 옵셔널 타입으로 정의되어 있어야 한다.

함수의 성격에 따라서는 반환값이 전혀 없는 함수를 작성할 수도 있다. 이런 경우를 “아무 값도 반환하지 않는다.” 또는 “void 타입을 반환한다.”고 표현한다. 반환 타입을 생략할 수 없도록 설계된 언어에서는 반환 타입을 void로 작성하도록 강제되기도 하지만, 스위프트에서는 다음과 같이 반환 타입을 생략함으로써 반환값이 없음을 표현할 수 있다.

1
2
3
4
func 함수명(매개변수1: 타입, 매개변수2: 타입, ...) {
    실행내용
    return 반환값
}


이전 내용 보기 iOS 면접 질문 목록 보기 다음 내용 보기

Leave a comment