반응형

제네릭을 사용해서 개발을 하다보면, 자주 마주하게 되는 비검사 경고에 대해서 이펙티브 자바에서는 어떻게 설명하고 있을까?

 

비검사 형변환 경고, 비검사 메서드 호출 경고, 비검사 매개변수화 가변인수 타입 경고, 비검사 변환 경고 등 제네릭을 사용하면 여러 경고를 맞이하게 된다. 제네릭에 익숙해질수록 마주치는 경고 수는 줄겠지만 새로 작성한 코드가 한번에 깨끗하게 컴파일되리라 기대하지는 말자.

대부분의 비검사 경고는 쉽게 제거할 수 있다. 컴파일러가 알려준 대로 수정하면 경고가 사라지긴 한다. 컴파일러가 알려준 타입 매개변수를 명시하지 않고, 자바 7부터 지원하는 다이아몬드 연사자만으로 해결할 수 있다. 그러면 컴파일러가 올바른 실제 타입 매개변수를 추론해준다. 제거하기 어려운 경고도 있지만, 곧바로 해결되지 않는 경고가 나타나도 포기하지말고 할 수 있는 한 모든 비검사 경고를 제거하자.

비검사 경고를 제거해야 하는 가장 큰 이유는 코드의 타입 안정성이 보장되기 때문이다. 그러면 런타임에 ClassCastException이 발생할 일이 없고, 의도한 대로 잘 동작하리라 확신할 수 있다. 경고를 제거할 수는 없지만 타입이 안전하다고 확신할 수 있다면 @SuppressWarnings("unchecked") 애너테이션을 달아 경고를 숨기자. 중요한 점은 타입이 안전하다고 확신할 수 있어야 한다는 점이다. 타입 안전을 검증하지 않은 채 경고를 숨기면 스스로에게 잘못된 보안 인식을 심어줄 수 있다. @SuppressWarning 애너테이션을 달고 있는 코드는 경고 없이 컴파일되겠지만, 런타임에는 여전히 ClassCastException이 발생할 수 있다. 안전하다고 검증된 비검사 경고를 그대로 두면 진짜 문제를 알리는 새로운 경고가 나와도 눈치채지 못할 수 있다. 제거하지 않은 수많은 거짓 경고 속에 새로운 경고가 파묻힐 것이기 때문이다. 

@SuppressWarning 애너테이션은 개별 지역변수 선언부터 클래스 전체까지 어떤 선언에도 달 수 있지만, 항상 가능한 좁은 범위에 적용해야 한다. 자칫 심각한 경고를 놓칠 수 있으니, 절대로 클래스 전체에 적용하지 말자. 

@SuppressWarning 애너테이션은 선언에만 달 수 있다. 깔끔하게 컴파일되고 비검사 경고를 숨기는 범위도 최소한으로 해당 애너테이션을 달도록 하자. @SuppressWarnings("unchecked") 애너테이션을 사용할 때면 그 경고를 무시해도 안전한 이유를 항상 주석으로 남겨야 한다. 다른 사람이 그 코드를 이해하는데 도움이 되며, 더 중요하게는, 다른 사람이 그 코드를 잘못 수정하여 타입 안전성을 잃는 상황을 줄여준다. 코드가 안전한 근거가 쉽게 떠오르지 않더라도 끝까지 포기하지 말자. 근거를 찾는 중에 그 코드가 사실은 안전하지 않다는 걸 발견할 수도 있다.

 

요약하자면,

비검사 경고는 중요하니 무시하지 말자. 모든 비검사 경고는 런타임에 ClassCastException을 일으킬 수 있는 잠재적 가능성을 뜻하니 최선을 다해 지거하자. 경고를 없앨 방법을 찾지 못하겠다면, 그 코드가 타입 안전성을 증명하고 가능한 한 범위를 좁혀 @SuppressWarnings("unchecked") 애너테이션으로 경고를 숨겨라. 그런 다음 경고를 숨기기로 한 근거를 주석으로 남겨라.

 

출처: 이펙티브 자바 3판

반응형

+ Recent posts