-
추상화(Abstraction)란?Design Pattern/객체지향 2024. 4. 12. 21:36반응형
객체지향 프로그래밍에서 추상화는 코드의 복잡성을 관리하고, 재사용성을 높이며, 유지 보수를 용이하게 하는 핵심 기술입니다. 본 블로그 게시글에서는 추상화의 개념을 이해하고, Java와 Go 언어에서의 구현 방법을 비교하여, 왜 추상화가 중요한지에 대해 자세히 설명하겠습니다.
추상화란 무엇인가?
추상화는 복잡한 현실 세계를 단순화하여 프로그램 내에서 이해하고 사용하기 쉽게 만드는 과정입니다. 이를 통해 개발자는 불필요한 세부 정보를 숨기고 중요한 정보만을 강조하여, 프로그램 간의 상호 작용을 개선할 수 있습니다. 추상화는 프로그래밍에서 모듈성을 높이고, 오류 가능성을 줄이며, 팀 작업을 용이하게 합니다.
Java에서의 추상화 - 초급
Java에서는 추상화를 abstract 클래스와 interface를 통해 구현합니다. 추상 클래스는 하나 이상의 추상 메소드를 포함할 수 있으며, 이를 상속받는 클래스에서 반드시 구현해야 합니다. 인터페이스는 모든 메소드가 추상 메소드인 형태로, 다중 상속의 이점을 제공합니다.
abstract class Animal { abstract void eat(); } class Dog extends Animal { void eat() { System.out.println("Dog is eating."); } } interface Movable { void move(); } class Car implements Movable { public void move() { System.out.println("Car is moving."); } }
Go에서의 추상화 - 초급
Go 언어는 인터페이스를 통해 추상화를 제공합니다. Go의 인터페이스는 메소드 시그니처의 집합으로, 어떠한 명시적 선언 없이도 어떤 타입이든 인터페이스를 '구현'할 수 있습니다. 이는 Java와 달리, 타입 시스템이 유연하면서도 강력한 다형성을 지원합니다.
type Animal interface { Eat() } type Dog struct{} func (d Dog) Eat() { fmt.Println("Dog is eating.") } type Movable interface { Move() } type Car struct{} func (c Car) Move() { fmt.Println("Car is moving.") }
Java에서의 추상화 - 중급
문제 상황: 여러 유형의 결제 방식(신용카드, PayPal, 비트코인)을 지원하는 전자상거래 시스템을 설계해야 합니다.
해결 방법: PaymentProcessor라는 추상 클래스를 만들어, 각 결제 방식의 공통 로직을 정의하고, 각 결제 방식에 특화된 로직을 서브 클래스에서 구현하게 합니다.
abstract class PaymentProcessor { protected double amount; public PaymentProcessor(double amount) { this.amount = amount; } abstract boolean processPayment(); protected void logTransaction() { System.out.println("Transaction for " + amount + " processed."); } } class CreditCardProcessor extends PaymentProcessor { private String cardNumber; public CreditCardProcessor(double amount, String cardNumber) { super(amount); this.cardNumber = cardNumber; } @Override public boolean processPayment() { System.out.println("Processing credit card payment for " + amount); // 로직 구현 logTransaction(); return true; } } class PayPalProcessor extends PaymentProcessor { private String emailId; public PayPalProcessor(double amount, String emailId) { super(amount); this.emailId = emailId; } @Override public boolean processPayment() { System.out.println("Processing PayPal payment for " + amount); // 로직 구현 logTransaction(); return true; } }
Go에서의 추상화 - 중급
문제 상황: 같은 전자상거래 시스템을 Go 언어로 구현하고, 다양한 결제 방식의 처리를 일관되게 관리하고자 합니다.
해결 방법: 인터페이스를 사용하여 결제 처리기를 정의하고, 각 결제 방식에 맞게 구조체와 메소드를 구현합니다.
type PaymentProcessor interface { ProcessPayment() bool LogTransaction() } type CreditCardProcessor struct { Amount float64 CardNumber string } func (ccp *CreditCardProcessor) ProcessPayment() bool { fmt.Printf("Processing credit card payment for %v\n", ccp.Amount) // 로직 구현 ccp.LogTransaction() return true } func (ccp *CreditCardProcessor) LogTransaction() { fmt.Println("Transaction for", ccp.Amount, "processed.") } type PayPalProcessor struct { Amount float64 EmailId string } func (pp *PayPalProcessor) ProcessPayment() bool { fmt.Printf("Processing PayPal payment for %v\n", pp.Amount) // 로직 구현 pp.LogTransaction() return true } func (pp *PayPalProcessor) LogTransaction() { fmt.Println("Transaction for", pp.Amount, "processed.") }
Java와 Go의 추상화 비교
Java의 추상화는 명시적이며, 클래스와 인터페이스를 통해 엄격하게 관리됩니다. 반면, Go는 더 유연하며, 인터페이스를 통해 암시적으로 추상화를 구현할 수 있습니다. Java에서는 다형성을 확장하기 위해 인터페이스를 명시적으로 구현해야 하지만, Go에서는 어떤 타입도 자동으로 인터페이스를 만족할 수 있습니다.
실제 사례
실제 프로젝트에서 추상화는 API, 라이브러리, 프레임워크 등의 설계에 핵심적으로 사용됩니다. 예를 들어, 네트워크 통신을 처리하는 라이브러리에서 다양한 프로토콜을 추상화하여, 사용자가 간단한 인터페이스를 통해 서로 다른 네트워크 프로토콜을 사용할 수 있도록 할 수 있습니다.
결론
추상화는 객체지향 프로그래밍의 중추적인 요소로, 복잡한 시스템을 효과적으로 설계하고 구현하는 데 필수적입니다. 언어 선택에 따라 추상화의 전략이 달라지므로, 프로젝트의 요구 사항에 맞추어 적합한 언어와 패러다임을 선택하는 것이 중요합니다.
반응형'Design Pattern > 객체지향' 카테고리의 다른 글
서브클래싱(Subclassing)과 서브타이핑(Subtyping)이란? (0) 2024.04.14 다형성(Polymorphism)이란? (1) 2024.04.12 상속(Inheritance)이란? (0) 2024.04.12 캡슐화(encapsulation)란? (0) 2024.04.10 인스턴스(Instance)란? (0) 2024.04.10