abstract vs interface: 비슷한데 왜 굳이 둘 다 있을까?

2026. 1. 27. 03:20·Learning Log

Java 문법을 공부하다 보면 abstract 과 interface가 나란히 등장한다.

처음엔 이렇게 느꼈다.

  • 추상 클래스는 상속받아 확장해서 쓰니까 유용하네.
  • 그런데 인터페이스는 다중 구현도 되네? 더 좋은 거 아닌가?

그런데 곧 의문이 생겼다.

메서드는 보통 내부 상태(필드)를 바꾸면서 동작하는데,

인터페이스는 추상 메서드는 있어도 멤버 필드(상태)는 못 가진다고 한다.

이거 좀 이상한데…?

abstract과 interface를 구분하는 기준은 “단일 상속 vs 다중 상속” 같은 문법 차이가 아니라, 상태(state)를 어떻게 다루는가에 있다.


1) “객체” vs “약속”

아래 문장 두 개로 정리하면 이해가 가장 빠르다.

  • abstract class = 불완전한 객체(공통 상태 + 기본 동작 포함 가능)
  • interface = 행동에 대한 계약(역할/능력만 표현)

즉, 추상 클래스는 “이런 종류의 객체다”라는 정체성(is-a)에 가깝고,

인터페이스는 “이런 행동을 할 수 있다”라는 역할(can-do)에 가깝다.


2) 진짜 차이: 상태(state)를 가질 수 있나?

구분 abstract class interface
상태(필드) ✅ 가능 ❌ 불가(상수만)
목적 공통 기반(템플릿) 제공 역할/규약 제공
관계 is-a (정체성) can-do (능력)
다중 ❌ 단일 상속 ✅ 다중 구현

여기서 중요한 건 “interface는 필드를 못 가진다”는 규칙이 불편함이 아니라 의도된 설계라는 점이다.


3) interface가 상태를 못 갖는 이유: “다중 + 상태”는 충돌을 부른다

인터페이스가 다중 구현이 가능한데, 만약 상태까지 허용하면 이런 문제가 생긴다.

interface Flyable {
    int speed;
}

interface Swimmable {
    int speed;
}

class Duck implements Flyable, Swimmable { }

여기서 Duck.speed는 무엇을 의미해야 할까?

  • Flyable의 speed?
  • Swimmable의 speed?
  • 둘 다면 어떻게 합칠까?

이런 애매함은 실제로 언어 설계에서 굉장히 위험하다.

그래서 Java는 결정을 내렸다.

인터페이스는 “행동의 계약”만 담당하게 하고,

공유 가능한 값(상수)만 허용하자.

그래서 인터페이스의 필드는 사실상 항상 상수다.

interface HttpStatus {
    int OK = 200; // public static final
}

이건 “상태”가 아니라 “정의(값의 기준)”에 가깝다.


4) 그럼 interface의 메서드는 무엇으로 동작할까?

인터페이스 자체에는 상태가 없다.

대신 구현 클래스가 상태를 가지고, 인터페이스 메서드는 그 상태를 기반으로 동작한다.

interface Payable {
    void pay(int amount);
}

class BankAccount implements Payable {
    private int balance;

    @Override
    public void pay(int amount) {
        balance -= amount;
    }
}

  • Payable은 “결제할 수 있다”는 규약만 제공
  • 실제 데이터(balance)는 구현체가 관리

인터페이스가 “약속”이라는 말이 여기서 완성된다.


5) abstract class는 언제 유리할까?

추상 클래스는 공통 상태와 기본 동작을 공유하고 싶을 때 적합하다.

abstract class Animal {
    protected int energy;

    public void eat() {
        energy += 10;
    }

    public abstract void move();
}

class Dog extends Animal {
    @Override
    public void move() {
        energy -= 5;
    }
}

  • 모든 동물이 갖는 공통 상태(energy)
  • 공통 동작(eat)
  • 반드시 구현해야 하는 동작(move)

이런 구조는 인터페이스만으로 만들면 결국 중복이 늘어나기 쉽다.


6) 결국 “역할 분담”이다

비유로 설명하자면,

  • abstract class: “이건 차량이다”(정체성/기반)
  • interface: “이건 결제할 수 있다”(능력/역할)

그래서 실제 코드에서는 둘을 섞어 쓸 수도 있다.

abstract class Vehicle {
    protected int speed;
    public abstract void move();
}

interface Payable {
    void pay(int amount);
}

class Taxi extends Vehicle implements Payable {
    private int money;

    @Override
    public void move() {
        speed += 10;
    }

    @Override
    public void pay(int amount) {
        money += amount;
    }
}

Taxi는:

  • Vehicle이라는 정체성을 가지면서(is-a)
  • Payable이라는 역할도 수행한다(can-do)

7) 언제 무엇을 선택할까?

  • 공통 상태(필드) + 기본 동작을 공유해야 한다 → abstract
  • 서로 무관한 클래스들에 동일한 행동을 강제해야 한다 → interface
  • “이 객체는 무엇인가?”가 중요하다 → abstract
  • “이 객체는 무엇을 할 수 있는가?”가 중요하다 → interface

'Learning Log' 카테고리의 다른 글

[멋사 클라우드 5기] Day 5 - Java 기본 라이브러리 & 컬렉션 정리  (0) 2026.01.28
equals가 있는데 hashCode는 왜 필요할까?  (0) 2026.01.27
[멋사 클라우드 5기] Day 4 - 상속, 다형성, 그리고 abstract vs interface  (0) 2026.01.27
[멋사 클라우드 5기] Day 3 - 객체 생성 흐름과 클래스 구조 이해하기  (1) 2026.01.25
[멋사 클라우드 5기] Day 2 - 배열, Git & GitHub 기본 개념 정리  (0) 2026.01.25
'Learning Log' 카테고리의 다른 글
  • [멋사 클라우드 5기] Day 5 - Java 기본 라이브러리 & 컬렉션 정리
  • equals가 있는데 hashCode는 왜 필요할까?
  • [멋사 클라우드 5기] Day 4 - 상속, 다형성, 그리고 abstract vs interface
  • [멋사 클라우드 5기] Day 3 - 객체 생성 흐름과 클래스 구조 이해하기
allluck777
allluck777
allluck777
    • 분류 전체보기 (44) N
      • AWS (0)
      • Network (0)
      • Linux (0)
      • Docker (0)
      • Project (4)
        • CloudNote (4)
      • Learning Log (36) N
      • Lecture (3)
        • 스프링 입문 - 코드로 배우는 스프링 부트, 웹 .. (3)
  • 전체
    오늘
    어제
  • hELLO· Designed By정상우.v4.10.6
allluck777
abstract vs interface: 비슷한데 왜 굳이 둘 다 있을까?
상단으로

티스토리툴바