: 마커 인터페이스는 메서드 선언이 없는 인터페이스이다. 대표적인 마커 인터페이스로 Serializable과 Cloneable이 있다. 마커 인터페이스를 활용하는 예를 살펴보자. 



ex) 복잡한 조건문이 필요한 로직

if(A||B){
	operationA();
}
if(A||B||C){
	operationB();
}
if(C||D||E){
	operationC();
}
if(B||D||E){
	operationD();
}

복잡한 조건문이 필요한 로직을 구현할 때 위와 같이 구현할 것이다. 하지만 조건이나 해야할 작업(operationX)이 추가된다면 코드를 수정하는 데 번거롭다. 또한 기존 로직을 모르는 사람이 코드를 건드려야 한다면 어려움이 많을 것이다. 대안으로 상속을 통해서 복잡도를 해결할 수는 있다. 부모 클래스에서 operationX()를 구현한 다음 조건 별로 자식 클래스를 만들어서 operationX를 호출하거나 오버라이드할 수 있다. 복잡도는 어느 정도 해결되지만 문제가 있다. 여러 작업을 할 때 메서드 호출 순서가 중요한데 순서를 잘못 호출 가능성이 있다. 또한 자식 클래스에서 여러 개의 operationX()를 호출하는 데 이 들 중 하나를 사용하지 않게 될 경우 주석처리를 한다. 이는 소스가 지저분해질 수 있고 주석 해제 과정에서 실수할 가능성도 있다. 또 조건을 추가할 때 자식 클래스 중에서 비슷한 operationX을 사용해 해당 자식 클래스를 상속해서 구현할 수 있다. 상속을 많이 하게 되면 코드 수정시 바뀔 부분이 많기 때문에 상속을 최소화 하는 게 좋다. 이러한 문제들을 해결해 주는 게 마커 인터페이스이다.  다음은 마커 인터페이스로 복잡한 조건문을 단순화시키는 방법이다.


1. 각 작업을 마커 인터페이스로 매핑한다.

public interface Markable1{}
public interface Markable2{}
public interface Markable3{}
public interface Markable4{}

2. 각 조건별로 자식 클래스를 만든다.

AClass extends Category implements Markable1, Markable2 {}
BClass extends Category implements Markable1, Markable4 {}
CClass extends Category implements Markable2, Markable3 {}
DClass extends Category implements Markable3, Markable4 {}
3. 부모 클래스에서 인스턴스를 체크해서 해당 작업을 진행한다.
if(this instanceof Markable1){
	operationA();
}
if(this instanceof Markable2){
	operationB();
}
if(this instanceof Markable3){
	operationC();
}
if(this instanceof Markable4){
	operationD();
}


위와 같이 마커 인터페이스를 활용하면 먼저 부모 클래스에서 operationX()의 순서가 정해져 작업 순서가 바뀔 경우가 줄어든다. 또한 특정 oprerationX를 호출해야 하지 않아야 할 때 imprements 만 빼면 된다. operationX를 추가할 때도 인터페이스만 추가하면 된다.

마커 인터페이스는 마커 어노테이션(Annotation)으로 활용 가능하다. 위 마커 인터페이스 예를 마커 어노테이션으로 바꿔보자.

@Retention(RetentionPolicy.RUNTIME)
@interface Markable1{	
}
@Retention(RetentionPolicy.RUNTIME)
@interface Markable2{	
}
@Retention(RetentionPolicy.RUNTIME)
@interface Markable3{	
}
@Retention(RetentionPolicy.RUNTIME)
@interface Markable4{	
}
Class clazz = this.getClass();
if(clazz.isAnnotationPresent(Markable1.class)){
	operationA();
}
if(clazz.isAnnotationPresent(Markable2.class)){
	operationB();
}
if(clazz.isAnnotationPresent(Markable3.class)){
	operationC();
}
if(clazz.isAnnotationPresent(Markable4.class)){
	operationD();
}

마커 인터페이스나 마커 어노테이션이나 별반 차이가 없어 보인다. 하지만 인터페이스는 자식 클래스에도 영향을 미치지만 어노테이션은 자식 클래스에 영향을 안 미친다. 상황에 맞게 사용하면 될 것 같다.

+ Recent posts