SOLID 원칙과 프론트엔드
SOLID는 소프트웨어 설계의 다섯 가지 원칙 — 단일 책임 원칙(SRP), 개방-폐쇄 원칙(OCP), 리스코프 치환 원칙(LSP), 인터페이스 분리 원칙(ISP), 의존 역전 원칙(DIP) — 의 앞글자를 딴 약어다. 원래 클래스 기반 객체지향 설계를 위해 정리된 원칙이지만, 컴포넌트·훅·서비스 단위로 구성되는 프론트엔드 개발에도 동일한 사고방식을 적용할 수 있다. 다섯 원칙 모두 궁극적으로는 코드의 재사용성·유연성·확장성을 높이고, 한 부분을 변경했을 때 관련 없는 다른 부분에 의도치 않은 영향이 가지 않도록 하는 것을 목표로 한다.
SRP(단일 책임 원칙)는 컴포넌트가 하나의 책임만 지도록 설계하는 원칙이다. 다만 이를 "책임 = 하나의 동작"으로 오해해 컴포넌트를 지나치게 잘게 쪼개면 오히려 전체 로직 파악이 어려워지고 개발 공수만 늘어난다. 순수 함수 수준이 아니라면 SRP는 "요구 사항을 전달하는 책무 단위"로 컴포넌트를 나누는 기준으로 이해하는 편이 실무적이다. 예를 들어 로그인 폼 컴포넌트에 "비밀번호 찾기" 기능을 추가할 때, 기존 컴포넌트를 확장하기보다 별도 컴포넌트로 분리해 각자의 책임을 유지하게 한다. OCP(개방-폐쇄 원칙)는 기존 코드를 변경하지 않고도 기능을 확장할 수 있어야 한다는 원칙이다. 섹션 타입을 `if-else`로 분기해 컴포넌트를 렌더링하는 구조는 새 섹션 타입이 추가될 때마다 기존 코드를 수정해야 하므로 확장에 닫혀 있는 것이고, 데이터(섹션 정보)를 그대로 컴포넌트에 전달하는 구조로 바꾸면 타입이 늘어나도 기존 코드를 건드릴 필요가 없어진다.
LSP(리스코프 치환 원칙)는 자식 컴포넌트(또는 파생 클래스)가 부모의 역할을 어떤 경고도 없이 완전히 대체할 수 있어야 한다는 원칙이다. 기본 버튼 컴포넌트를 상속받은 특수 버튼이 부모가 제공하는 동작 중 일부를 제거하거나 다르게 바꾼다면 LSP를 위반한 것이다. ISP(인터페이스 분리 원칙)는 컴포넌트가 실제로 사용하지 않는 props(인터페이스)에 의존하지 않도록, props를 필요한 만큼만 좁혀 설계해야 한다는 원칙이다. 텍스트만 렌더링하는 컴포넌트가 쓰지도 않는 `photo` props까지 받도록 설계하는 것은 ISP 위반의 예다. DIP(의존 역전 원칙)는 상위 모듈이 하위 모듈(예: 특정 API 서버를 직접 호출하는 로직)에 직접 의존하지 않고, 데이터 fetch 로직을 별도 서비스로 분리해 컴포넌트가 그 서비스(추상)에만 의존하게 하는 원칙이다. 이렇게 하면 API 서버 구현이 바뀌어도 서비스 계층만 수정하면 되고 컴포넌트는 영향받지 않는다.
핵심 내용
- SRP(단일 책임): 컴포넌트는 "요구 사항을 전달하는 책무 단위"로 분리 — 무조건적인 잘게 쪼개기는 지양
- OCP(개방-폐쇄): 조건 분기(`if-else`) 대신 데이터 기반 구조로 바꿔 확장에는 열려있고 변경에는 닫히게 설계
- LSP(리스코프 치환): 자식/파생 컴포넌트는 부모의 동작을 깨지 않고 완전히 대체 가능해야 함
- ISP(인터페이스 분리): 컴포넌트는 필요한 props만 받고 불필요한 props에 의존하지 않아야 함
- DIP(의존 역전): 데이터 fetch 등 구현 로직을 별도 서비스로 분리해 컴포넌트는 추상(서비스)에만 의존
- SOLID는 원래 클래스 설계 원칙이지만, 컴포넌트·훅 단위로 구성되는 프론트엔드 설계에도 동일한 사고방식으로 적용 가능
관련 개념
- React 컴포넌트 패턴 — Container/Presentational, Compound, HOC 등 SOLID 원칙을 구현하는 구체적 React 패턴
- 디자인 시스템 — 재사용 가능하고 확장 가능한 컴포넌트 설계라는 목표를 공유
- 테스트-코드-작성-전략 — 작은 책임 단위로 나뉜 함수·컴포넌트가 유닛 테스트를 용이하게 만드는 연결점
출처
- 프론트엔드와 SOLID 원칙 — 2024-02-27, UX Engineer 이야기