ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - 인터페이스
    Language/Java 2021. 12. 8. 13:33

    인터페이스란?

    인터페이스의 개념

     - 인터페이스란, 자바 프로그래밍 언어에서 클래스들이 구현해야 하는 동작을 지정하는 데 사용되는 추상 자료형이다.

     - 즉, 동일한 목적 하에 동일한 기능을 수행하게끔 강제하는 역할을 하는 것이다. 

     - 자바의 다형성을 극대화하여 개발코드 수정을 줄이고 프로그램 유지보수성을 높이기 위해 인터페이스를 사용한다.


    인터페이스의 문법

    인터페이스의 구성요소

     - 인터페이스는 interface 키워드를 통해 선언할 수 있으며, 일반 클래스에서 implements 키워드를 통해 인터페이스를 구현할 수 있다.

     - 또한, Java 8 이전까지는 상수, 추상 메서드만 선언이 가능했지만, Java 8부터는 디폴트 메서드, 정적 메서드가 추가되었다.

     

    public interface 인터페이스명 {
        
        /** 상수 */
        타입 상수명 = 값;
        
        /** 추상 메서드 */
        타입 메서드명(매개변수, ...);
        
        /** 디폴트 메서드 */
        default 메서드명(매개변수, ...) {
        }
        
        /** 정적 메서드 */
        static 메서드명(매개변수) {
        }
    }

    1. 상수 : 인터페이스에서 값을 정해줄 테니 함부로 바꾸지 말고 제공해주는 값만 참조하라는 의미

    2. 추상 메서드 : 가이드만 제공해 줄 테니 추상 메서드를 오버라이딩해서 재 구현하라는 의미

    3. 디폴트 메서드 : 인터페이스에서 기본적으로 제공해주지만, 마음에 들지 않으면 각자 구현해서 사용하라는 의미

    4. 정적 메서드 : 인터페이스에서 제공해주는 것으로, 무조건 사용해야 하는 메서드임을 의미


    인터페이스의 사용

    인터페이스의 구현

     - 하나의 예를 들어보겠다. 대한민국에서 은행 사업을 하기 위해서는 금융결제원에서 정의한 가이드를 따라야 하고, 해당 가이드는 Bank라는 이름의 인터페이스 형태로 구성되어 있다. 이제 어떤 은행이든 은행 시스템을 운영하기 위해서는 Bank 인터페이스 가이드에 맞게 구현을 해야 한다.

     

    public interface Bank {
        
        /** 상수 (고객에게 인출해 줄 수 있는 최대 금액) */
        public int MAX_INTEGER = 10000000;
        
        /** 추상 메서드 (인출 메서드) */
        void withDraw(int price);
        
        /** 추상 메서드 (입금 메서드) */
        void deposit(int price);
        
        /** 디폴트 메서드 (고객의 휴면계좌를 찾아주는 메서드) */
        default void findDormantAccount(String customId) {
            System.out.println(customId + "님의 휴면계좌 : 000-000-0000-00");
        }
        
        /** 정적 메서드 (블록체인 인증을 요청하는 메서드) */
        static void blockChainAuth(String backName) {
            System.out.println(backName + "에서 블록체인 인증을 요청합니다.");
        }
    }

     - 인출 메서드(withDraw( )), 입금 메서드(deposit( ))는 각 은행에서 오버라이딩해서 재구현을 해야 하며, 정적 메서드인 블록체인 인증 메서드(blockChainAuth( ))는 무조건 금융결제원에서 제공하는 메서드를 사용해야 한다.

     

     - 위 코드에서 디폴트 메서드(findDormantAccount( ))는 무엇일까? 하나의 예시를 들어 설명해 보겠다.

     

     - 금융 결제원에서 이미 Bank 인터페이스를 각 은행사에 배포를 하였고 정상적으로 서비스가 되고 있는데, 갑자기 금융 트렌드가 바뀌면서 고객의 휴면계좌를 찾아주는 서비스를 정부에서 점진적으로 도입하라고 지시를 한 상태이다.

     

     - 이 상황에서 추상 메서드를 추가해서 다시 가이드를 하면 되지 않을까?라고 생각하겠지만, 이것은 쉬운 방법이 아니다. 왜냐하면 각 은행사마다 개발환경 및 운영환경이 다르고, 휴면계좌를 찾아주는 신규 프로세스를 도입하는 데 있어 개발기간이 모두 상이하기 때문이다.

     

     - 즉, 추상 메서드를 인터페이스에서 추가한다면, Bank 인터페이스를 implements 한 모든 클래스에서 강제적으로 추상 메서드를 구현해야 하고 구현하지 않을 시 에러가 난다.

     

     - 하지만, 기본 구현부에 대한 디폴트 메서드를 정의하고, 만약 기본 구현부가 마음에 들지 않으면 각자가 오버라이딩을 하여 재 구현할 수 있도록 선택적인 메서드를 가이드한다면, 시스템 운영에 있어서 유지보수성이 확보될 것이다.

     

    인터페이스를 통한 재정의
    public class KBBank implements Bank {
    
        @Override
        public void withDraw(int price) {
            System.out.print("KB은행만의 인출 로직");
    		
            if(price < Bank.MAX_INTEGER)
                System.out.println(price + "원 인출 성공");	
            else
                System.out.println(price + "원 인출 실패");	
        }
    
        @Override
        public void deposit(int price) {
            System.out.print("KB은행만의 입금 로직");
            
            System.out.println(price + " 원 입금");
        }
    }

     - 위 코드는 KB은행이 Bank 인터페이스를 통해 은행사에 맞는 스타일로 인출, 입금 서비스를 제공한 사례이다.

     - KB은행은 휴면계좌를 찾아주는 메서드를 재 구현하지 않았다. 즉, 금융결제원이 제공해주는 메서드를 아직은 사용하지 않겠다는 뜻으로 이해하면 된다.

     

    public class SHBank implements Bank {
    
        @Override
        public void withDraw(int price) {
            System.out.println("SH은행만의 인출 로직");
            
            if(price < Bank.MAX_INTEGER)
                System.out.println(price + "원 인출 성공");	
    		else
                System.out.println(price + "원 인출 실패");
        }
    
        @Override
        public void deposit(int price) {
            System.out.println("SH은행만의 입금 로직");
            System.out.println(price + "원 입금");
        }
    	
        @Override
        public String findDormantAccount(String customId){
            System.out.println("SH은행만의 휴면계좌 찾기 로직");
            System.out.println(customId + "님의 휴면계좌 : 000-000-0000-00");
        }
    }

     - SH은행 같은 경우에는 휴면 계좌 찾아주기 메서드를 오버라이딩하여, SH은행사 만의 휴면계좌 찾아주기 로직은 재 구현하였다.

     

    public class KakaoBank {
    
        public void kakaoWithDraw(int price) {
            System.out.print("Kakao은행만의 인출 로직");
            
            System.out.println(price + "원 인출");	
        }
    
        public void kakaoDeposit(int price) {
            System.out.print("Kakao은행만의 입금 로직");
            
            System.out.println(price + "원 입금");
    	}
    	
        public void kakaoFindDormancyAccount(){
            System.out.println("kakao은행만의 휴면계좌 찾기 로직");
        }
    }

     - 마지막으로, 신규 은행사인 카카오뱅크에 대한 코드이다. 위 코드에서 볼 수 있듯이 카카오뱅크는 Bank 인터페이스를 implements를 하지 않은 채 자신만의 메서드를 구현하였다. 이럴 경우 금융결제원에서 제공해주는 어떠한 서비스도 사용할 수 없으며, 호환성이 없어 연동이 불가능할 것이다.

     

    public class Main {
        public static void main(String[] args) {
            Bank bank = new KBBank();
            bank.withDraw(100);
            bank.deposit(100);
            bank.findDormantAccount("763231");
            Bank.BCAuth("KBBank");
            
            // ========== 인스턴스 교체 ==========
            
            bank = new SHBank();
            bank.withDraw(100);
            bank.deposit(100);
            bank.findDormantAccount("1282");
            Bank.BCAuth("SHBank");
        }
    }

     - 위 코드와 같이 하나의 타입(Bank)으로 간단하게 인스턴스(KBBank, SHBank)를 바꾸며 사용이 가능하다. 


    정리

    요약

     - 인터페이스는 상수와 추상 메서드를 통해 강력한 강제성을 가지게 하여, 해당 인터페이스를 구현한 클래스가 동일한 동작을 수행하도록 보장해 준다.

     - 또한, Java 8부터는 디폴트 메서드를 허용하면서 추가요건에 대한 대처를 할 수 있도록 유연성을 확보해주었다.


    출처

    https://limkydev.tistory.com/197

     

    728x90

    댓글

Designed by Tistory.