미새문지

SOLID 원칙 본문

개발 TIL

SOLID 원칙

문미새 2025. 1. 6. 00:15
728x90

SOLID

SOLID는 객체지향 프로그래밍(OOP)에서 유지보수성확장성을 높이기 위한 5가지 설계 원칙을 의미하며, 이 원칙들은 모듈화가 잘 되어 있고 재사용 가능성을 높이는 데 도움을 준다.

Single Responsibility Principle (SRP) - 단일 책임 원칙

  • 정의: 한 클래스는 한 책임만을 가져야 하고, 그 역할과 관련된 변경만 반영해야 한다.
  • 목적: 각 클래스가 명확한 역할을 가지도록 설계하여 코드 변경 시 다른 부분에 영향을 최소화
  • 예시:
// 잘못된 설계
class UserManager {
    createUser() { /* 사용자 생성 */ }
    validateUser() { /* 사용자 검증 */ }
    sendEmail() { /* 이메일 전송 */ }
}

// 개선된 설계: 각 책임을 분리
class UserCreator {
    createUser() { /* 사용자 생성 */ }
}
class UserValidator {
    validateUser() { /* 사용자 검증 */ }
}
class EmailSender {
    sendEmail() { /* 이메일 전송 */ }
}

 

 

Open/Closed Principle (OCP) - 개방/폐쇄 원칙

  • 정의: 클래스, 모듈 등의 소프트웨어 요소는 확장에는 열려 있고, 수정에는 닫혀 있어야 한다.
  • 목적: 기존 코드를 변경하지 않고 기능을 확장할 수 있도록 설계
  • 예시:
// 잘못된 설계: 기존 코드 변경 필요
class Payment {
    payWithCreditCard() { /* 신용카드 결제 */ }
    payWithPayPal() { /* PayPal 결제 */ }
}

// 개선된 설계: 인터페이스를 활용해 확장
interface PaymentMethod {
    pay(): void;
}
class CreditCardPayment implements PaymentMethod {
    pay() { /* 신용카드 결제 */ }
}
class PayPalPayment implements PaymentMethod {
    pay() { /* PayPal 결제 */ }
}
class Payment {
    processPayment(method: PaymentMethod) {
        method.pay();
    }
}

 

Liskov Substitution Principle (LSP) - 리스코프 치환 원칙

  • 정의: 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.
  • 목적: 다형성을 유지하여 코드의 예측 가능성을 높임
  • 예시:
// 잘못된 설계
class Rectangle {
    constructor(public width: number, public height: number) {}
    setWidth(width: number) { this.width = width; }
    setHeight(height: number) { this.height = height; }
    getArea() { return this.width * this.height; }
}
class Square extends Rectangle {
    setWidth(width: number) {
        this.width = width;
        this.height = width; // 정사각형 규칙 강제
    }
    setHeight(height: number) {
        this.height = height;
        this.width = height; // 정사각형 규칙 강제
    }
}

// 개선된 설계: 상속 대신 별도 설계
class Square {
    constructor(public size: number) {}
    getArea() { return this.size * this.size; }
}

 

 

Interface Segregation Principle (ISP) - 인터페이스 분리 원칙

  • 정의: 어떤 클래스가 다른 클래스에 종속될 때에는 가능한 최소한의 인터페이스만을 사용해야 한다.
  • 목적: 불필요한 의존성을 줄이고, 클라이언트별 맞춤형 인터페이스 제공
  • 예시:
// 잘못된 설계: 모든 메서드 구현 강제
interface Worker {
    work(): void;
    eat(): void;
}
class Robot implements Worker {
    work() { /* 작업 수행 */ }
    eat() { /* 불필요한 구현 */ throw new Error("로봇은 먹지 않습니다."); }
}

// 개선된 설계: 인터페이스 분리
interface Workable {
    work(): void;
}
interface Eatable {
    eat(): void;
}
class Robot implements Workable {
    work() { /* 작업 수행 */ }
}
class Human implements Workable, Eatable {
    work() { /* 작업 수행 */ }
    eat() { /* 식사 */ }
}

 

 

Dependency Inversion Principle (DIP) - 의존 역전 원칙

  • 정의: 프로그래머는 추상화에 의존해야지 구체화에 의존하면 안된다.
  • 목적: 모듈 간 결합도를 낮추고 유연한 설계
  • 예시:
// 잘못된 설계: 고수준 모듈이 저수준 모듈에 의존
class MySQLDatabase {
    connect() { /* MySQL 연결 */ }
}
class DataManager {
    private database: MySQLDatabase;
    constructor() {
        this.database = new MySQLDatabase();
    }
    getData() { this.database.connect(); }
}

// 개선된 설계: 인터페이스를 통한 의존성 주입
interface Database {
    connect(): void;
}
class MySQLDatabase implements Database {
    connect() { /* MySQL 연결 */ }
}
class DataManager {
    private database: Database;
    constructor(database: Database) {
        this.database = database;
    }
    getData() { this.database.connect(); }
}

 

 

 

728x90

'개발 TIL' 카테고리의 다른 글

Reflow와 Repaint  (0) 2025.01.08
클로저(Closure)  (0) 2025.01.07
Typescript란?  (0) 2025.01.03
defee headline api 연동 테스트 및 잡담  (0) 2025.01.02
프로그래머스 가장 큰 수  (0) 2024.12.23