본문 바로가기
Language/Java

[JAVA] 추상 클래스 vs 인터페이스 : 객체 지향 설계의 본질적 차이 분석

by Papa Martino V 2026. 1. 16.
728x90

추상 클래스 vs 인터페이스
추상 클래스 vs 인터페이스

 

자바 프로그래밍에서 '추상화'를 구현하는 두 가지 핵심 도구가 바로 추상 클래스(Abstract Class)인터페이스(Interface)입니다. 많은 초보 개발자들이 "둘 다 미완성 메서드를 갖는 것 아닌가?"라는 의문을 갖지만, 자바의 버전이 올라갈수록(Java 8의 default method, Java 9의 private method 도입 등) 두 개념의 기능적 경계는 모호해지면서도 그 설계적 목적은 더욱 명확해지고 있습니다. 본 포스팅에서는 단순히 문법적인 차이를 넘어, 실무에서 어떤 기준으로 두 도구를 선택해야 하는지 심층적으로 다루어 보겠습니다.


1. 추상 클래스(Abstract Class): "상태와 행위를 공유하는 혈연 관계"

추상 클래스는 abstract 키워드를 사용하여 선언하며, 단 하나라도 추상 메서드를 포함하고 있다면 반드시 추상 클래스로 선언되어야 합니다. 가장 큰 특징은 'is-a (~은 ~이다)' 관계를 형성한다는 점입니다.

주요 특징

  • 필드(변수) 보유 가능: 인스턴스 변수를 가질 수 있어 자식 클래스들의 공통된 상태를 유지하기에 유리합니다.
  • 생성자 존재: 직접 객체를 생성할 수는 없지만, 자식 객체가 생성될 때 부모의 초기화 로직을 수행할 생성자를 가집니다.
  • 목적: 부모의 유전자를 물려받아 기능을 확장하고, 공통 로직을 재사용하는 데 초점이 맞춰져 있습니다.

2. 인터페이스(Interface): "능력을 부여하는 계약 관계"

인터페이스는 interface 키워드를 사용하며, 'has-a (~을 할 수 있는)' 혹은 계약(Contract)의 의미가 강합니다. 클래스와 관계없이 특정 기능을 강제하고 싶을 때 사용합니다.

주요 특징

  • 다중 구현(Multiple Inheritance): 자바에서 클래스는 단일 상속만 가능하지만, 인터페이스는 여러 개를 동시에 구현할 수 있습니다.
  • 상태 비보유: 기본적으로 모든 변수는 public static final(상수)이며, 인스턴스 변수를 가질 수 없습니다.
  • 목적: 서로 다른 클래스들이라도 동일한 동작을 수행할 수 있도록 규격(스펙)을 맞추는 데 초점이 맞춰져 있습니다.

3. 추상 클래스 vs 인터페이스 핵심 비교

두 개념의 기술적 명세와 설계적 의도를 한눈에 비교해 보겠습니다.

비교 항목 추상 클래스 (Abstract Class) 인터페이스 (Interface)
사용 키워드 abstract class / extends interface / implements
상속/구현 범위 단일 상속만 가능 다중 구현 가능
변수(필드) 일반 변수 및 상수 가능 상수(static final)만 가능
생성자 존재함 존재하지 않음
설계 관점 부모의 특성을 확장 (is-a) 공통된 행위의 규약 (can-do)

4. 언제 무엇을 사용해야 할까? (Best Practice)

실무 환경에서의 선택 기준은 명확합니다.

추상 클래스를 선택하는 경우

  • 관련성이 높은 클래스들 간에 코드를 공유하고 싶을 때
  • 자식 클래스들이 부모의 필드나 메서드에 접근하여 상태를 변경해야 할 때
  • 접근 제어자(protected, private 등)를 통해 캡슐화를 유지하고 싶을 때

인터페이스를 선택하는 경우

  • 클래스의 계층 구조와 상관없이 특정 기능을 강제하고 싶을 때 (예: Comparable, Runnable)
  • 다중 상속 효과를 통해 객체에 여러 가지 능력을 부여하고 싶을 때
  • 결합도를 낮추어 유연한 설계(의존성 주입 등)를 지향할 때

5. Java 8 이후의 변화: 디폴트 메서드(Default Method)

과거에는 인터페이스에 메서드 구현을 넣을 수 없었으나, Java 8부터 default 키워드를 통해 메서드 바디를 가질 수 있게 되었습니다. 이는 기존 인터페이스에 새로운 기능을 추가할 때 발생하는 하위 호환성 문제를 해결하기 위함입니다. 그럼에도 불구하고 인터페이스가 추상 클래스가 될 수 없는 이유는 여전히 '상태(인스턴스 필드)'를 가질 수 없기 때문입니다.


6. 결론

추상 클래스는 나의 정체성(What)을 정의하고, 인터페이스는 나의 기능(How/Contract)을 정의합니다. 좋은 설계는 이 둘을 적재적소에 혼합하여 사용하는 것입니다. 부모의 공통 로직은 추상 클래스로 묶고, 외부와의 소통 창구는 인터페이스로 추상화하는 방식이 가장 견고한 객체지향 아키텍처를 만듭니다.


참고 문헌 및 출처

  • Oracle Java Documentation: Abstract Methods and Classes
  • Joshua Bloch, Effective Java 3rd Edition



728x90