[Android/Java] findViewById가 Type safety하지 않은 이유
Type Safety, 말 그대로 "타입에 안정적인 것"이라는 뜻이다. findViewById의 문제점으로 꼽히는 것 중 Type Safety하지 못하다는 것이 있는데 타입에 불안정하다는 것은 코드 작성 중에 참조 변수에 잘못된 타입을 초기화했으나 컴파일 과정에서 발견하지 못해 Runtime 중에 오류가 발생할 수 있다는 것을 의미한다. 어떤 까닭으로 findViewById가 Type safety하지 못하다고 하는지 그 이유에 대해서 알아보자.
findViewById 메서드를 살펴보면 위와 같다. 다른 것을 제외하고 반환형을 보면 View 클래스를 상속받은 클래스 타입을 반환하도록 되어 있다. 여기서 View는 화면을 구성할 때 사용하는 모든 클래스의 최상위 클래스로 화면을 구성하는 TextView, EditText, ImageView 등 모든 클래스가 View 클래스를 상속받는다. 위와 같은 구조는 다음과 같은 오류를 발생시킬 수 있다.
EditText editText = findViewById(R.id.main_edit_text
ImageView imageView = findViewById(R.id.main_edit_text);
activity_main.xml에 EditText view를 작성하고 아이디 "main_edit_text"를 할당했다. MainActivity.java에서 EditText 객체와 ImageView 객체를 선언하고 findViewById를 통해 레이아웃에서 생성한 EditText view를 초기화해보자. 첫 번째 코드는 정상적이기 때문에 문제가 없다. 하지만 두 번째 코드는 타입이 ImageView인 참조 변수에 EditText를 초기화하고 있으니 문제가 발생할 것 같지만 이 코드는 문제가 없는 정상적인 코드다. 왜냐하면 ImageView 클래스는 View 클래스를 상속받고 있기 때문에 findViewById 반환형에 적합하기 때문이다. 즉 코드 문맥상 문제가 없기 때문에 위 코드는 초기화하는 것만으로는 에러로 인식되지 않는다.
문제는 imageView 객체에 참조하는 순간 발생한다. 빠르면 어플을 실행하면서 Activity가 초기화되는 과정에서 발견될 것이고 아니라면 어플을 사용하는 과정에서 에러를 발생시킬 것이다. 이렇게 컴파일 과정에서 잘못된 타입을 체크하지 못해서 런타임 중에 에러가 발생하는 것을 "타입에 불안정하다"라고 한다.
findViewById가 Type Safety하지 못한 이유에 대해서 알아봤다. 그렇다면 바인딩 방식은 findViewById와 무엇이 다르기에 Type Safety한 것인지 보자. 위 코드를 보면 바인딩 객체에서 mainEditText에 접근할 경우 <T extends View>와 같은 타입이 아닌 정확히 AppCompatEditText 객체를 반환해주고 있음을 볼 수 있다. 또 findViewById를 초기화할 땐 코드 문맥상 문제가 없기 때문에 에러를 잡지 못하지만 바인딩 객체는 정확한 타입의 객체를 반환함으로써 초기화려하는 객체의 타입과 반환하려는 객체의 타입이 다르다는 에러 메시지를 출력하고 있음을 볼 수 있다.