인터페이스에 대한 얘기를 하다가
여기까지 오게 되었네요..
이번 포스트에서는 어노테이션을 사용해서 지금까지 만들었던 심플 프레임워크를 바꿔보려고 합니다.
사실 이번 포스트는 인터페이스와는 큰 관련은 없을지 모르겠습니다.
어노테이션은 @XXX 의 형식으로 사용되는 것으로
가장 대표적인 어노테이션은 @Override 그리고 스프링에서 사용하는 @Controller나
JUnit4 이상에서 사용되는 @Test 정도라고 생각하는데요
이 어노테이션은.. 사전에서는 주석이라고 되어 있습니다. 일반적으로 코드에 주석이라고 하면
컴파일러나 JVM은 읽지 못 하고 사람만 볼 수 있는 주석이라고 생각을 했다면
이 어노테이션은 컴파일러나 JVM에서도 볼 수 있고 활용 할 수 있는 주석이라고 보시면 될 것 같습니다.
어노테이션을 만들면 그 어노테이션의 RetentionPolicy를 정하게 됩니다.
바로 Compile 혹은 Runtime 인데요
위 예시된 어노테이션 중 Override가 Compile 이고
나머지 것들이 Runtime이 될 것 같네요.
예상하셨겠지만
@Override를 잘못 사용하거나 실제로 Override하지 않은 메서드에 저 어노테이션을 사용하면
IDE가 에러를 표시해주죠. 바로 컴파일 단계에서 사용되는 어노테이션입니다. (컴파일 단계 까지만..)
Junit의 @Test나 스피링의 @Controller 어노테이션은 실제 Runtime시에 JVM이 읽고 사용 할 수 있는
어노테이션들입니다.
어노테이션에 대한 것들은 따로 찾아보시면 더 많이 나올거고.. 일단 여기서는
어떻게 프레임워크를 바꿔 볼 것인가.. 인데요..
Class 자체에 어노테이션을 달아서 , 특정 디렉토리의 클래스들을 실시간으로 읽어서
해당 어노테이션이 달려있는 클래스들의 특정 메서드를 실행하는 방법도 있을 것 이고
Junit처럼 메서드 레벨에 어노테이션을 달아서 그 메서드들을 실행시키는 방법도 있을 것 입니다.
여기서 해 보려고 하는 것은 후자입니다.
앞서서 인터페이스를 사용하여 isPassed라는 메서드를 실행하는 MuiltTester를 만들었었는데요..
사용자에 따라서는 하나의 테스터 클래스가 여러 테스트 메서드를 가지고 있고
그 메서드들을 전부 다 실행하여 테스트를 해보고 싶을 경우도 있을 것 입니다.
Junit처럼...
그럼 일단 여기서 사용 할 어노테이션을 만들어 보겠습니다.
MyTest.java
이 어노테이션을 Runtime시에 활용해서 메서드를 실행 하려고 하기 때문에
RetentionPolicy를 RUNTIME으로 설정하였습니다. 어노테이션의 이름은 MyTest고 @MyTest로 사용 될 것 입니다.
이제 테스트 클래스들의 상위 인터페이스를 만들어보겠습니다
ProductTester.java
앞에서는 이 인터페이스에 공통적으로 사용 할 메서드가 선언되어 있었지만
우리는 그것을 어노테이션으로 마킹하여 메서드를 실행시킬 것이기 때문에 여기서는
필요가 없게 됩니다. 그럼에도 불구하고 인터페이스를 만든 이유는 하나의 List에 해당 테스터 클래스들을
전부 넣고 loop를 돌면서 일괄적으로 실행하기 편하도록 하기 위함입니다.
JAVA에 있는 인터페이스 중 Serializable 같은 인터페이스겠네요..
만일 어노테이션을 클래스 레벨에서 선언하고
클래스들을 읽어서 특정 어노테이션이 달린 클래스만 실행 시키도록 한다면
이 인터페이스도 필요 없어지겠죠..
그럼 이제 실제 테스터 클래스들이 어떻게 사용되는지 볼게요..
@MyTest가 쓰인 곳과 메서드의 이름을 보세요.
메서드의 이름이 제각각이라더라도 @MyTest 어노테이션으로 표시를 해준격이 되기 때문에
실시간에 실행 가능한 메서드가 됩니다.
여기서는 테스트 메서드가 하나씩만 쓰여있지만 두개 세개가 되어도 상관 없습니다.
단지 테스트 프레임워크에서 실행하기 원하는 메서드에
@MyTest 어노테이션만 달아주면 됩니다.
대신.. reflect를 이용하여 method를 실행하게 되므로
파라메터 정도는 맞춰주는 것이 여로모로 편할 것 입니다.
그러면 MultiTester를 수정 한 AnnotationTester 클래스를 보겠습니다.
AnnotationTester.java
보시면 List에 들어있는 테스터 클래스들을 가져와서 Class 객체를 얻고
거기서 메서드들을 뽑아냅니다.
그리고 그 메서드들을 탐색하면서 MyTest.class 어노테이션을 가져와서
그 어노테이션이 있으면 그 메서드를 실행하는 로직으로 되어 있습니다
코드가 간단하니까
쉽게 보실 수 있을 것 입니다.
이 어노테이션을 잘 사용하면
여러모로 심플한 코드를 작성 할 수도 있습니다.
스프링에서 xml로 관리 되던 bean 객체들을 어노테이션을 도입하면서
코드의 간결함을 가져 올 수 있었던 것이 대표적인 예라고 생각합니다. (물론 xml이 더 좋다라고 생각하시는 분도 계십니다.. 관리적 측면에서..)
DB 컬럼을 어노테이션을 매칭하여
DB에서 가져 온 데이터를 자동으로 Domain 클래스의 필드와 매핑해서
Domain 객체를 생성 할 수도 있겠고요...
아무튼..
이렇게 해서 최종적으로는
어노테이션을 활용해서 테스트 프레임워크를 만들어보았습니다.
아주 심플하죠..ㅋㅋ
여기서 인터페이스와 어노테이션을 활용 한 방법은
아주 간단하고 수 많은 활용 방법 중 극히 일부분일 뿐입니다.
저도 계속 공부하고 있고요..
이런 것도 있구나.. 하고 느껴 보실 정도면
좋을 것 같습니다.