dev-sohee 님의 블로그
인터페이스와 추상 클래스, 둘 중 뭘 써야 하는거지? 본문
혹시 개발자가 코드를 짜는 모습을 상상해본 적이 있으신가요?
개발을 경험해본 적이 없는 사람이라면 머릿속에 있는 것들을 타자를 치면서 바로 실현시키는 개발자의 모습을 상상하실 수도 있습니다. 하지만 실제 개발 과정에서는 저렇게 결과물을 뚝딱 만들어낼 수 없습니다.
어떤 시스템을 개발하든 간에 일반적인 절차라는 것이 있습니다. 일반적인 절차는 다음과 같습니다.
1. 분석
- 시스템을 만들어 달라고 한 사람들에게 어떻게 개발하기를 원하는지 물어보며 요구사항을 분석하는 단계입니다.
2. 설계
- 분석 단계에서 만든 대략적인 그림을 프로그램으로 만들 수 있도록 설계하는 단계입니다. 이 단계에서 어떤 클래스, 어떤 메서드, 어떤 변수를 만들 것인지 등의 세부적인 것들을 정리합니다.
예시) 시퀀스다이어그램, ERD, 클래스 다이어그램, 서버구조도 등
3. 개발 및 테스트
- 설계에서 만들기로 한 것들을 실제로 개발하는 단계입니다.
4. 시스템 릴리즈
- 시스템을 사용자에게 제공하는 단계입니다. 시스템을 오픈한 후에는 운영/유지보수 단계를 거치며 문제점을 보완해 나갑니다.
이제 본론으로 들어가서, 인터페이스와 추상 크래스에 대한 이야기를 시작해보겠습니다.
설계를 할 때 프로그램을 어떻게 만들 것인지에 대한 정리를 문서로만 작성해 두면 나중에 관련 내용을 수정했을 때 문서도 수정해야 하므로 2중, 3중의 일이 됩니다. 그래서, 설계 단계에서 인터페이스와 추상 클래스라는 것을 만들어 두면 개발할 때 메서드의 이름을 어떻게 할지, 매개 변수를 어떻게 할지 일일이 고민하지 않아도 됩니다.
즉, 인터페이스와 추상 클래스를 사용하는 이유는 다음과 같이 정리할 수 있습니다.
- 설계 시 선언해 두면 개발할 때 기능을 구현하는 데에만 집중할 수 있다.
- 개발자의 역량에 따른 메서드의 이름과 매개변수 선언의 격차를 줄일 수 있다.
- 선언과 구현을 구분하여 설계 단계의 산출물과 개발 단계의 산출물이 효율적으로 관리됩니다.
이제 인터페이스와 추상 클래스를 어떻게 사용하는지, 둘은 뭐가 다른 것인지에 대해 알아보겠습니다.
# 인터페이스
인터페이스 사용 방법
1. class로 시작하지 않고 반드시 interface로 시작해야 합니다.
2. interface 내부에 선언된 메서드들은 몸통이 있으면 안됩니다. (즉, 메서드 선언 이후에 중괄호를 열고 닫아서는 안됩니다.)
3. 이후 만들어져 있는 인터페이스를 적용할 때는 implements라는 예약어를 써서 인터페이스들을 나열하면 됩니다.
인터페이스의 장점
1. 다중 상속 가능: 클래스는 여러 개의 인터페이스를 구현할 수 있습니다. 이는 다양한 독립적인 기능을 클래스에 추가할 수 있는 유연성을 제공합니다. (즉, implements 뒤에 여러 개의 인터페이스가 존재할 수 있습니다.)
2. 느슨한 결합: 인터페이스는 클래스와의 결합도를 낮추어 줍니다. 클래스가 인터페이스를 구현함으로써 인터페이스가 요구하는 기능을 제공할 수 있지만, 클래스의 내부 구현은 자유롭게 변경할 수 있습니다. 이는 유지보수성을 높이고 코드의 유연성을 증가시킵니다.
3. 다형성 제공: 인터페이스는 다형성의 핵심을 구현합니다. 여러 클래스가 동일한 인터페이스를 구현하면 클라이언트 코드는 이들을 동일한 방식으로 다룰 수 있습니다. 예를 들어, List 인터페이스를 구현한 ArrayList와 LinkedList는 동일한 메서드들을 제공하므로 클라이언트 코드는 두 클래스를 동일하게 다룰 수 있습니다.
인터페이스의 단점
1. 구현 강제: 인터페이스를 구현하는 클래스는 인터페이스에 정의된 모든 메서드를 구현해야 합니다. 이는 클래스가 인터페이스를 구현할 때 추가적인 구현 부담을 줄 수 있습니다.
2. 제한된 기능: 인터페이스는 추상 메서드만을 포함하며, 메서드의 구현을 포함할 수 없습니다. 따라서 인터페이스만으로는 일부 기본 구현을 공유하기 어려울 수 있습니다.
# 추상 클래스
추상 클래스 사용 방법
1. class 선언시 class라는 예약어 앞에 abstract라는 예약어를 사용해야 합니다.
2. 추상 클래스 안에는 abstract로 선언된 메서드가 0개 이상이면 됩니다.
3. abstract로 선언한 메서드가 하나라도 있으면 그 클래스는 반드시 abstract으로 선언되야 합니다.
4. 인터페이스와 달리 몸통이 있는 메서드가 있어도 상관 없습니다.
5. 추상 클래스는 인터페이스와 달리 상속과 똑같은 extends라는 예약어를 사용하여 적용합니다.
추상클래스의 장점
1. 일반 메서드 포함 가능: 추상 클래스는 추상 메서드뿐만 아니라 구현된 메서드와 필드도 포함할 수 있습니다. 이는 클래스들 간의 공통된 코드를 재사용하고 확장하기 좋습니다. 예를 들어, 여러 동물 클래스가 추상 클래스 Animal을 상속하여 공통된 특성과 동작을 재사용할 수 있습니다.
2. 추가적인 기능 제공: 추상 클래스는 상속을 통해 추가적인 기능을 제공하고, 메서드의 구현을 필수로 하지 않고 선택적으로 오버라이드할 수 있습니다. 이는 클래스들 간의 강한 관계를 형성할 수 있습니다.
추상클래스의 단점
1. 단일 상속만 가능: 추상 클래스는 클래스이기 때문에 다중 상속이 불가능합니다. 따라서 단일 상속의 제약을 가집니다. (즉, extends 뒤에는 단 하나의 클래스만 존재할 수 있습니다.)
2. 강한 결합: 추상 클래스는 상속을 통해 강한 결합을 만들어 냅니다. 자식 클래스는 부모 추상 클래스의 구현을 직접적으로 공유하며 확장해야 합니다. 이는 클래스들 간의 강한 관계를 형성하는 데 도움이 될 수 있지만, 유연성 측면에서는 제한적일 수 있습니다.
좋은 소프트웨어 설계를 위해서는 결합도는 낮추고 응집도는 높이는 것이 바람직합니다. 결합도는 클래스(모듈)간의 상호 의존 정도로서 결합도가 낮으면 상호 의존성이 줄어들어 객체의 재사용이나 수정, 유지보수가 용이합니다. 응집도는 하나의 모듈 내부에 존재하는 구성 요소들의 기능적 관련성으로, 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정, 유지보수가 용이합니다.
여기까지 공부해보니 인터페이스와 추상 클래스는 비슷한 듯 다른 것 같습니다. 그렇다면 각각 언제 사용해야 하는 걸까요? 인터페이스를 사용하다 보면, 어떤 메서드는 미리 만들어 놓아도 전혀 문제가 없을 것 같은 경우가 생깁니다.
바로 이럴 때 추상 클래스를 사용하면 됩니다.
인터페이스와 추상 클래스는 코드의 재사용성과 확장성, 코드 응집도와 유지보수성을 높이는 데 아주 중요한 역할을 합니다. 다중상속을 허용하는 인터페이스는 유연한 설계와 독립적인 기능 추가를 지원하며, 단일 상속을 허용하는 추상 클래스는 공통된 구현을 제공하고 클래스들 간의 강한 결합을 형성합니다. 따라서 프로젝트의 요구사항과 설계 목적에 맞게 적절히 선택하여 사용하시면 됩니다.
'java' 카테고리의 다른 글
Java 8, Java 11, Java 17 뭐가 달라졌는지 알고 사용하자 (0) | 2024.07.28 |
---|---|
JVM의 청소부, GC(Garbage Collector) (0) | 2024.07.13 |
JVM의 부스터, JIT-Compiler (0) | 2024.07.13 |
자바의 두뇌 : JVM의 모든 것 (0) | 2024.07.06 |
JDK vs JRE (0) | 2024.06.22 |