1. 소개

이 빠른 사용방법(예제)에서는 Java의 마커 인터페이스에 대해 배웁니다.

2. 마커 인터페이스

마커 인터페이스는 내부에 메서드나 상수가 없는 인터페이스 입니다 . 객체에 대한 런타임 유형 정보를 제공 하므로 컴파일러와 JVM은  객체에 대한 추가 정보를 갖 습니다.

마커 인터페이스는 태깅 인터페이스라고도 합니다.

마커 인터페이스는 여전히 사용 중이지만 코드 냄새를 가리킬 가능성이 높으므로 신중하게 사용해야 합니다. 그 주된 이유는 마커가 어떤 동작도 정의하지 않기 때문에 인터페이스가 나타내는 선을 흐리게 하기 때문입니다. 최신 개발은 동일한 문제 중 일부를 해결하기 위해 어노테이션을 선호합니다.

3. JDK 마커 인터페이스

Java에는 Serializable , Cloneable 및  Remote 와 같은 많은 내장 마커 인터페이스가 있습니다.

Cloneable 인터페이스 의 예를 살펴보겠습니다 . 이 인터페이스를 구현하지 않는 객체를 복제하려고 하면 JVM에서 CloneNotSupportedException 이 발생 합니다. 따라서 Cloneable 마커 인터페이스는 Object.clone() 메서드  를 호출할 수 있는 JVM에 대한 표시기 입니다.

같은 방식으로 ObjectOutputStream.writeObject() 메서드 를 호출할 때  JVM은 객체가 Serializable  마커 인터페이스를 구현하는지 확인합니다 . 그렇지 않은 경우 NotSerializableException  이 발생합니다. 따라서 개체는 출력 스트림으로 직렬화되지 않습니다.

4. 커스텀 마커 인터페이스

우리만의 마커 인터페이스를 만들어 봅시다.

예를 들어 데이터베이스에서 개체를 제거할 수 있는지 여부를 나타내는 마커를 만들 수 있습니다.

public interface Deletable {
}

데이터베이스에서 엔티티를 삭제하려면 이 엔티티를 나타내는 객체가 Deletable  마커 인터페이스를 구현해야 합니다.

public class Entity implements Deletable {
    // implementation details
}

데이터베이스에서 엔터티를 제거하는 메서드가 있는 DAO 개체가 있다고 가정해 보겠습니다. 마커 인터페이스를 구현하는 객체만 삭제할 수 있도록 delete() 메서드를  작성할 수 있습니다.

public class ShapeDao {

    // other dao methods

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

        // delete implementation details
        
        return true;
    }
}

보시다시피, 우리는 객체의 런타임 동작에 대한 표시를 JVM에 제공하고 있습니다.  객체가 마커 인터페이스를 구현하는 경우 데이터베이스에서 삭제할 수 있습니다.

5. 마커 인터페이스와 어노테이션

어노테이션을 도입함으로써 Java는 마커 인터페이스와 동일한 결과를 얻을 수 있는 대안을 제공했습니다. 또한 마커 인터페이스와 마찬가지로 모든 클래스에 어노테이션을 적용할 수 있으며 특정 작업을 수행하기 위한 표시기로 사용할 수 있습니다.

그래서 중요한 차이점은 무엇입니까?

어노테이션과 달리 인터페이스를 사용하면  다형성을 활용할 수 있습니다 . 결과적으로  마커 인터페이스에 추가 제한을 추가할 수 있습니다.

예를 들어 데이터베이스에서 Shape  유형만 제거할 수 있다는 제한을 추가해 보겠습니다.

public interface Shape {
    double getArea();
    double getCircumference();
}

이 경우 마커 인터페이스인 DeletableShape 는 다음과 같습니다.

public interface DeletableShape extends Shape {
}

그런 다음 우리 클래스는 마커 인터페이스를 구현합니다.

public class Rectangle implements DeletableShape {
    // implementation details
}

따라서 모든  DeletableShape 구현은  Shape  구현 이기도 합니다 . 분명히 우리는 어노테이션을 사용하여 그렇게 할 수 없습니다 .

그러나 모든 디자인 결정에는 장단점이 있으며 마커 인터페이스에 대한 반론으로 다형성을 사용할 수 있습니다. 이 예에서 Rectangle 을 확장하는 모든 클래스 는 자동으로  DeletableShape를 구현합니다.

6. 마커 인터페이스와 일반적인 인터페이스

이전 예제에서 DAO의 delete() 메서드를 수정하여 객체가 Deletable 인지 여부를 테스트하는 대신 객체가 Shape  인지 여부 테스트 하여 동일한 결과를 얻을 수  있습니다.

public class ShapeDao { 

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

그렇다면 일반적인 인터페이스를 사용하여 동일한 결과를 얻을 수 있는데 왜 마커 인터페이스를 생성합니까?

Shape 유형 외에도 데이터베이스에서 Person 유형 도 제거하려고 한다고 가정해 보겠습니다 . 이 경우 이를 달성하기 위한 두 가지 옵션이 있습니다.

첫 번째 옵션은  삭제할 객체가 Person 의 인스턴스인지 여부를 확인하기 위해 이전 delete() 메서드 에 추가 검사를 추가하는 것 입니다 .

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

그러나 데이터베이스에서도 제거하려는 유형이 더 있다면 어떻게 될까요? 분명히 이것은 모든 새로운 유형에 대해 방법을 변경 해야 하기 때문에 좋은 선택이 아닙니다 .

두 번째 옵션은  Person 유형  이 마커 인터페이스 역할을 하는 Shape  인터페이스 를 구현 하도록 하는 것입니다. 그러나 Person 객체는 실제로 Shape 입니까? 대답은 분명히 아니오이며, 이는 두 번째 옵션을 첫 번째 옵션보다 더 나쁘게 만듭니다.

결과적으로 일반적인 인터페이스를 마커로 사용하여 동일한 결과를 얻을 수 있지만 결국 좋지 않은 디자인이 됩니다.

7. 결론

이 기사에서는 마커 인터페이스와 사용 방법에 대해 배웠습니다. 그런 다음 이러한 유형의 인터페이스에 대한 몇 가지 내장 Java 예제와 JDK에서 이를 사용하는 방법을 살펴보았습니다.

다음으로, 우리는 고유한 마커 인터페이스를 만들고 어노테이션을 사용하여 무게를 측정했습니다. 마지막으로 일부 시나리오에서 기존 인터페이스 대신 마커 인터페이스를 사용하는 것이 좋은 이유를 보여주었습니다.

항상 그렇듯이 코드는 GitHub 에서 찾을 수 있습니다 .

Generic footer banner