item 39) 명명 패턴보다 어노테이션을 사용하라
명명 패턴
전통적으로 도구나 프레임워크가 특별히 다뤄야 할 프로그램 요소를 이름으로 구분하는 패턴
예를 들면, JUnit에서 버전 3까지 테스트 메서드의 이름을 반드시 test로 시작하도록 지어야 한다는 규칙이 있었다.
단점
오타가 나면 제대로 작동되지 않지만 오류를 발생시키지 않는다.
비정상적인 상황을 정상적으로 간주하는 문제가 발생할 수 있다.
올바른 프로그램 요소에서만 사용되리라 보증할 수 없다.
개발자의 의도에 따라 움직이지 않는 경우가 발생한다.
TestSafety... 라는 클래스를 만들고 이 클래스 내부의 모든 메서드가 JUnit에서 실행되길 기대해도, 실제로는 실행되지 않는다.
프로그램 요소를 매개변수로 전달할 수 없다.
원하는 예외가 발생해야 성공하도록 테스트 코드를 작성하는 경우, 메서드 이름에 예외의 이름을 덧붙여야 하지만 컴파일러가 해당 클래스가 존재하는지조차 확인하기 어렵다.
어노테이션 타입
원하는 조건을 만족하지 못할 경우 컴파일에러를 발생시키므로, 명명 패턴의 문제점을 해결해준다.
메서드나 클래스 위에 붙여 자동으로 로직이 수행되도록 해준다.
마커 어노테이션
마커 어노테이션: 아무 매개변수 없이 단순히 대상에 마킹하는 용도로 사용하는 애너테이션
메타 어노테이션: 어노테이션 선언에 다는 어노테이션, 어노테이션의 조건을 정의할 수 있다.
아래는 마커 어노테이션으로
@Test
를 선언하는 예제이다.메타 어노테이션을 통해
@Test
어노테이션이 1) Runtime에도 유지되어야 하며, 2) 반드시 메서드 선언에만 사용되어야 함을 의미하게 된다.
마커 어노테이션 처리기
위 마커 어노테이션은 어떠한 로직을 처리하지 않는 단순한 어노테이션이다.
따라서 아래와 같이 마커 어노테이션 처리기 클래스를 두어 로직이 수행되도록 한다.
reflection을 사용해 어노테이션이 붙은 메서드를 찾아 실행하고, 발생한 예외를 처리한다.
매개변수가 있는 어노테이션
아래와 같이 어노테이션의 매개변수를 입력받을 수 있다.
n개의 예외 클래스를 입력받아, 테스트 메서드에서 해당 예외가 발생했는지 확인하도록 한다.
모든 예외는 Throwable을 확장하므로 한정적 타입 토큰을 활용할 수 있다.
마커 어노테이션 처리기 클래스에서 아래와 같이 매개변수를 가져와 원하는 예외가 발생했는지 확인할 수 있다.
@Repeatable 메타 어노테이션
어노테이션에
@Repeatable
을 달아 여러개의 값을 받는 어노테이션을 만들 수 있다.아래와 같이 같은 어노테이션에 매개변수를 다르게 입력해 여러번 달 수 있다.
코드 가독성을 개선할 수 있다.
어노테이션 선언부와 처리하는 부분의 코드 양이 늘어난다.
처리 코드가 복잡해지므로 오류 발생할 가능성이 커진다.
주의할 점
@Repeatable을 명시한 어노테이션을 반환하는 컨테이너 어노테이션을 하나 더 정의하고, @Repeatable에 해당 컨테이너 어노테이션의 class 객체를 매개변수로 전달해야 한다.
컨테이너 어노테이션은 내부 어노테이션 타입의 배열을 반환하는 value 메서드를 정의해야 한다.
적절한 @Retention과 @Target을 명시해야 컴파일 오류가 발생하지 않는다.
@Repeatable 구현 예제
아래 예제는 ExceptionTest에 @Repeatable을 달고, 컨테이너 어노테이션을 매개변수로 전달하는 형태이다.
마커 어노테이션 처리기 클래스에서 아래와 같이 매개변수를 가져와 예외가 발생했는지 확인할 수 있다.
어노테이션을 여러개 달면 해당 컨테이너 어노테이션 타입이 적용되므로, isAnnotationPresent 메서드로 컨테이너 어노테이션을 검사해야 한다.
Last updated