카테고리:

업데이트:

1. 들어가기

인터페이스는 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할을 합니다.

그렇기 때문에 어떤 인터페이스를 구현한다는 것은

자신의 인스턴스로 무엇을 할 수 있는지 클라이언트에게 말해주는 것입니다.

이 지침에 맞지 않는 예로 제가 사용을 고민해봤던 상수 인터페이스가 있습니다.

SNS 로그인을 연동해 보았을 때, 저는 상수를 많이 사용하게 되었습니다.

그 때 했던 고민 중 하나로 상수 인터페이스를 만들어서 설계하면 어떨까? 라는 고민을 했던 적이 있습니다.

예를 들면 다음과 같습니다.

  public interface Kakao {
    // 카카오 로그인에 필요한 RESTAPI KEY
    static final String REST_API_KEY = "...";

    // 카카오 로그인 인증 URL
    static final String AUTH_URL = "...";

    // 카카오 로그인 request parameter key
    static final String CLIENT_ID = "client_id";
  }
  public class KakaoLogin implements Kakao {
    public String getKakaoAuthUrl() {
      return new URIBuilder(AUTH_URL, StandardCharsets.UTF_8)
                      .setPath("/oauth/authorize")
                      .addParameter(CLIENT_ID, REST_API_KEY)
                      .build().toString();
    }
  }

하지만 이는 인터페이스의 안티 패턴입니다.

클래스 내부에서 사용하는 상수는 외부 인터페이스가 아니라 내부 구현에 해당되기 때문입니다.

따라서 상수 인터페이스를 구현하는 것은 내부 구현을 클래스의 API로 노출하는 행위로

사용자에게 혼란을 줄 가능성이 있고, 더 심하게는 클라이언트 코드가 이 상수들에 종속되게 합니다.

그럼 상수는 어떻게 구현할 수 있을까요?

2. 상수 구현 방법

  • 특정 클래스나 인터페이스와 강하게 연관된 상수

    이런 경우는 클래스나 인터페이스 자체에 상수를 추가합니다.

    대표적인 예로 Integer와 Double에 선언된 MIN_VALUE, MAX_VALUE가 있습니다.

  • 열거 타입으로 나타내기 적합한 상수

    Enum을 사용해 상수를 추가합니다.

  • 둘 다 아닌 경우

    인스턴스화할 수 없는 유틸리티 클래스에 담아 상수를 추가합니다.

      package example.sns;
    
      public class KakaoConstants {
        private KakaoConstants() {} // 인스턴스화 방지
    
        static final String REST_API_KEY = "...";
        static final String AUTH_URL = "...";
        static final String CLIENT_ID = "client_id";
      }
    

    만약, 유틸리티 클래스의 상수를 빈번히 사용한다면 static import를 사용할 수 있습니다.

      import static example.sns.KakaoConstants.*;
    
      public class KakaoLogin {
        public String getKakaoAuthUrl() {
          return new URIBuilder(AUTH_URL, StandardCharsets.UTF_8)
                        .setPath("/oauth/authorize")
                        .addParameter(CLIENT_ID, REST_API_KEY)
                        .build().toString();
        }
      }
    

3. 정리

이번 포스트는 인터페이스를 타입을 정의하는 용도로 사용하지 않은 안티패턴으로

상수 인터페이스에 대해 알아보았습니다.

인터페이스를 상수 공개용 수단으로 제공하게 된다면 사용자에게 혼란을 줄 가능성이 있고,

더 심하게는 클라이언트 코드가 이 상수들에 종속되게 합니다.

그렇기 때문에 인터페이스는 타입을 정의하는 용도로만 사용해야 하고

상수를 정의할 때는 다음의 3가지에 맞는 상수 구현 방법을 사용하도록 합시다.

  • 특정 클래스나 인터페이스와 강하게 연관된 상수

    🎯 클래스나 인터페이스 자체에 상수 추가

  • 열거 타입으로 나타내기 적합한 상수

    🎯 Enum

  • 둘 다 아닌 경우

    🎯 유틸리티 클래스

            
              📕 개인 기록용 블로그입니다.
              😊 오타나 잘못된 정보가 있을 경우 댓글이나 메일로 말씀해주시면 바로 수정하겠습니다! 😊
          

댓글남기기