제네릭 구체화와 발할라 프로젝트

프로그래밍 언어에서 제네릭이란 타입 정보를 일반화함으로써, 프로그램의 논리적 흐름을 추상화시킬 수 있는 방안을 제공한다. 자바도 JDK5부터 타입 변수를 도입해 제네릭 프로그래밍이 가능해졌다. 하지만 당시의 의사결정 과정에선 제네릭이란 새로운 기능을 탑제한 JVM에서 기존 버전에서 컴파일된 클래스가 문제 없이 실행돼야 한다는 호환성의 문제를 굉장히 중요한 우선순위로 다뤘고, 이런 조건을 만족시키기 위해 컴파일러에 타입 변수(<T>와 같은)의 정보를 삭제하는 기능(type erasure)을 추가해서 어떤 버전의 JDK에서 클래스를 컴파일됐든 상관없이 호환성을 유지할 수 있도록 했다.

하지만 컴파일러가 제네릭 타입 정보를 알 수 없다는 사실은 자바라는 언어에 제약을 초래하게 된다. 제네릭 타입 변수를 통해 타입 안정성이 보장되는 가운데 여러 타입을 포용하는 플로우를 작성할 순 있지만, 타입 변수 자체에 접근해 유의미한 정보를 추출하여 조작하는 장치를 제공할 방법은 기대할 수 없게 됐다. 즉, 기반 타입(raw type)이 동일한 모든 제네릭 타입은 컴파일된 시점에서 모두가 서로 동일한 타입으로 존재하게 되기 때문에, 타입 변수에 기반해 인스턴스를 생성하거나 타입 변수에 따른 인스턴스 타입을 구분하는 등의 유용한 언어적 장치를 제공할 방안을 잃게 됐다. 이런 이유로 자바 개발자는 런타입에 타입 정보를 활용하기 위해선 리플렉션을 사용하거나 명시적으로 타입 정보를 메소드 간에 전달해야 하는 불편함을 감수하게 됐으며, JVM의 입장에서도 제네릭 타입 정보에 기반한 최적화의 기회를 잃게 됐다.

결국, 런타임에 제네릭의 타입 정보를 제대로 활용하기 위해선, 컴파일러가 타입을 삭제하지 않고 해당 정보를 클래스의 바이트코드 상에 나타낼 수 있도록 제네릭 정보를 구체적으로 인식(generic reification)하는 과정이 선행돼야 한다. 그리고 바로 이런 필요성이 OpenJDK 발할라 프로젝트에서 브라이언 거츠(Brian Goetz)와 게빈 킹(Gavin King) 사이에서 시작된 뜨거운 논쟁의 이면에 숨어있는 배경이다. 거츠가 이끌고 있는 발할라 프로젝트에선 값 타입(원시형 타입과 같은)과 참조형 타입 사이의 간격을 메꾸려는 시도를 하고 있는데, 게빈 킹의 입장에선 이번 기회에 값 타입과 참조 타입을 통합하는 타입 구조를 추가해서 좀 더 급진적이고 이상적인 방향으로 자바가 발전할 수 있길 기대하고 있는 듯 하다. 그리고 이런 변화를 성공시키기 위해선 컴파일러와 JVM의 변경이 필요하게 되고, 결국 그 방향은 제네릭 구체화를 포괄할 것으로 보인다. C#에선 CLR이 구체화된 제네릭을 활용하도록 하려는 노력이 성공했고, C++에선 극단적일 정도로 훌륭하게 제네릭을 활용(템플릿 메타프로그래밍)하는 방안을 제공해오고 있기 때문에, 이런 사례로부터의 경험을 바탕에 둔다면 현실적으로 불가능한 일은 아닐거란 생각이 든다. 발할라 프로젝트에서 List<int>와 List<Integer>의 상관 관계를 어떻게 정의하고 풀어낼지 그 결과가 기대된다. 자바가 제네릭 구체화로의 방향을 선택해서 타입 삭제에 따른 언어적 한계로부터 벗어날 수 있는 기회를 갖게 될지 지켜보도록 하자.