이번에는 Closure에 대해서 확인을 해보도록 하겠다.
Closure
- 참조 타입이고, 코드에서 전달 및 사용할 수 있는 독립 기능 블록이며, 일급 객체의 역할을 할 수 있음.
- 일급 객체 : 전달인자로 보낼 수 있고, 변수/상수 등으로 저장허거나 전달할 수 있으며, 함수의 반환값이 될 수도 있다.
- 클로저는 이름 없는 함수, 익명 함수를 지칭한다. ( named closure, unnamed closure )
- 클로저는 2가지를 포함하지만 보통 unnamed closure를 말한다.
클로저에 대한 간략한 정의에 대해서 확인해봤다.
클로저의 사용 방법에 대해서 확인해보도록 하자.
{ 매개변수 -> 리턴 타입 in 실행구문 } |
클로저는 익명 함수라서 func 키워드를 사용하지 않고, 클로저는 헤드와 바디로 이루어져있다.
매개변수 -> 리턴 티입이 클로저 헤드이며, 실행구문을 클로저 바디라고 말한다.
클로저 헤드와 바디를 구분지어 주는게 in 키워드 이다.
그럼 이제 매개변수와 리턴타입이 없는 Closure 부터 확인을 해보도록 하자.
클로저는 익명이긴 하지만 함수이다. Swift에서 Closure는 일급 객체이기 때문에 상수나 변수에 클로저를 대입할 수 있다.
따라서 필자는 매개변수와 리턴 타입이 없는 클로저를 만들어 변수 welcome에 대입시켰다.
정의한 클로저를 호출하려면 함수를 호출하는 것과 동일하게 사용해주면 된다.
따라서 Closure의 실행구문의 print 내용이 출력된 것을 확인할 수 있다.
좌측의 이미지는 매개변수와 리턴타입이 있는 클로저를 생성하였다. 매개변수와 리턴 타입이 있는 Closure는 호출을 할 때에 함수처럼 전달인자 레이블을 작성해주면 안된다.
일반적인 함수를 호출하듯이 레이블명을 작성할 경우에는 에러가 발생한다. 이렇기 때문에 클로저를 호출할 때에는 전달인자 레이블을 사용하지 않는다. Extraneous argument label 'name:' in call 에러가 발생한다.
이렇게 전달인자 레이블을 작성하지 않고, 바로 내용을 작성해주면 된다.
또한 클로저는 함수의 파라미터 타입으로 클로저를 전달할 수 있다. 이유는 클로저가 위에서 언급했다 싶이 일급 객체라서 가능하다.
함수 wlecomClosure를 만들었고, 매개변수와 리턴타입이 없는 클로저를 파라미터 타입으로 전달하고 있다.
함수의 호출 역시 closure를 작성하며, closure 부터 }) 까지가 클로저로 작성한 내용이다.
따라서 welcomClouser 함수가 호출이 되면서 함수 실행구문에 있는 클로저 함수가 호출이 되니 클로저 안의 print가 호출이 되어 Welcom to Closure가 표기가 되는 부분이다.
함수의 반환 타입으로 클로저를 사용할 수 있다. 기존의 함수와 동일하지만 반환 타입 부분에 클로저를 반환하도록 만들어 주면 된다.
welcomeClosure2의 함수에 매개변수가 없고 클로저를 반환하도록 만들었다.
헷갈릴수도 있겠지만 첫번째 소괄호가 매개변수이며, ()->() 이부분이 클로저를 반환한다는 내용이다.
추가적으로 welcomeClosure2() 를 사용할 경우에는 오류가 나지는 않지만 클로저의 내용이 나오지 않는다.
즉, 클로저 호출이 아닌 그냥 일반 함수의 반환값을 반환하는것 같다.
이거까지는 필자도 아직 Swift의 고급 개발자가 아니기 때문에 정확히는 모르겠다..
왜 그런지 아시는 분이 있으면 설명을 댓글에 부탁드리겠습니다.
이렇게 클로저는 일급 객체 함수의 특성을 다 가지고 있기 때문에 변수나 상수에 개입할 수 있고, 함수 파라미터로 전달을 받을 수 있고, 리턴 타입으로도 사용할 수 있다.
이제 더 헷갈리게 진행을 해보자...
클로저를 간단하게 표현할 수 있다. 클로저가 조금 길어지거나 가독성이 떨어진다면 후행 클로저 기능을 사용하면 된다.
후행클로저는 맨 마지막으로 매개변수로 전달될 때에만 해당이 됨으로 매개변수로 클로저 여러개를 전달할 때에는 맨 마지막 클로저만 후행 클로저를 사용할 수 있다.
좌측의 이미지 같은 경우에는 일반적으로 closure를 사용하는 방법이다. 후행 클로저를 사용하지 않은 방법이다.
우측의 이미지 같은 경우에는 후행클로저를 사용한 방법이다. welcom2가 실행된 클로저 호출의 내용을 확인해보면 바로 클러저의 내용을 작성할 수 있다는 것을 알 수 있다. 함수를 만들때에 애초에 매개변수와 리턴타입이 없는 클로저를 사용했다고 함수를 만들었기 때문에 생략이 가능하다. 추가적으로 in 키워드까지도 생략이 가능하며, 위와 같은 경우에는 () 소괄호까지도 생략이 가능하다.
매개변수에 클로저가 여러개가 있는 경우에는 다중 후행 클로저 문법을 사용할 수 있다.
함수의 매개변수로 hi와 bye 2개의 클로저를 선언했다.
이후에 이 함수를 사용할때에 함수의 이름을 입력하다가 서제스쳔창에서 엔터를 클릭하면 이렇게 자동완성 기능을 통하여 위 이미지처럼 표기가 된다.
다중 후행 클로저를 사용하는 경우에는 중괄호를 열고 닫음으로써 클로저를 표현해주며, 코드와 같이 첫 번째 크로저인 경우에는 알아서 스위프트에서 매개변수 레이블을 생략해줌으로 인하여 편하게 사용할 수 있다.
간소화에 대해서 어느정도 진행을 많이 했다.
좀더 간소화에 대해서 제대로 알아보고 위해서 샘플로 클로저 함수를 생성하였다.
좌측의 이미지는 매개변수로 closure를 받고 잇으며, closure의 매개변수로 Int 2개를 받고 인트 타입을 return 시키는 클로저 함수이다.
그리고 함수의 코드 블럭에는 매개변수로 받은 closure를 실행하는 내용을 작성하였고, 2와 4를 넘겨주고 있다.
우측의 이미지를 확인했을 때에는 간소화를 1도 진행하지 않은 원래의 Closure 사용에 대한 내용을 작성하였다.
이렇게 길고 어렵게 작성했던 내용을 다양하게 간소화를 진행할 수 있다.
간소화 없이 코드를 작성했을 경우에는 직관적으로는 보기 쉬워보이지만, 클로저의 내용이 길어질 경우에는 가독성이 어려워진다.
특히 개발자들끼리 가장 싫어하는 자기 자신만 볼 줄 아는 코드. 이런 개념으로 보일 수도 있다.
하나씩 내용 확인을 진행해보자.
순번 | 내용 |
number 1 | 1차 경량화를 통해서 넘겨받는 인자를 함축적으로 a,b 로 표현을 하였다. multipleClosure 함수를 선언할 때에 애초에 Int로 지정된 데이터 타입을 생략을 할 수 있는 부분이다. |
number 2 | 약식 인수를 이용하여 매개변수의 이름도 생략할 수 있다. 약식 인수 : 매개변수 이름을 대신한다는 것을 의미한다. 배열과 같은 인덱스 순서의 개념으로 0부터 시작하고, $를 앞에 붙이면 순서대로 인식한다. 매개 변수 이름 생략시 약식 인수 이름으로 대체를 하면 매개변수와 in 키워드를 같이 삭제 할 수 있다. |
number 3 | 단일 리턴문만 남을 경우에는 return 키워드도 생략이 가능하다. 하지만 단일 리턴문이 아닐 경우에는 이렇게 에러가 발생한다. 에러의 내용은 return 키워드가 빠졌다는 내용임으로 단일 return 문이 아닐 경우에는 return 키워드를 작성해줘야한다는 것을 알 수 있다. |
number 4 | 위에서 진행했다 싶이 후행으로 진행한 내용으로 이해하면 된다. |
number 5 | 후행으로 진행한 내용에서 소괄호 또한 삭제를 할 수 있다. |
이렇게 클로저의 간소화에 대해서 내용 확인을 진행해봤다. 간단한 내용이지만 길었던 클로저에 대한 표현이 이렇게 간소화를 진행하면 상당히 짧아지는 것을 확인할 수 있다.
이렇게 클로저 간소화를 사용한다면 내용이 복잡한 클로저라도 다른 개발자들과 협업하여 개발을 진행할 경우에는 가독성이 높은 코드를 작성할 수 있다.
클로저에는 이스케이프 클로저의 개념도 있고, 클래스 인스턴스에 프로퍼티를 할당 한다면 클로저와 인스턴스 사이에 강한 순환 참조가 생겨 메모리 릭이 발생하는 내용도 있지만 우선은 이정도의 개념만 알고가도 충분할 것 같다.
이후에 추가적으로 진행할 예정이며, 이것을 진행한 필자도 오늘 상당히 많이 헷갈린다...
'APPLE > Swift 문법' 카테고리의 다른 글
[ 기초 문법 ] 고차함수 ( map, filter, reduce ) (0) | 2022.08.25 |
---|---|
[ 기초 문법 ] try-catch (0) | 2022.08.24 |
[ 기초 문법 ] 옵셔널 체이닝 (0) | 2022.08.23 |
[ 기초 문법 ] 열거형 (0) | 2022.08.22 |
[ 기초 문법 ] Extension (0) | 2022.08.22 |