개요

함수형 프로그래밍에서 자주 사용되는 클로저의 개념을 알아보고 Golang 예제를 통해서 클로저가 어떻게 동작하는지에 대해서 자세히 알아봅니다.

클로저란

클로저란 특정 함수와 그 함수가 선언될 때 접근할 수 있었던 주변의 상태(lexical environment)를 함께 캡처하여, 해당 함수가 나중에 실행될 때도 그 상태에 접근할 수 있게 하는 기능을 말합니다.

조금 더 쉽게 풀이하자면 클로저는 함수가 정의될 때의 환경(변수, 상수 등)을 ‘기억’합니다. 함수가 해당 환경 밖에서 호출되어도, 함수 정의 시점의 환경에 있는 변수들에 접근할 수 있음을 의미합니다

“클로저란 외부 함수 변수에 접근 할 수 있는 내부 함수”

Untitled

  • A라는 외부 함수는 a라는 int 형의 변수를 가지고 있습니다.
  • A라는 외부 함수는 외부 함수의 변수인 a의 값을 +1 하는 익명 함수를 반환합니다 (클로저 함수)
  • 외부에서 A 함수를 선언하면 A 함수는 익명 함수 (클로저)를 반환합니다.
  • 클로저는 A 함수 초기화 당시의 변수나 상수들의 값을 캡처하고 참조할 수 있습니다.

클로저를 사용하는 이유

데이터 은닉 및 캡슐화

클로저를 사용하면 함수 내부에 변수를 숨길 수 있습니다. 이는 변수를 직접적으로 접근하거나 변경하는 것을 방지하여, 데이터를 보호하고 오용을 줄일 수 있습니다. 객체 지향 프로그래밍에서의 캡슐화와 비슷한 개념으로, 클로저는 모듈식 코드를 작성하는 데 도움을 줍니다.

상태유지

특정 함수가 호출될 때 컨텍스트 내에서 상태 값을 유지해야 하는 경우들이 있는데 이때 클로저를 이용해서 구현할 수 있습니다. 이러면 전역변수를 사용해서 상태를 유지하는 것 보다 안전하게 코드를 작성할 수 있습니다.

모듈화

클로저를 사용하면 코드를 작은, 재사용 가능한 부분으로 나눌 수 있습니다. 이를 통해서 코드들을 적절한 단위로 모듈화하고 이는 코드의 재사용성을 높이고 유지 보수하기 쉬운 코드를 작성할 수 있도록 돕습니다.

Golang에서 클로저

Golang 에서도 익명함수를 지원하고 있고 그렇기에 클로저를 구현할 수 있습니다.

 1package main
 2
 3import "fmt"
 4
 5func adder() func(int) int {
 6    sum := 0
 7    return func(x int) int {
 8        sum += x
 9        return sum
10    }
11}
12
13func main() {
14    add := adder()
15    fmt.Println(add(1))  // 1
16    fmt.Println(add(20)) // 21
17    fmt.Println(add(300))// 321
18}

위 예제에서 adder 함수는 클로저를 반환합니다. 이 클로저는 sum 변수를 “기억하고”, 호출될 때마다 새로운 값을 sum에 더합니다. 이처럼 클로저는 함수가 종료된 후에도 변수의 상태를 유지할 수 있게 합니다.

정리

클로저 함수가 무엇이고 어떤 장점이 있는지를 설명하고 Golang 예시를 통해서 어떻게 동작하는지를 알아보았습니다.

클로저를 통해서 개발자는 상태를 은닉하고, 데이터를 캡슐화하며, 모듈식 코드를 작성할 수 있습니다. 클로저는 단순히 기술적인 요소를 넘어서, 보다 나은 소프트웨어 설계를 위한 사고방식의 전환점을 제시하는 도구 중에 하나로 현대 프로그래밍, 특히 함수형 프로그래밍에서 빼놓을 수 없는 역할을 하고 있습니다.