아장아장 개발 일기

마커 인터페이스(Marker Interface)의 이해(+ 어노테이션, 일반 인터페이스와의 비교) 본문

개발/Spring

마커 인터페이스(Marker Interface)의 이해(+ 어노테이션, 일반 인터페이스와의 비교)

빨간머리 마녀 🍒 2022. 12. 22. 13:19

CrudRepository와 JPARepository의 차이에 대해 배우던 중, 마커 인터페이스(Marker Interface)에 대한 개념이 나와 공부할겸

Baeldung의 관련 게시글을 번역, 정리해보았다.

 

마커 인터페이스란?

마커 인터페이스라 하면 아래를 의미한다.

  • 내부에 메서드나 상수가 없는 인터페이스
  • 객체에 대해 런타임 타입의 정보를 제공
    → 컴파일러와 JVM이 객체에 대해 추가적인 정보를 확인할 수 있음
  • 태깅 인터페이스(tagging interface)라고도 불림
  • 코드 스멜(code smell)을 야기할 수 있어 잘 사용해야함
  • 최근 개발 동향은 같은 용도로 어노테이션 사용을 선호하는 편
    → 마커 인터페이스와 어노테이션간의 공통점, 차이점은 아래의 '마커인터페이스 VS 어노테이션'에 서술

 

JDK 마커 인터페이스

자바 내에서의 마커 인터페이스의 예시와 특징은 아래와 같다.

  • 자바에는 Serializable, Cloneable, Remote과 같은 내장 마커 인터페이스가 있음
  • Cloneable 마커 인터페이스는 Object.clone() 메서드를 호출할 수 있는지를 JVM에 알려주는 지표로 역할
  • 마찬가지로 ObjectOutputStream.wwriteObject() 메서드를 호출할때 JVM은 객체가 Serializable 마커 인터페이스를 상속하는지 확인 → 아닐 경우 NotSerializableException 발생

 

커스텀 마커 인터페이스 예시 코드

public interface Deletable {

}

// 객체가 DB에서 삭제될 수 있는지 확인하는 마커 인터페이스
public class Entity implements Deletable {
	// implements details
}

//DB에서 객체를 삭제하기위해 객체는 위의 Deletable 마커 인터페이스를 상속
public class ShapeDao {

	// other dao methods

	public boolean delete(Object object) {
		if (!(object instanceof Deletable)) {
			return false;
		}

		// delete implementation details

		return true;
	}
}

// DB에서 객체를 삭제하는 메서드를 가진 DAO 객체
// 위의 코드에서 볼 수 있듯이 JVM에 객체의 런타임 행동에 대해 정보를 주고있음
// 만약 객체가 마커인터페이스를 상속하면 DB에서 삭제될 수 있음

 

마커 인터페이스 VS 어노테이션

위에서 최근에는 마커 인터페이스의 용도를 어노테이션으로 사용하는 추세라고 설명했는데, 마커 인터페이스와 어노테이션의 특징(공통점, 차이점)은 아래와 같다.

  • 공통점  : 둘다 모든 클래스에 적용될 수 있고, 특정 행위를 수행하기 위한 지표로 사용할 수 있음
  • 차이점 : 어노테이션과 다르게 인터페이스는 다형성 활용 가능 → 마커 인터페이스에 추가적인 제약을 설정할 수 있음
public interface Shape {
	double getArea();
	double getCircumference();
}

// Shape 타입만 DB에서 삭제 될 수 있도록 제한사항 추가

 

public interface DeletableShape extends Shape {
}
// 마커 인터페이스인 DeletableShape
public class Rectangle implements DeletableShape {
	// implements details
}

// 모든 DeletableShape 상속은 곧 Shape 상속임 → 어노테이션을 활용해서는 구현 불가능
// 다형성을 마커인터페이스에 반하여 사용하게 될 수도 있다는 단점도 있음
// 예) Rectangle을 상속하는 모든 클래스는 자동으로 DeletableShape을 상속하게 됨

 

마커 인터페이스 VS 일반 인터페이스

앞의 예시에서는 객체가 Shape인지 아닌지를 테스트하기 위해, 객체가 Deletable 인지 확인하는 대신, DAO의 delete() 메서드를 수정하였고, 둘다 같은 결과값을 가졌다. 그렇다면 왜 일반적인 인터페이스 대신 마커 인터페이스를 사용하는 것일까?

public class ShapeDao { 

    // other dao methods 
    
    public boolean delete(Object object) {
        if (!(object instanceof Shape)) {
            return false;
        }
    
        // delete implementation details
        
        return true;
    }
}

 

Shape 타입 뿐만 아니라 Person 타입도 삭제하고 싶다고 가정하면 이를 구현하기 위한 두가지 옵션이 있다.

1. 삭제하려는 객체가 Person인지 체크하는 소스 추가
삭제하고 싶은 타입이 늘어날때마다 메서드를 수정해야하는 단점이 있다.

public boolean delete(Object object) {
    if (!(object instanceof Shape || object instanceof Person)) {
        return false;
    }
    
    // delete implementation details
        
    return true;
}
// 삭제하고 싶은 타입이 늘어날때마다 메서드를 수정해야하는 단점이 있음

2. Person 타입이 Shape 인터페이스를 상속
  → 엄밀히 말하면 Person은 Shape 이 아니다.

 

⇒ 일반적인 인터페이스로도 마커 인터페이스와 같은 결과를 낼 수는 있지만 전체적인 코드 디자인이 나빠진다.

 

 

* 참고

https://www.baeldung.com/java-marker-interfaces#:~:text=A%20marker%20interface%20is%20an,also%20called%20a%20tagging%20interface

 

Comments