SOLID 가이드: 다섯 원칙을 암기하지 않고 쓰는 법
Dev
마지막 업데이트

SOLID 가이드: 다섯 원칙을 암기하지 않고 쓰는 법


SOLID는 자주 “외워야 하는 다섯 규칙”처럼 소개되는데, 바로 그 점 때문에 많은 입문자가 거리감을 느낍니다. 슬로건처럼 들리기 때문입니다. 하지만 원칙을 암기 대상이 아니라 반복되는 설계 고통에 대한 반응으로 보기 시작하면 훨씬 실용적으로 다가옵니다.

SOLID는 객체 지향 설계에서 책임, 변형, 계약, 의존성을 다루는 휴리스틱 묶음입니다. 순수성을 위한 규율이라기보다 변경 비용을 낮추기 위한 관찰 도구에 가깝습니다.

이 글에서는 아래 내용을 다룹니다.

  • SOLID가 실제로 무엇을 보호하려는지
  • 각 원칙을 실무적으로 이해하는 짧은 감각
  • 원칙을 너무 경직되게 써서 오히려 해치는 상황

핵심만 먼저 말하면 이렇습니다. 결제 서비스에서 하나의 OrderService 클래스가 주문 생성, 결제 처리, 이메일 발송, 재고 차감까지 전부 담당하고 있었는데, 결제 로직을 수정할 때마다 이메일 테스트가 깨지고 재고 테스트가 깨지는 상황이 반복됐습니다. SRP를 적용해서 4개 서비스로 분리하니 변경 영향 범위가 명확해지고, 배포 때 “이거 건드리면 저쪽도 깨지나?” 걱정이 사라졌습니다.

책임이 흐려지고, 계약이 거짓말하고, 의존성 방향이 뒤집히면 코드베이스는 금방 비싸집니다. SOLID는 그 지점을 더 빨리 보게 해 줍니다.

SOLID란 무엇인가

SOLID는 다섯 설계 원칙의 머리글자입니다.

  • S: Single Responsibility Principle
  • O: Open/Closed Principle
  • L: Liskov Substitution Principle
  • I: Interface Segregation Principle
  • D: Dependency Inversion Principle

이름을 외우는 것보다 더 중요한 것은, 각 원칙이 어떤 설계 실패를 막으려는지 이해하는 것입니다.

SOLID는 어떤 문제를 풀려고 하는가

코드베이스가 커질수록 반복되는 고통이 있습니다.

  • 한 클래스가 너무 많은 일을 맡는다
  • 새 변형이 생길 때마다 같은 hotspot을 수정한다
  • 하위 타입이 안전한 대체물이 되지 못한다
  • 인터페이스가 비대해져서 어색해진다
  • 핵심 로직이 인프라 세부사항에 끌려다닌다

SOLID는 이런 문제를 더 빨리 알아차리게 해 주는 언어입니다.

아키텍처를 자동으로 설계해 주는 것은 아니지만, 설계가 비싸지기 전에 더 좋은 질문을 하게 도와줍니다.

각 원칙을 실무적으로 이해하는 법

SRP: 책임 경계를 지킨다

SRP는 한 단위가 너무 많은 서로 다른 이유로 바뀌고 있지 않은지를 봅니다.

막아 주는 문제는 아래와 같습니다.

  • 뒤섞인 책임
  • God class
  • 무관한 의존성이 너무 많은 테스트

가격 정책, 저장, 이메일, 로깅이 한 클래스에서 같이 변한다면 보통 SRP부터 흔들리고 있는 것입니다.

OCP: 안정된 코어를 반복 수정에서 지킨다

OCP는 반복되는 변형을 같은 코어 수정이 아니라 확장으로 처리할 수 있는지를 봅니다.

막아 주는 문제는 아래와 같습니다.

  • 계속 커지는 조건문
  • 안정된 코드의 회귀 위험
  • 모든 새 변형을 흡수하는 hotspot

새 규칙이 들어올 때마다 같은 함수에 분기가 하나씩 늘어난다면 OCP를 떠올릴 시점입니다.

LSP: 계약의 진실성을 지킨다

LSP는 하위 타입이 정말로 상위 타입의 안전한 대체물인지 묻습니다.

막아 주는 문제는 아래와 같습니다.

  • 컴파일은 되지만 행동이 깨지는 상속
  • 하위 타입별 방어 분기
  • 공유된 것처럼 보이지만 실제로는 다른 계약

호출자가 특정 하위 타입만 따로 처리해야 한다면 LSP가 흔들리고 있는 경우가 많습니다.

ISP: 클라이언트를 비대한 인터페이스에서 지킨다

ISP는 클라이언트가 실제로 쓰지 않는 메서드에 의존하고 있지 않은지를 봅니다.

막아 주는 문제는 아래와 같습니다.

  • 비대한 인터페이스
  • not supported 남발
  • 관련 없는 호출자에게 새어 나가는 변경

하나의 인터페이스가 여러 역할을 동시에 흉내 내고 있다면 ISP 이슈일 가능성이 큽니다.

DIP: 핵심 로직을 구체 세부사항에서 지킨다

DIP는 상위 수준 로직이 저수준 구현 선택에 너무 직접적으로 묶여 있지 않은지를 봅니다.

막아 주는 문제는 아래와 같습니다.

  • SDK나 벤더 세부사항에 묶인 핵심 서비스
  • 어색한 테스트 경계
  • 비즈니스 로직 모양까지 바꾸는 인프라

DB나 메일 공급자가 바뀌었는데 유스케이스 코드부터 흔들린다면 보통 DIP가 약한 상태입니다.

원칙들은 어떻게 함께 작동하는가

SOLID는 다섯 개의 낱말보다, 연결된 시스템으로 볼 때 훨씬 더 유용합니다.

흔한 흐름은 아래와 같습니다.

  • SRP가 누가 무엇을 가져야 하는지 정리해 주고
  • OCP가 변형을 어디서 안전하게 추가할지 보게 하고
  • LSP가 하위 타입 설계가 정직한지 확인해 주고
  • ISP가 계약을 클라이언트 역할 기준으로 다듬고
  • DIP가 의존성 방향을 건강하게 유지하게 만듭니다

그래서 이 원칙들은 서로를 받쳐 줍니다. 경계가 좋아질수록 계약도 좋아지고, 계약이 좋아질수록 의존성 방향도 건강해집니다.

언제 SOLID가 과용되는가

이 부분도 원칙만큼 중요합니다.

SOLID는 기계적으로 적용하면 오히려 해로울 수 있습니다.

  • 실제 변형도 없는데 인터페이스를 먼저 만들고
  • 가상의 미래를 위해 확장 지점을 미리 깔고
  • 클래스를 너무 잘게 쪼개서 설계를 소음으로 만들고
  • 도메인을 선명하게 하는 대신 구체 라이브러리를 얇게 감싼 추상화만 늘어나는 경우

목표는 “SOLID해 보이는 코드”가 아니라, 실제 설계 고통을 줄이되 의식적인 구조 남발로 대체하지 않는 것입니다.

자주 하는 오해

1. SOLID를 따르면 자동으로 좋은 코드가 된다

그렇지는 않습니다. 원칙 용어는 맞아도 실제로는 읽기 어려운 과설계가 될 수 있습니다.

2. SOLID는 인터페이스와 레이어를 많이 만드는 것이다

때로는 추상화가 맞지만, 때로는 더 중요한 것이 ownership을 선명하게 하고 경계를 단순하게 만드는 것입니다.

3. SOLID는 객체 지향 언어에서만 의미 있다

이름은 객체 지향에서 왔지만, 책임·계약·의존성 방향에 대한 고민 자체는 훨씬 넓은 범위에 적용됩니다.

4. 모든 영역에 다섯 원칙을 똑같이 강하게 적용해야 한다

코드베이스 모든 부분이 같은 압력을 받지는 않습니다. 어떤 곳은 SRP/DIP가 절실하고, 어떤 단순한 영역은 무거운 추상화가 전혀 필요 없을 수 있습니다.

SOLID를 말하기 전에 보는 체크리스트

아래 질문이 도움이 됩니다.

  • 지금 정확히 어떤 설계 고통이 있는가
  • 어떤 변경이 특히 비싼가
  • 문제의 핵심이 책임, 변형, 계약 모양, 의존성 방향 중 어디에 있는가
  • 제안하는 추상화가 코드를 더 선명하게 만드는가, 아니면 의식만 늘리는가

이 질문을 먼저 거치면 원칙이 훨씬 현실적인 도구가 됩니다.

FAQ

Q. 입문자는 어떤 원칙부터 보는 게 좋나요?

SRPDIP가 가장 실전적인 출발점인 경우가 많습니다. 책임과 의존성 방향은 실제 코드에서 가장 빨리 체감되기 때문입니다.

Q. 실무에서도 정말 쓰이나요?

그렇습니다. 팀이 이름을 직접 말하지 않아도 많은 설계 논의가 결국 같은 관심사를 다루고 있습니다.

Q. 작은 프로젝트도 SOLID가 필요한가요?

공식 체크리스트처럼 다 적용할 필요는 없습니다. 다만 작은 코드도 책임과 의존성 경계가 선명할수록 유지가 쉬워집니다.

먼저 읽어볼 가이드

검색 유입이 많은 핵심 글부터 이어서 보세요.

광고