-
C# 설계의 핵심: 인터페이스 vs 추상 클래스, 5분 만에 끝내는 완벽 비교개발/C# 2026. 1. 23. 12:05반응형
1. 핵심 개념: "무엇인가(Is-A)" vs "무엇을 할 수 있는가(Can-Do)"
가장 쉽게 이해하는 방법은 이 비유를 기억하는 겁니다.
- 추상 클래스 (Abstract Class): 정체성입니다. "이 클래스는 근본적으로 무엇인가?"를 정의합니다. (예: 사과, 바나나는 '과일'이다.)
- 인터페이스 (Interface): 능력입니다. "이 클래스가 어떤 기능을 할 수 있는가?"를 정의합니다. (예: 자동차, 비행기는 '이동할 수 있다'.)
2. 한눈에 보는 주요 차이점
구분 추상 클래스(Abstract Class) 인터페이스(Interface) 상속 단일 상속만 가능 (부모는 하나) 다중 상속 가능 (능력은 여러 개) 필드(변수) 변수(데이터)를 가질 수 있음 변수를 가질 수 없음 (상태 저장 불가) 목적 관련 있는 클래스들의 공통점을 묶을 때 관련 없는 클래스들에게 공통 기능을 줄 때 접근 제한자 public, private, protected 모두 가능 기본적으로 모두 public 3. 코드 예시
상황 1: 추상 클래스를 써야 할 때 (근본이 같을 때)
연구 중인 PCB 부품 탐지 프로젝트를 예로 들어볼게요. '저항', '커패시터'는 모두 근본적으로 **'전자부품'**이죠.
public abstract class ElectronicComponent { public string PartNumber { get; set; } // 공통 데이터 가질 수 있음 // 모든 부품은 전압을 체크하는 공통 로직이 있다고 가정 public void CheckVoltage() { Console.WriteLine($"{PartNumber} 전압 체크 중..."); } // 이름 출력 방식은 부품마다 다를 수 있으니 추상 메서드로! public abstract void PrintInfo(); }상황 2: 인터페이스를 써야 할 때 (능력을 부여할 때)
그런데 어떤 부품은 '로그'를 남길 수 있고, 어떤 부품은 '통신'을 할 수 있습니다. 이건 '근본'이라기보다 '추가 능력'에 가깝죠.
public interface ILoggable { void WriteLog(); // "로그를 남길 수 있는 능력을 부여함" } // 저항(Resistor)은 전자부품이면서 로그도 남길 수 있음 public class Resistor : ElectronicComponent, ILoggable { public override void PrintInfo() => Console.WriteLine("나는 저항입니다."); public void WriteLog() => Console.WriteLine("저항 로그 기록 완료"); }4. 언제 무엇을 쓸까?
제가 실무에서 결정하는 기준은 딱 이겁니다.
- "여러 클래스가 아주 밀접하게 연결되어 있고, 공통된 코드가 많다" -> 추상 클래스
- 부모 클래스에서 미리 코드를 짜두면 자식들이 편하게 쓸 수 있습니다.
- "서로 다른 클래스들이라도 특정 기능(메서드)만 똑같은 이름으로 구현하게 하고 싶다" -> 인터페이스
- 예를 들어, Save()라는 기능을 '기판 이미지'도 할 수 있고 '설정 파일'도 할 수 있다면 인터페이스가 정답입니다.
- "나중에 기능을 계속 추가할 것 같다" -> 인터페이스
- C#은 클래스 상속을 하나밖에 못 받기 때문에, 추상 클래스를 써버리면 나중에 다른 부모를 모실 수 없습니다. 반면 인터페이스는 언제든 덧붙일 수 있죠.
마무리하며
처음에는 인터페이스가 더 추상적이라 어렵게 느껴질 수 있습니다. 하지만 **"추상 클래스는 부모님께 물려받는 '유전자'고, 인터페이스는 내가 배워서 익히는 '자격증'이다"**라고 생각하면 훨씬 이해가 빠르실 거예요.
여러분의 프로젝트에서는 어떤 방식이 더 어울리나요? 지금 설계 중인 클래스 구조를 한 번 점검해 보세요!
반응형'개발 > C#' 카테고리의 다른 글
C# 비동기의 복병, TaskCanceledException 완벽 대처법 (타임아웃 해결) (0) 2026.01.26 C# 인터페이스를 활용한 의존성 주입(DI) 완벽 이해 (0) 2026.01.23 [C#] "파일을 찾을 수 없습니다" – FileNotFoundException, 경로의 함정 (1) 2026.01.22 [C#] Struct vs Class, 성능 차이 진짜 날까? (언제 무엇을 쓸지 정해드립니다) (0) 2026.01.20 C# foreach 돌리다 터지는 '열거 작업 수정' 에러, 해결 가이드Enumerable was modified (0) 2026.01.19