Kotlin inline, reified 알아보기

JCChoo
4 min readApr 21, 2020

--

안녕하세요! 오늘은 inline 함수와 reified를 알아보려고 해요!

왜냐면… 어떤 분의 코드를 클론해 분석하던 중 inline 함수를 사용해 깔끔하게 구현된 몇몇 코드를 보면서 저건 뭘까… 하면서 공부를 해봤어요!

공부했으면 쓰면서 다시 리뷰해봐야겠쥬?

깔끔하게 보실분은 여기를 참고하세요!
(노션이 미디움보다 나은… 거 같…아요…)

inline

우선 문서에서 본 설명은 아래와 같습니다!

고차 함수를 사용하면 런타임 패널티가 부과된다. 각 function은 객체이며, closure, 즉, function의 body에 엑세스된 변수를 캡처한다. 메모리 할당과 런타임 오베헤드를 초래한다. 그러나 많은 경우에 오버헤드의 이런 종류는 람다 표현에 inlining함으로써 제거할 수 있다.

??? 뭔말인지 모르겠어요 저는… 그래서 예제를 살펴보면서 이해했답니다!

바로 예제부터 보시죵

코틀린은 compile 단계에서 함수 타입의 변수, 즉 람다를 FunctionN 인터페이스를 구현한 “Object”로 저장한다. 코틀린 표준 라이브러리는 매개 변수에 따라 Function0<R>, Function1<P1, R>, Function2<P1, P2, R>… 인터페이스를 제공하고 각 매개변수 개수에 맞는 invoke() 메서드가 하나씩 선언되어 있다. 컴파일러는 FunctionN 인터페이스의 invoke() 메서드 내에 람다 식을 구현하고 해당 객체를 파라미터로 사용하는 것이다.

즉, testCalculator()에서 매개 변수로 전달한 “{a: Int, b: Int → a+b}” 람다 식은 매개변수가 두 개이므로, Function2<Int, Int, Int> 인터페이스를 구현한 임의의 객체로 생성되어 calculator()의 body 매개변수에 전달된다.

위의 코드를 설명으로 써본거에요! 이해 가시나요?

만약! 해당 코드를 아래처럼 쓴다면, 어떻게 될까요?

위의 코드처럼 calculator() 함수를 각각 다른 람다 식을 사용해 여러 번 실행할 경우 람다 식마다 각각의 “객체”가 생성되어 메모리에 저장되고 해당 객체의 invoke() 함수가 각각 호출되기 때문에, 메모리 할당과 가상 호출에 의한 런타임 오버헤드가 발생하게 된다!!!! 헐…?

걱정마세용! 코틀린에서는 람다를 매개 변수로 사용하는 고차 함수를 “인라인 함수(Inline function)”으로 정의하여 오버 헤드를 줄일 수 있는 방법을 제공하고 있답니다!?

인라인 함수로 정의된 함수는 컴파일 단계에서 호출하는 방식이 아니라 코드 자체가 복사되는 방식으로 컴파일이 된다고 해요!! 오예~~~

위 코드가 컴파일이 된다면, sum()함수에 “바이트 코드”가 메모리에 할당되고, main()의 내용은 sum()함수의 바이크 코드가 저장된 “주소를 호출”하는 바이트 코드를 포함할 것이다.

그런데, 그뤈뒈~~~ 여기서 “inline” 키워드를 붙여 인라인 함수로 선언한다면? 컴파일러는 main() 함수에서 sum() 함수를 호출하는 모든 부분을 sum() 함수의 본문인 “a+b”로 복붙!!! 해버린다.

즉, 실행 단계에서는 아래와 같은 코드 형태가 된다!

보셨나요? 이렇게 되면 직접 호출하는 방식보다 메모리 할당 면에서 좋아좋아집니다!

왜 붙이는지 이해 가셨죵? 그럼 디컴파일해서 어떻게 변한건지 직접 보실까요?

보시면 아시겠지만, Function2 객체를 만들어 호출하지 않아요! 즉, 본문 자체가 복사되어, calculator 호출도 Function2 객체 생성도 없이 실행되는 것을 볼 수 있어요!!

즉, 정리하자면!!!

function 앞에 inline 키워드를 붙여 사용

inline function은 컴파일 단계에서 “호출”방식이 아닌 “코드 복사” 방식으로 변환

람다 전달 시 발생하는 메모리, 호출 등의 오버헤드 감소 목적

특정 람다를 인라인 방식에서 제외하고 싶을 때는 noinline 키워드 사용

이렇답니다~!! 이해가셨죵?

reified는 간단히….만 알아보죵

reified

타입 파라미터에 reified를 정의하면 마치 클래스처럼 타입 파라미터에 접근해 사용할 수 있어요! 즉, type 정보를 남길 수 있죠!!!

이렇게요!

이해가셨죵? 근데!!! reified는 inline 함수와 세트여서!! 다른 함수에선 못써요!! 쓸때 주의해서 쓰세요! 20000~

--

--

JCChoo

“기본부터”라는 말을 좋아하지만 정작 기본이 없는… 기본을 쌓아나가려고 합니다. 안드로이드 개발자로 성장하기 위해 열심히 책상앞에 앉아 두들겨보겠습니다.