glenn-syj / more-effective-java

이펙티브 자바를 읽으며 자바를 더 효율적으로 공부합니다
4 stars 5 forks source link

[MEJ-009] 마커 인터페이스 활용에 대한 예시 #177

Closed yngbao97 closed 4 months ago

yngbao97 commented 5 months ago

Based on: #173 by @FickleBoBo


마커 인터페이스의 경우 자바가 기본적으로 제공하는 마커 인터페이스를 개발자가 implements 할지 여부를 결정하는 것이 중요해보였는데, 개발자가 마커 인터페이스를 굳이 정의해서 활용할 필요가 있을지 고민이 되었는데 해답을 얻기 어려웠다.

어려웠던 점으로 적어주셨던 '개발자가 마커 인터페이스를 활용할 필요성'에 대해 조금 공부해보았는데, 마침 좋은 예시를 찾아 공유하고자 합니다.

마커 인터페이스는 객체에 대한 런타임 유형 정보를 JVM에 제공합니다. 예를 들어, ObjectOutputStream.writeObject() 메서드를 호출할 때 JVM은 객체가 직렬화 가능한 상태인지 인터페이스 구현 여부를 통해 확인합니다. 따라서 아래 적어주신 내용처럼 '제한의 개념'으로 가볍게 이해해볼 수도 있을 것 같습니다.

마커 인터페이스는 그냥 인터페이스이므로 이를 구현한 클래스들은 마커 인터페이스 타입으로 구분이 가능하기 때문에 기능의 확장 혹은 제한의 개념으로 사용할 수 있을 것 같다.

마커 인터페이스 Deletable 정의

예를 들어, 데이터베이스에서 객체를 제거할 수 있는지 여부를 나타내는 Deletable이라는 마커 인터페이스를 정의해볼 수 있습니다.

public interface Deletable {
}

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

그렇다면 데이터베이스에서 엔터티를 제거하는 메서드가 포함된 DAO가 있다고 가정해보겠습니다. Deletable 을 구현한 객체만 삭제할 수 있도록 다음과 같이 delete 메서드를 작성할 수 있습니다.

public class ShapeDao {

    // other dao methods

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

        // delete implementation details

        return true;
    }
}

마커 인터페이스의 장점

애너테이션과 달리 인터페이스를 사용하면 다형성을 활용할 수 있습니다. 마커 인터페이스에 추가 제한사항을 두는 것입니다.

예를 들어 Shape 유형만 제거할 수 있다는 제한을 추가하려면 다음과 같이 작성할 수 있습니다.

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

public interface DeletableShape extends Shape {
}

이렇게 되면 Shape 유형 중 DeletableShape를 구현한 객체들만 해당 제한사항을 통과할 수 있게 됩니다.

단순히 Shape을 구현했다고 해서 deletable 하지않고, DeletableShape를 구현하더라도 Shape 유형이 아니라면 문제가 발행하게 됩니다. 이렇게 구조적으로 다형성을 활용할 수 있는 것이 마커 애너테이션 및 일반 인터페이스와 구별되는 마커 인터페이스의 장점이자, 개발자가 직접 정의해볼 수 있는 부분이지 않을까 생각했습니다.

짧은 지식으로 열심히 정리해봤습니다만 첨부드린 링크도 참고해서 읽어보시면 좋을 것 같습니다. 고민에 대한 해답에 조금 도움이 된다면 좋겠네요. 흥미로운 주제로 글 작성해주셔서 감사합니다!


참고자료

FickleBoBo commented 5 months ago

마커 인터페이스를 활용하는 좋은 예시를 찾아와 주셔서 학습에 많은 도움이 될 것 같습니다.

delete 메서드에서 instanceof를 통해 마커 인터페이스를 구현했는지 확인하는 방식으로 해당 객체가 삭제를 해도 되는 객체인지 확인하는 코드로 보이는데, 마커 인터페이스를 사용한 좋은 예시라고 생각됩니다.

DeletableShape의 예시의 경우 Deletable 마커 인터페이스에서 한단계 더 나아간 형태로 보이는데(다형성 적극 활용) 이러한 활용을 통해 파라미터에 대해 자세하게 예외처리를 할 수 있다는 점이 좋은 것 같습니다.