숨숨 베이스

지식이 숨어있는 공간

람다식 캡쳐링

Last updated on November 30, 2025

1. 정의

람다식 내부에서 파라미터 인수가 아닌, 외부의 변수를 참조하여 활용하는 것을 람다식 캡처링 이라고 한다.

2. 유형

람다식 캡쳐링은 어떤 종류의 외부 변수를 가져와서 쓰느냐에 따라서 그 활용 방법이 달라진다.
분류
매서드 내 지역 변수
클래스 혹은 객체의 필드값 (static, 인스턴스 변수)
제약 조건
해당 변수가 final 이거나 effectivley final 이어야 함.
없음
캡처 방식
지역 변수의 값 자체를 복사
필드의 참조값을 복사 (즉 해당 필드를 가진 클래스나 객체의 주소)
수정 여부
가져온 변수의 내용을 수정할 수 없다. 오직 조회만 가능하다.
수정할 수 있음
즉 매서드 내 지역변수는 딱 한 번 할당이 일어난 것이어야 하고, 람다식에 쓰더라도 조회만 가능할 뿐 값 수정은 불가능하다. 하지만, 해당 람다식을 쓰는 클래스 혹은 객체의 static 혹은 인스턴스 변수는 final이 아니더라도 가져올 수 있으며, 값 수정도 제한 없이 가능하다는 것이다.

3. 이유

람다식과 생명주기를 함께 하는가 여부에 따라 위의 특성이 갈린다.
람다식은 함수형 인터페이스의 '객체' 로서 heap에 저장되며 객체 생성 시부터 GC 수거시 까지 생존한다.

A. 매서드 내 지역 변수를 조회만 가능한 이유

매서드 내 지역변수는 stack에 저장되며 함수 호출 시부터 종료시까지만 생존한다. 따라서 람다식과 생명 주기가 다르기에, 람다식은 아직 살아서 작업을 진행 중이지만, 매서드는 먼저 종료되어 반환된 경우가 있을 수 있다.
이떄 만약 매서드 내 지역 변수를 람다식 내부에서 수정하도록 허용한다면, 사라진 메모리 내용을 수정하려 시도하는 문제가 발생할 수 있다. (이를 dangling reference 문제 - 이미 사라진 객체르 가리키는 문제라고 한다.)

B. 매서드 내 지역 변수는 final이어야 하는 이유

매서드 내 지역 변수가 final이 아니라면, 람다식에 들어가서 활용되고 있는 와중에도 다른 스레드에서 동일 함수 호출하여 내용물을 계속 바꿀 수 있다. 이는 심각한 동시성 문제를 초래하기에 사전에 final로 이를 방지했다.

C. 클래스 혹은 객체의 필드값은 위의 모든 제약 조건이 없는 이유

람다식은 일회성 익명함수로 그것의 역할을 다하면 GC에 의해 수거된다. 따라서 람다식의 생애주기는 그것을 호출한 객체보다 늦게 태어나서 빨리 죽게 된다. 즉 람다식이 살아있는 동안 필드 값은 무조건 존재한다. 그러므로 dangling reference 문제가 생기지 않는다. 또한 동시성 문제는 객체 단위일 때 제어가 훨씬 쉽고, 제어할 수 있는 방안이 많이 마련되어 있다. 따라서 굳이 final일 필요도 없다.

부록

A. 모르는 것 정리

  • effectively final
    : final 키워드가 명시적으로 붙어있진 않지만, 딱 한 번 할당되고 전체 코드에서 한 번도 재할당이 이루어지지 않은 변수를 말하는 키워드이다. 컴파일러가 이를 인식한다.

➡️ 다음 글