Abstract란 뜻 자체로는 "추상적인"이란 의미를 가지고 있고, JAVA에서는 "완전치 않은"이란 의미로 사용이 되고 있다. 주로 클래스나 메소드에서 사용이 가능하고, 사용 방식은 설계만 존재하고 실제 구현된 내용은 없는 상태를 명시한다. 클래스와 메소드에만 붙을 수 있고, 변수(멤버 또는 로컬)에는 붙을 수 없다.

public abstract class Animal{
private String name;
public abstract void sound(); // 하위 클래스에서 해당 메소드의 내용을 반드시 구현해야함.
}
class Dog extends Animal{
@Override
public void sound(){
System.out.println("멍"); // 상속을 받아서 메소드의 내용을 구현을 함.
}
}
class Cat extends Animal{
@Override
public void sound(){
System.out.println("야옹"); // 상속을 받아서 메소드의 내용을 구현을 함.
}
}
Abstract의 기본적인 골자는 이러하다.
Abstract가 붙은 class는 직접적으로 객체를 만들 수 없고, 반드시 상속을 통해서만 사용을 해야된다. 그리고 이 추상 클래스 내부에서는 내용이 존재하지 않는 추상 메소드를 포함 시킬 수 있다.
Abstact가 붙은 Method는 리턴타입, 이름, 파라미터만 존재하고, 중괄호 내의 구현된 내용은 존재하지 않는다. 해당 메소드는 반드시 그 클래스를 상속 받는 하위 클래스 내부에서 반드시 구현이 되어야 한다.
그러면 왜 이렇게 번거롭게 Abstract를 써가면서 클래스나 메소드를 구현을 해야 될까?
그 이유는 일관된 구조와 코드 표준화를 통해서 하위 클래스들에게 공통 필드, 메소드 등의 설계 골격을 미리 제공되어 설계가 일관되고 개발 속도를 향상 시킬 수 있다. 그리고 코드 재사용성을 증가시켜 코드 중복을 최소화 시킬 수 있다. 마지막으로 한 군데에서 공통 설계를 관리를 하기 때문에 여러 하위 클래스가 추상 클래스를 상속, 유지보수와 확장이 쉽고 편리하다.
세 줄 요약을 하면
1. 개발속도 향상
2. 코드 재사용성 증가
3. 유지보수와 확장 편리
하지만 이 Abstract에서도 한계점은 존재한다.
추상 클래스는 단일 상속만 지원을 하기 때문에 복잡한 구조에서는 추후에 나올 인터페이스만큼의 유연성이 떨어질 수 있다.
모든 하위 클래스가 추상 메소드를 구현을 해야되기 때문에 상속을 받았지만 불필요한 메소드들까지 다 구현을 해야되서 불필요한 코드를 늘려야될 수 있다.
추상 클래스 자체로는 인스턴스 생성이 불가하므로 반드시 상속이 필요한 구조에서만 사용을 해야된다.
마지막으로 이 Abstract의 최종 목적은 무엇일까?
하위 클래스에게 일정한 메소드 구현을 강제하여 시스템 전체의 일관성을 유지하고 표준화된 개발 환경을 구성하여 전체적인 설계의 완성도와 일관성 확보를 통해 코드 전반적인 일관성 및 유지 관리의 효율성을 높이는 것이 abstract의 사용 의의가 된다.


Interface란, class들이 구현을 해야하는 동작, "기능의 명세"를 지정하는 추상 자료형이다. 구현 없이 메소드의 선언만 존재하는 껍데기라고 생각하면 편리하다. 실제 동작은 이를 구현하는 클래스에서 완성이 된다. 인터페이스 특징 중에서는 다중 상속이 가능하다는 점이 있다. 다중 상속을 사용하여 여러 클래스를 유연하게 연결할 수 있다.
모든 메소드는 암묵적으로 public abstract를 포함하고 있고, 변수들은 public static final을 포함하고 있다.
인스턴스 생성은 불가능하며 반드시 클래스를 통한 구현(implements)이 되어야 한다.
주저리주저리 길게 설명을 하는 것보다 그림을 한 번 보고 이해하는게 빠를 수도 있다.

클래스의 구조가 다음 그림과 동일하다.
interface가 있는 class 끼리는 extends를 통해서 상속이 가능하다. 그러므로 class A,B,C,D는 모두 interface class이다. class E,F는 class B,C,D에서 implemnts를 통해서 interface의 구현을 담당하는 일반 클래스이다.
Interface class : A, B, C, D
일반 class : E, F
일반 클래스에서는 interface의 특징대로 여러 개의 interface를 implements를 할 수 있다.
class E : A, B, C, D
class F : A, C, D
를 클래스 내에서 구현이 가능하다.
이제 코드로 넘어가보자.
// 최상위 인터페이스
interface A {
void methodA();
}
// 인터페이스 B, C, D가 각각 A를 상속
interface B extends A {
void methodB();
}
interface C extends A {
void methodC();
}
interface D extends A {
void methodD();
}
// class E가 B, C 인터페이스를 implements (구현)
class E implements B, C, D {
@Override
public void methodA() {
System.out.println("E: methodA");
}
@Override
public void methodB() {
System.out.println("E: methodB");
}
@Override
public void methodC() {
System.out.println("E: methodC");
}
@Override
public void methodD() {
System.out.println("E: methodD");
}
}
// class F가 C, D 인터페이스를 implements (구현)
class F implements C, D {
@Override
public void methodA() {
System.out.println("F: methodA");
}
@Override
public void methodC() {
System.out.println("F: methodC");
}
@Override
public void methodD() {
System.out.println("F: methodD");
}
}
최상위 인터페이스인 class A는 class B,class C,class D에게 모두 상속을 진행하였기 때문에 class A 내부에 있는 method A는 class B,class C,class D 모두에 존재한다.

class B : Method A, Method B
class C : Method A, Method C
class D : Method A, Method D
이렇게 갖고 있게 된다. class E는 implements를 통해서 class B,C,D에 있는 내용을 구현해야하고, class F는 implements를 통하여 C,D에 있는 내용을 구현해야한다.

class E : Method A, Method B, Method C, Method D
class F : Method A, Method C, Method D
위의 내용에도 말을 했듯이 interface안에 있는 메소드는 암묵적으로 abstract를 따르고 있기 때문에, 구현 클래스에서 implements된 메소드는 모두 구현을 진행해야한다.
그럼 왜 Interface를 사용해야 될까?
제일 중요한 기능은 다형성이라는 것이다. 동일한 인터페이스를 구현한 클래스라면, 어떤 구현체이든 인터페이스 타입으로 통일해서 사용할 수 있어서 코드가 상당히 유연해진다. 이 구현체(모듈/컴포넌트)를 갈아끼우기가 쉬워서 시스템 변경이나 확장에 유리하기도 하다. 또한 다중 상속 효과도 다형성에 큰 이바지를 하고 유연성에도 큰 역할을 한다.
Interface의 장점이 뭐길래?
인터페이스를 표준으로 두어서 팀원들이 서로 구현체만 만들면 되니, 동시에 개발이 가능하고 협업에 유리하다.
인터페이스를 사이에 두고 구현체를 분리하기 때문에, 각각의 수정 또는 확장이 상대적으로 자유로워 느슨한 결합 구조(Lossely Coupled) 구조가 형성된다.
서로 전혀 관계없는 클래스들에게 "공통 인터페이스" 하나를 구현하도록 해서, 특정 메소드 이름만 동일하게 구현하도록 만들 수 가 있다.
프로그램에서 객체의 실제 타입에 상관없이 동일한 방법으로 동작을 호출 할 수 있다.
일관된 개발 경험과 코드 표준화를 도울 수 있다.
장점이 엄청 많아 보이는데 무조건 써야되는거 아니야? 라고 생각한 당신. 물론 단점도 존재한다.
Abstract를 따르기 때문에 구현의 강제성을 띄고 있고 코드 중복의 가능성이 존재한다.
그리고 abstract의 단점처럼 중복 구현 로직이 발생하기 때문에 코드 중복 문제가 제기된다.
그리고 상위 인터페이스의 변경이 된다면 이를 구현한 모든 구현체들에게 영향이 가므로 대규모 리팩토링이 필요해진다.
마지막으로 과도한 사용을 하면 오히려 복잡성이 늘어난다는 단점이 존재한다.
Interface의 최종 목적은...
"규격(약속, 명세)"를 제공하여 유연하고 확장성이 높은 설계, 느슨한 결함, 코드 표준화, 분업 개발, 다형성 극대화를 목표로 사용을 하고 있다. 이를 잘 활용하면, 교체가 용이하고 테스트가 수월해지며, 성장과 유지보수가 효율적인 시스템으로 구성을 할 수 있다.



'멀티캠퍼스' 카테고리의 다른 글
| Servlet MVC 실습 코드 리뷰 (0) | 2025.09.01 |
|---|---|
| 서블릿 기초 (1) | 2025.08.25 |
| 데이터베이스 Index (1) | 2025.08.19 |
| 데이터베이스 (DDL) (2) | 2025.08.12 |
| UML(Unified Modeling Language)과 클래스 다이어그램(Class Diagram) (2) | 2025.08.06 |