기어가더라도 제대로

[8일차] 클로저 본문

Swift - 기초

[8일차] 클로저

Damagucci-juice 2022. 9. 28. 19:08

처음엔 너무 어려웠던 클로저입니다. 누구나 클로저를 처음 배울 땐 생소하게 생겨서 어려움을 느낍니다. 저도 그렇고요. 

근데 클로저를 한번 배워 놓으면 다음에 마주할 때 훨씬 쉽게 느껴질 것입니다. 

클로저의 주요한 특징은 익명함수라는 것, 그리고 함수를 그 자체로 변수화 수 있도록 해준다는 것입니다. 

잘 이해가 안되지만 천천히 보도록하시죠. 

  • 함수를 변수에 할당하고
  • 함수에 함수를 파라메터로 넘기고
  • 반환값도 함수를 받을 수 있습니다. 

만약에 함수를 변수에 저장하고 싶으면 () 를 호출해선 안됩니다. 

()를 쓰는 순간 함수를 호출하게 되어서 그 함수의 리턴값을 변수에 저장합니다. 함수 그자체가 아니라요. 

func greetUser() {
    print("Hi there!")
}

greetUser()

var greetCopy = greetUser
greetCopy()

이런식으로 함수를 변수에 저장할 수 있습니다. 근데, 단순히 변수에 저장만 하기 위해서 함수를 선언하는것은 비효율적으로 보입니다. 여기서 클로저가 등장합니다. 

let sayHello = {
    print("Hi there!")
}

sayHello()

이런식으로 익명의 함수를 만들어서 변수에 저장할 수 있습니다. 참 쉽죠? 거창한 이름을 쓰긴 했지만 내용은 코드의 블럭을 청크해서 그 변수를 어디서나 사용하는 것입니다. 

또 클로저에 우리는 parameter 를 담고 싶어지지 않습니까? 개발자라면 무릇 그래야겠지요. (껄껄) 그 방식은 다음과 같습니다. 

let sayHello = { (name: String) -> String in
    "Hi \(name)!"
}

근데 보면 중괄호 안에 뭔가 복잡하게 자리한거 같은데 지금은 좀 그래보일 수 있지만 나중엔 그렇지 않을 겁니다. 

소괄호 안에 name 파라메터를 받아서 in 으로 넘기는데 in 이라는 키워드가 새롭죠? 

in 키워드는 파라메터와 클로저의 리턴 타입 바로 뒤에 옵니다. 일반적인 함수를 생각해보면 함수를 선언하고 파라메터와 리턴 타입을 { } 바깥에 지정해주는 것을 볼 수 있습니다. 근데 클로저는 그게 안되요. 

func someFunction(value: Int) -> Int {
	value * 5
}

let someClosure = { (value: Int) -> Int in 
	value * 5
}

클로저의 경우는  { } 안에서 모든걸 해결해줘야하는 아이라서 in 이라는 키워드가 나온것입니다. 
즉 다시말해서 "여기서 파라미터와 반환 타입을 다 말했음! 끝 !" 이라고 밝혀주는 것이 in 키워드인것이지요.

in 다음 부터는 클로저의 body 에요

그러나 저러나 이게 왜 필요한데? 라고 질문 하실 수 있을 거같네요. 너무 생소하고 처음 배울 때 어려운 이것을 왜 배워야할까요? 

swift 와 swiftUI 에서 많이 사용이 되고 있기 때문이에요. 위에처럼 사용되는 경우는 드물지만, 선언형 프로그래밍인 SwiftUI 를 사용하다보면 그냥 호출만 하고 띡인 경우가 많아요. 

또한 함수 그 자체를 타입으로 넘긴다는 말을 이해하려면 클로저를 이해해야해요.

var greetCopy: () -> Void = greetUser
  1. 빈 괄호를 열고 닫는 것은 파라미터를 안받는 다는 말이에요.
  2. 화살표는 리턴 타입이 곧 나온다는 뜻이에요
  3. Void 타입은 리턴 타입이 없다는 Nothing 의 의미죠. Void 대신 () 이 써있는 경우도 있는데 혼란을 줄 수 있어서 쓰지 말도록해요.

그리고 클로저는 주로 어느 때 쓰이냐하면,

  • 지금 당장 선언은 해놓지만 언제 실행될지는 모르는 코드 뭉치를 사용해야해요
  • 네트워크 작업이 끝나면 실행할 코드에요
  • 지연 시간 이후에 실행할 코드에요.
  • 특정 옵션이 선택되면 실행할 코드에요

등등 지금 당장은 실행하지 않지만 언젠가는 실행될 코드를 쓸 때 아주 유용합니다. 좀 공부를 하다보면 completionHandler 라는 파라메터 이름을 보게 될텐데 이게 그 클로저를 이용한 거라고 이해를 해주시면 좋을거같아요. 몰라도 됩니다. 이해가 안되는게 당연한겁니다. 

Comments