SOLID Principles 다시는 잊지 않을

발행: (2026년 4월 9일 AM 08:24 GMT+9)
5 분 소요
원문: Dev.to

Source: Dev.to

Source:

소개

SOLID는 깔끔하고 유지보수 가능하며 확장 가능한 코드를 작성하기 위한 설계 원칙 집합입니다. SOLID는 다음을 의미합니다:

단일 책임 원칙 (SRP)

클래스나 함수는 오직 하나의 책임만 가져야 합니다. 아래의 나쁜 예시에서는 CreateUser 함수가 이메일 관련 로직까지 처리하고 있습니다.

나쁜 예시

public class UserService {
    public void CreateUser(string email) {
        var user = new User(email);
        _repository.Save(user);

        var smtpClient = new SmtpClient("smtp.company.com");
        var message = new MailMessage(
            "no-reply@myapp.com", email, "Welcome!",
            "Your account was created successfully."
        );
        smtpClient.Send(message);
    }
}

좋은 예시

public class UserService {
    public void CreateUser(string email) {
        var user = new User(email);
        _repository.Save(user);

        _emailService.SendWelcome(email);
    }
}

개방/폐쇄 원칙 (OCP)

코드는 확장에는 열려 있어야 하지만 수정에는 닫혀 있어야 합니다. 기존 코드를 변경하지 않고도 새로운 동작을 추가할 수 있어야 합니다.

나쁜 예시

public class DiscountService {
    public double Calculate(string type) {
        if (type == "VIP") return 0.2;
        if (type == "Regular") return 0.1;
        if (type == "Employee") return 0.3;
        return 0;
    }
}

좋은 예시

public interface IDiscount {
    double Calculate();
}

public class VipDiscount : IDiscount {
    public double Calculate() => 0.2;
}

public class RegularDiscount : IDiscount {
    public double Calculate() => 0.1;
}

public class DiscountService {
    public double Calculate(IDiscount discount) {
        return discount.Calculate();
    }
}

리스코프 치환 원칙 (LSP)

서브타입은 기반 타입을 대체할 수 있어야 하며, 시스템을 깨뜨리지 않아야 합니다. 서브클래스는 기본 클래스의 기대 동작을 변경해서는 안 됩니다.

나쁜 예시

public class Bird {
    public virtual void Fly() { }
}

public class Penguin : Bird {
    public override void Fly() {
        throw new Exception("Penguins can't fly");
    }
}

Bird bird = new Penguin();
bird.Fly(); // throws exception

좋은 예시

public abstract class Bird { }

public interface IFlyingBird {
    void Fly();
}

public class Eagle : Bird, IFlyingBird {
    public void Fly() { }
}

public class Penguin : Bird { }

인터페이스 분리 원칙 (ISP)

클라이언트는 사용하지 않는 메서드에 의존해서는 안 됩니다. 인터페이스는 세분화되어 구현 클래스가 실제로 필요로 하는 동작만 제공하도록 해야 합니다.

나쁜 예시

public interface IWorker {
    void Work();
    void Eat();
}

public class Robot : IWorker {
    public void Work() { }

    public void Eat() {
        // forced to implement this method even though it doesn't use it
    }
}

좋은 예시

public interface IWorkable {
    void Work();
}

public interface IEatable {
    void Eat();
}

public class Human : IWorkable, IEatable {
    public void Work() { }
    public void Eat() { }
}

public class Robot : IWorkable {
    public void Work() { }
}

의존성 역전 원칙 (DIP)

고수준 모듈은 저수준 모듈에 의존해서는 안 되며, 둘 다 추상화에 의존해야 합니다. 다시 말해, 구현이 아닌 추상화에 의존해야 합니다.

나쁜 예시

public class UserService {
    private EmailService _emailService = new EmailService();

    public void CreateUser(string email) {
        // logic
        _emailService.Send(email);
    }
}

좋은 예시

public interface IEmailService {
    void Send(string email);
}

public class EmailService : IEmailService {
    public void Send(string email) { }
}

public class UserService {
    private readonly IEmailService _emailService;

    public UserService(IEmailService emailService) {
        _emailService = emailService;
    }

I’m happy to help translate the passage for you, but I don’t see a Source line in the message you provided. Could you please share the full text (including the “> Source: …” line) that you’d like translated? Once I have that, I’ll keep the source line unchanged and translate the rest into Korean while preserving the original formatting.

0 조회
Back to Blog

관련 글

더 보기 »

결합도와 SRP에 대한 요약

클래스가 응집된다는 것은 무엇인가? 응집된 클래스는 오직 하나의 책임만을 갖는 클래스이다. 응집된 클래스는 더 작고, 더 조직적이며, 유지보수가 쉽고 재사용 가능하다.

생성자란 무엇인가?

소개 JavaScript에서 constructor는 객체를 생성하고 초기화하는 특수한 function 또는 method입니다. 유사한 ...