요즘 코틀린을 배우는 중인데 과제를 하던 중 교수님이 적어두신
//implement here...
에 class를 선언하니까 참조를 못한다고 떴습니다. 물론 class가 사용처보다 아래에 작성되긴 했지만 저는 교수님이 적으라고 한 곳에 적은 죄 밖에 없었기에 억울했습니다...
게다가 코틀린은 자바와 같은 컴파일 언어인데 선언 순서에 영향을 받을 거라고 생각치도 못했습니다.
저 같은 오개념을 가진 사람도 있을 것이라 생각해 이번 블로그 주제를 선정하게 되었습니다.
코틀린은 자바와 마찬가지로 JVM(Java Virtual Machine)을 타겟으로 하는 컴파일 언어입니다. 그러나 코틀린은 사용하고자 하는 요소가 그 사용처보다 코드 상위(먼저)에 정의되어야만 컴파일이 성공하는 경우가 일반적입니다.
이는 흔히 알려진 '컴파일 언어는 선언 순서에 자유롭다'는 인식과는 다릅니다. 그렇다면 선언 순서의 자유도에 영향을 미치는 근본적인 요인은 무엇일까요?
선언 순서의 자유도를 결정하는 핵심 요인은 언어의 종류(컴파일 vs 인터프리트)가 아닌, 컴파일러가 소스 코드를 처리하는 방식, 즉 '통과(Pass)' 횟수에 있습니다.
방식: 코드를 여러 번 스캔하여, 첫 번째 통과에서 모든 심볼(클래스, 함수 등)의 존재와 위치를 파악(전방 참조 허용)하고, 이후 통과에서 실제 검증 및 코드를 생성합니다. -> 즉, 선언 순서가 비교적 자유롭습니다.
방식: 코드를 위에서 아래로 한 번에 처리하며, 요소를 사용할 시점에는 반드시 그 정의가 이미 컴파일러에게 알려져 있어야 합니다. -> 즉, 선언이 사용처보다 앞에 되어있어야만 합니다.
코틀린 컴파일러는 단일 통과에 가까운 효율적인 처리를 지향하며, 이는 언어 설계 철학과 긴밀하게 연결되어 있습니다.
다른 근본 언어를 배우고 코틀린을 배우기 시작하면 코틀린이 얼마나 컴팩트함과 직관적임을 유지하고자 했는지 참... 느껴집니다 (개인적인 의견)
코틀린은 다중 스캔의 복잡성을 줄여 컴파일러 구조를 단순화하고 처리 속도를 높이고자 하였고 (근데 앱 개발할때는 애뮬레이터 때문에 느려터짐) 스크립트와 유사한 순차적 실행 흐름 갖도록 선언도 이 흐름에 맞춰 사용 전 정의를 규칙으로 확립함으로써 코드의 지역성(Locality)과 가독성을 극대화합니다.
코틀린은 JVM 기반 컴파일 언어의 이점을 유지하면서도, 현대적인 언어의 요구사항(간결성, 명확성)을 위해 명시적인 선언 순서를 채택한 것입니다.
결론적으로, 선언 순서의 자유도는 언어의 종류가 아닌 컴파일러의 내부 설계 방식에 의해 결정됩니다. 자바는 다중 통과로 유연성을 확보했고, 코틀린은 단일 통과 경향과 가독성 철학으로 명확성을 선택한 것입니다.
실무에서 코틀린을 사용할 때는 이 원리를 이해하고, 클래스나 함수를 사용하기 전에 정의하는 Top-Down 방식의 코딩 습관을 유지합시다!
컴파일러에게 코드 유연성과 목적 코드에 대한 접근 속도를 향상시킬 것인지, 컴파일 속도를 향상시킬 것인지 trade-off가 존재하겠네요! 그러면 사용자의 요구에 따라 컴파일 방식을 커스텀할 수 있는 컴파일러를 직접 만들어보는 것도 재밌을 것 같다는 생각이 듭니다. 잘 읽었습니다!