Skip to content

Conversation

@ericKwon95
Copy link
Collaborator

issue #4

04. Closure

Swift에서 클로저(Closure)란 무엇이며, 어떻게 사용하나요?

  • Swift에서 클로저는 이름 없는 함수입니다.
  • 클로저는 1급 객체이기 때문에 변수, 함수의 인자, 함수의 반환값으로 사용할 수 있습니다.

클로저의 캡처(Capture) 기능은 무엇인가요?

  • 클로저는 클로저가 호출된 컨텍스트와 다른 생명주기를 가질 수 있습니다.
  • 따라서 클로저 내부에서 외부 컨텍스트의 변수를 참조하게 되면, 클로저보다 외부 컨텍스트가 더 빨리 사라질 가능성이 있습니다.
  • 이러한 가능성 때문에 클로저는 외부 컨텍스트의 변수와 상수를 캡처해 외부 컨텍스트가 사라져도 캡처한 값을 참조 및 변경 가능하도록 설계되어 있습니다.

@escaping 클로저와 non-escaping 클로저의 차이점은 무엇인가요?

  • 클로저가 함수의 매개변수로 전달되었지만, 함수 반환 이후에 호출되는 경우 클로저가 탈출(escaping)한다고 할 수 있습니다.
  • 이 때 매개변수에 @escaping을 작성해 해당 클로저는 탈출이 허용됨을 나타낼 수 있습니다.
  • 만약 탈출 클로저 내부에서 클래스 인스턴스 self를 참조하게 된다면, 두 참조 타입이 서로를 참조하는 순환 참조가 발생하게 됩니다.
  • 이를 방지하기 위해 캡처 리스트에서 weak 또는 unowned 키워드를 사용해 레퍼런스 카운트를 증가시키지 않도록 방지해야 합니다.
  • 클로저의 생명주기가 self보다 긴 경우를 대비하기 위해 weak 키워드를 사용해주는 것이 좋습니다.

트레일링 클로저(Trailing Closure) 문법은 어떤 경우에 유용한가요?

  • 트레일링 클로저 문법은 콜백 함수를 작성할 때 유용합니다.
  • 함수의 매개변수로 함수를 전달 및 호출하는 것이 콜백 함수인데요, 트레일링 클로저 문법을 활용하면 콜백 함수를 손쉽게 작성할 수 있습니다.

@ericKwon95 ericKwon95 self-assigned this Dec 27, 2024
@ericKwon95 ericKwon95 changed the title Create 04-Closure [Level1] 04-Closure Dec 27, 2024
@ericKwon95 ericKwon95 changed the title [Level1] 04-Closure [Level1] 04 - Closure Dec 27, 2024
@ericKwon95 ericKwon95 changed the title [Level1] 04 - Closure [LEVEL 1] 04 - Closure Dec 27, 2024
@mint3382 mint3382 linked an issue Dec 27, 2024 that may be closed by this pull request
4 tasks
@@ -0,0 +1,20 @@
## 04. Closure
### Swift에서 클로저(Closure)란 무엇이며, 어떻게 사용하나요?
- Swift에서 클로저는 이름 없는 함수입니다.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클로저 공식 문서에 보면 다른 프로그래밍 언어의 익명 함수와 닮았다고 되어 있지만 그 밑의 설명을 보면 함수를 closures that have a name 라고 표현합니다. 때문에 클로저가 함수를 포함하는 형식이 되기에 클로저는 그룹 코드인데 표현 중에 이름 있는 클로저는 함수라고 부르고 이름 없는 클로저는 이를 제외한 것이라고 보는 것은 어떨까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그 시각이 좀 더 타당하다고 생각되네요! 반영하여 수정하도록 하겠습니다~!

Comment on lines 11 to 16
### @escaping 클로저와 non-escaping 클로저의 차이점은 무엇인가요?
- 클로저가 함수의 매개변수로 전달되었지만, 함수 반환 이후에 호출되는 경우 클로저가 탈출(escaping)한다고 할 수 있습니다.
- 이 때 매개변수에 @escaping을 작성해 해당 클로저는 탈출이 허용됨을 나타낼 수 있습니다.
- 만약 탈출 클로저 내부에서 클래스 인스턴스 self를 참조하게 된다면, 두 참조 타입이 서로를 참조하는 순환 참조가 발생하게 됩니다.
- 이를 방지하기 위해 캡처 리스트에서 weak 또는 unowned 키워드를 사용해 레퍼런스 카운트를 증가시키지 않도록 방지해야 합니다.
- 클로저의 생명주기가 self보다 긴 경우를 대비하기 위해 weak 키워드를 사용해주는 것이 좋습니다.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구조체와 열거형에서도 escaping closure를 사용할 수 있나요?

Copy link
Collaborator Author

@ericKwon95 ericKwon95 Dec 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구조체의 경우 아래와 같이 사용할 수 있음을 확인했습니다!

struct Foo {
    let bar: () -> Void
    
    init(bar: @escaping () -> Void) {
        self.bar = bar
    }
}

let foo = Foo(bar: {
    print("Hello World!")
})
foo.bar()

열거형의 경우 연관값으로 클로저를 전달할 경우 escaping 함수로 동작한다는 을 확인했습니다~!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mutating 키워드가 붙은 함수에서도 escaping closure를 사용할 수 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드로 테스트해 봤을 때에는 함수에서 인자로 escaping 클로저를 받는 경우, 함수 내부에서 구조체 프로퍼티로 선언된 클로저를 사용하는 경우 둘 다 사용 가능했습니다~!
혹시 제가 놓치고 있는게 뭘까요?!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 그렇다면 해당 클로저 내부에서 self 키워드 사용해보셨나요?!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헉 탈출 클로저 내부에서 값 타입 self에 접근하는 케이스를 놓치고 있었네요~!
바보같이 클로저 사용 가능 여부만 체크하고 있었습니다 ㅠㅠ
알려주셔서 감사합니다~!
값 타입은 immutable 하기 때문에, 기본적으로 escaping 클로저 내부에서 self 값에 대한 변경이 불가능하겠군요.
self를 변경 가능하도록 mutating 키워드를 붙여도 나중에 실행될 수 있는 escaping 클로저 특성상 메모리 접근 충돌 문제가 발생 가능합니다.
이를 방지하기 위해 컴파일 에러가 발생하고, 이를 해결하기 위해서는 캡처 리스트를 사용해 값의 복사본을 사용해야 한다는 것 까지 알게 되었습니다~!
값 타입을 self로 캡처할 때 고려해야 할 부분들이 여럿 있군요... 감사합니다 민송님!
내용 확인하신 후 반영하도록 하겠습니다~!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 맞습니다! 관련된 이야기를 하고 싶었습니다 ㅋㅋㅋ

@ericKwon95
Copy link
Collaborator Author

@mint3382
main 뿐만 아니라 현재 PR 브랜치에도 프로텍션이 걸려 있어서 추가 커밋 시 새로 PR을 만들어야 하는 상황이어서 공유드립니다!
혹시 의도하신 부분이었다면 죄송합니닷

@mint3382
Copy link
Member

@mint3382 main 뿐만 아니라 현재 PR 브랜치에도 프로텍션이 걸려 있어서 추가 커밋 시 새로 PR을 만들어야 하는 상황이어서 공유드립니다! 혹시 의도하신 부분이었다면 죄송합니닷

아 세상에 제가 찾아보고 수정해놓겠습니다...

@mint3382 mint3382 self-requested a review January 1, 2025 09:11
Comment on lines 11 to 16
### @escaping 클로저와 non-escaping 클로저의 차이점은 무엇인가요?
- 클로저가 함수의 매개변수로 전달되었지만, 함수 반환 이후에 호출되는 경우 클로저가 탈출(escaping)한다고 할 수 있습니다.
- 이 때 매개변수에 @escaping을 작성해 해당 클로저는 탈출이 허용됨을 나타낼 수 있습니다.
- 만약 탈출 클로저 내부에서 클래스 인스턴스 self를 참조하게 된다면, 두 참조 타입이 서로를 참조하는 순환 참조가 발생하게 됩니다.
- 이를 방지하기 위해 캡처 리스트에서 weak 또는 unowned 키워드를 사용해 레퍼런스 카운트를 증가시키지 않도록 방지해야 합니다.
- 클로저의 생명주기가 self보다 긴 경우를 대비하기 위해 weak 키워드를 사용해주는 것이 좋습니다.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 맞습니다! 관련된 이야기를 하고 싶었습니다 ㅋㅋㅋ

Copy link
Collaborator

@NeoSelf1 NeoSelf1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오,,, self의 타입 간 escaping 클로저가 동작하는 매커니즘에 대해 얕게나마 이해한것같습니다... 최고입니다 다들

@mint3382 mint3382 self-requested a review January 6, 2025 01:31
@ericKwon95 ericKwon95 merged commit 6dd643c into main Jan 6, 2025
@ericKwon95 ericKwon95 deleted the 04-Closure branch January 6, 2025 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[LEVEL 1] 04. Closure

4 participants