본문 바로가기
language/java

객체지향 설계 원칙 SOLID 완벽 이해하기

by 죄니안죄니 2026. 5. 22.
반응형

객체지향 설계 원칙 SOLID 완벽 이해하기

Java 객체지향 프로그래밍(OOP)을 공부하다 보면 반드시 등장하는 개념이 바로:

SOLID 원칙

입니다.

실무에서도:

  • Spring
  • 클린 아키텍처
  • DDD
  • 대규모 백엔드 설계

전부 SOLID 철학 위에서 설계됩니다.

초보 시절에는 보통:

SRP
OCP
LSP
ISP
DIP
 

약어만 외우고 넘어가기 쉽습니다.

하지만 실제로 SOLID는 단순 암기용 이론이 아니라:

  • 유지보수 쉬운 구조
  • 변경에 강한 설계
  • 유연한 객체 구조
  • 확장 가능한 시스템

을 만들기 위한 핵심 설계 원칙입니다.

이번 글에서는:

  • SOLID가 왜 등장했는가
  • 각 원칙의 진짜 의미
  • 실무 사례
  • Spring과의 연결
  • 잘못 이해하기 쉬운 부분

까지 정리해보겠습니다.


1. SOLID란?

SOLID는 객체지향 설계 원칙 5가지를 정리한 개념입니다.

약어의미
S SRP (단일 책임 원칙)
O OCP (개방 폐쇄 원칙)
L LSP (리스코프 치환 원칙)
I ISP (인터페이스 분리 원칙)
D DIP (의존 역전 원칙)

2. 왜 SOLID가 중요할까?

대규모 시스템에서는:

  • 기능 계속 추가
  • 요구사항 계속 변경
  • 개발자 여러 명 협업

상황이 반복됩니다.

이때 설계가 좋지 않으면:

기능 하나 수정
↓
전체 코드 영향
↓
버그 폭발
 

발생 가능.

SOLID는 이를 줄이기 위한 설계 원칙입니다.


3. SRP (Single Responsibility Principle)

단일 책임 원칙

의미:

클래스는 하나의 책임만 가져야 한다


4. SRP 안 좋은 예

 
class UserService {

    void login() {}

    void sendEmail() {}

    void saveToDB() {}

    void createPdf() {}
}
 

문제:

  • 책임 과도
  • 변경 이유 너무 많음
  • 유지보수 어려움

5. SRP 좋은 예

UserService
MailService
PdfService
UserRepository
 

책임 분리.


6. SRP 핵심

중요한 건:

메서드 개수
 

가 아니라:

변경 이유가 하나인가?
 

입니다.


7. 실무에서 SRP 매우 중요

대표 사례:

역할분리
Controller 요청 처리
Service 비즈니스 로직
Repository DB 접근

Spring 구조 자체가 SRP 기반.


8. OCP (Open Closed Principle)

개방 폐쇄 원칙

의미:

확장에는 열려 있고 수정에는 닫혀 있어야 한다


9. OCP 안 좋은 예

 
if (type.equals("CARD")) {

} else if (type.equals("KAKAO")) {

}
 

새 결제 방식 추가 시:

기존 코드 수정 필요
 

10. OCP 좋은 예

 
interface Payment {

    void pay();
}
 

구현체 추가:

 
class CardPayment implements Payment
class KakaoPayment implements Payment
 

새 기능 추가 시:

기존 코드 수정 최소화
 

가능.


11. OCP 핵심 기술

핵심은:

  • 다형성
  • 인터페이스
  • 추상화

입니다.

Spring DI도 사실상 OCP 구현 구조.


12. LSP (Liskov Substitution Principle)

리스코프 치환 원칙

의미:

부모 타입 자리에 자식 객체가 문제 없이 들어갈 수 있어야 한다


13. LSP 안 좋은 예

 
class Bird {
    void fly() {}
}

class Penguin extends Bird {

    @Override
    void fly() {
        throw new UnsupportedOperationException();
    }
}
 

문제:

Penguin은 사실 fly 불가능
 

즉:

is-a 관계 깨짐
 

14. LSP 핵심

상속은 단순 코드 재사용이 아니라:

타입 호환성 보장
 

이 핵심.


15. 실무에서 LSP 중요 사례

예시:

 
List list = new ArrayList();
 

→ LinkedList로 교체해도 동작 동일해야 함.


16. ISP (Interface Segregation Principle)

인터페이스 분리 원칙

의미:

클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안 된다


17. ISP 안 좋은 예

 
interface Worker {

    void work();
    void eat();
    void sleep();
}
 

Robot도 구현해야 한다면?

불필요 메서드 강제
 

문제 발생.


18. ISP 좋은 예

 
interface Workable {
    void work();
}

interface Eatable {
    void eat();
}
 

필요한 인터페이스만 구현.


19. ISP 핵심

핵심은:

작고 명확한 인터페이스
 

입니다.

실무에서 거대한 인터페이스는 유지보수 어려움.


20. DIP (Dependency Inversion Principle)

의존 역전 원칙

의미:

구현체가 아니라 추상화에 의존해야 한다


21. DIP 안 좋은 예

 
class UserService {

    private MySqlRepository repository =
        new MySqlRepository();
}
 

문제:

구현체 강결합
 

22. DIP 좋은 예

 
interface UserRepository {

}
 

 
class UserService {

    private UserRepository repository;
}
 

즉:

구현이 아니라 인터페이스 의존
 

구조.


23. Spring과 DIP

Spring 핵심 철학 중 하나.

예시:

 
@Autowired
UserRepository repository;
 

실제 구현체는:

  • JpaRepository
  • MyBatisRepository
  • MemoryRepository

교체 가능.


24. SOLID와 Spring 관계

Spring은 사실상:

SOLID 실현 프레임워크

에 가깝습니다.

대표 연결:

SOLIDSpring
SRP Layer 분리
OCP DI + 다형성
DIP Interface 기반
ISP 작은 Bean 역할
LSP 구현체 교체 가능

25. SOLID를 잘못 이해하는 경우

초보자가 자주 하는 실수:

“클래스를 무조건 많이 쪼개야 한다”
 

아닙니다.

핵심은:

변경에 강한 구조
 

입니다.


26. 인터페이스 남발 문제

예시:

UserService
UserServiceImpl
 

구현체 하나뿐인데 무조건 인터페이스 생성.

작은 프로젝트에서는 오히려 복잡도 증가 가능.


27. 실무에서 중요한 건 균형

너무 과한 추상화는:

  • 코드 복잡도 증가
  • 이해 어려움
  • 유지보수 비용 증가

가능.


28. 좋은 SOLID 적용 기준

좋은 설계는:

  • 변경 가능성 높은 부분 분리
  • 구현체 교체 가능
  • 책임 명확
  • 결합도 낮음

특징을 가집니다.


29. SOLID의 진짜 목적

SOLID 핵심 목적은:

유지보수 쉬운 시스템
 

입니다.

즉:

  • 변경 영향 최소화
  • 확장 쉬운 구조
  • 테스트 쉬운 구조

를 만드는 것이 핵심.


30. 정리

SOLID는 단순 암기용 이론이 아닙니다.

실제로는:

  • Spring 설계
  • 객체지향 구조
  • DI
  • 다형성
  • 유지보수성

전체를 지탱하는 핵심 설계 원칙입니다.

특히 실무에서는:

  • 책임 분리(SRP)
  • 인터페이스 기반 설계(DIP)
  • 확장 가능한 구조(OCP)

를 이해하는 것이 매우 중요합니다.

다음 글에서는:

불변 객체(Immutable Object) 설계

를 Thread-safe와 JVM 메모리 관점까지 포함해서 정리해보겠습니다.

반응형

댓글