top of page

개발자라면 알아야 할 솔리드 (SOLID) 원칙. 제대로 알고 코딩을 하는가? 8분에 배워보자

개발자라면 꼭 알고 코딩을 해야 하는 원칙 중 하나가 이 SOLID (솔리드) 원칙입니다. 객체 지향 설계 5원칙이라고 불리고 있는 이 원칙은 디버깅이나 코드관리의 효율성, 그리고 나아가서는 버그를 줄일 수 있게 도와줍니다. 혹시 이 원칙을 모르고 코딩을 하신다면 쓰레기 코드를 만들고 계실 확률이 아주 높으므로 개발을 그만두는 것이 좋습니다. 개발도 학문입니다.

원칙은 어렵지만 좀 더 쉽게 배울 수 있도록 리액트 (React, JavaScript)를 이용한 예제로 설명을 해 봤습니다.


SOLID 원칙이란?

SOLID 원칙은 애플리케이션을 쉽게 재사용하고 (reusable), 관리를 하고 (maintainable), 확장을 하고 (scalable), 간단히 분해 할 수 있는 (loosely coupled) 다섯 가지 기본원칙으로 구성되어 있습니다. 이 다섯 가지 원칙은 다음과 같습니다:

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

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

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

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

  • Dependency Inversion Principle (의존 역전 원칙)

각각의 원칙을 React의 예제를 이용하여 알아보겠습니다. 프레임워크나 개발 언어는 달라도 콘셉트는 같습니다.



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

“하나의 모듈은 한 가지만 해야한다” - Wikipedia

단일 책임 원칙은 하나의 컴포넌트는 하나의 목표와 책임만 있어야 한다는 뜻입니다. 특정하나의 목표가 있고 책임만 있게 되면 다른 것과 연결되어 꼬이는 문제가 없어지죠. SRP 원칙을 따른다면 이해하기 쉽고, 정확하게 정리된 코드가 나오게 됩니다.

아래의 예제를 보겠습니다.

위의 예제에는 Products라는 컴포넌트가 여러가지 책임을 지면서 SRP 원칙을 무시하고 있습니다. 이 컴포넌트는 데이터를 가져와 map이라는 loop을 돌면서 UI를 렌더링 하고 있죠. 이렇게 만들어진 코드는 이해하고, 관리하고, 테스트하기가 어렵습니다.

대신에 아래와 같은 코드를 사용하여 SRP 원칙을 준수합니다:

Product라는 컴포넌트는 Product의 UI 렌더링이라는 하나의 역할을 맡게 되고 Products는 데이터를 불러와 Product애 전달하는 하나의 역할로 나뉘어 지게 됩니다. 이렇게 나누게 되면 각 컴포넌트는 하나만 하게 되죠. 각 컴포넌트마다 코드가 더 간단하여 쉽게 이해하고, 테스트와 관리가 쉬워집니다.



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

“소프트웨어의 개체들은 (클래스, 모듈, 함수 등등) 확장에는 개방이 되어야 하고 수정에는 폐쇠되어야 한다” - Wikipedia

개방-폐쇄 원칙에는 컴포넌트들이 (새 기능등의) 확장성에는 개방이 되어야하고 (기존 코드를 수정하는) 수정에는 폐쇄가 되어야 합니다. 이 원칙은 변화에 적응을 하고 모듈러화 되어 관리에 편하게 만들게 도와줍니다.

다음의 예제를 통하여 알아보겠습니다:

위의 예제는 Button이라는 기존 컴포넌트에 icon이라는 prop을 넣어 수정을 하였습니다. 기존의 컴포넌트를 수정하여 새로운 기능을 첨가하는 것은 개방-폐쇄 원칙을 따르는 방법이 아닙니다. 이렇게 수정하는 방식은 컴포넌트가 차후에 어떤 방식으로 변할지 모르게 되고 예상하지 못하는 결과를 초래할 수도 있습니다.

대신에 아래의 방법을 사용합니다:

위의 예제는 IconButton이라는 다른 컴포넌트를 만들게 되었습니다. 이 컴포넌트는 icon이라는 prop을 이용하고 button이라는 HTML button element를 확장하였죠. 이 방법은 개방-폐쇄 원칙을 준수합니다.


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

“서브타입 (자식)의 객체는 슈퍼타입(부모)의 객체의 역할을 대체할 수 있어야 한다” - Wikipedia

Liskov Substitution Principle (리스코프 치환 원칙, LSP)는 객체지향 개발에서 객체 계층 간의 대체역할을 강조하는 원칙입니다. 리액트에서의 LSP 원칙은 파생된 컴포넌트가 베이스 컴포넌트의 역할을 할 수 있어야 한다는 의미입니다.

다음의 예제를 통해 이해하여 보겠습니다:

위의 예제에는 BadCustomSelect라는 컴포넌트가 커스텀 select input으로 사용되고 있습니다. 하지만 베이스 컴포넌트인 select input element의 특성이 없어서 리스코프 치환 원칙을 무시하고 있죠.

대신에 아래의 방법을 사용합니다:

위의 수정된 코드는 CustomSelect라는 컴포넌트가 베이스 컴포넌트인 select input를 확장한 컴포넌트이죠. value라는 props가 존재하고, iconClassName, handleChange, 그리고 마지막으로 남은 모든 props를 …props로 보내고 있습니다. 이 CstomSelect 컴포넌트는 모든 select의 특성이 계승이 되므로 리스코프 치환 원칙 (LSP)을 따르게 됩니다.



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

“어떤 코드도 사용하지 않는 다른 메서드에 의존하면 안 된다” - Wikipedia

Interface Segregation Principle (인터페이스 분리 원칙, ISP)은 인터페이스들은 클라이언트에 맞추어지게 개발이 되어야 하고 너무 방대해지거나 필요 없는 기능이 있으면 안 된다는 원칙입니다.

다음의 예제를 보겠습니다:

위의 예제에는 product라는 불필요한 정보를 ProductThumbnailURL이라는 컴포넌트에 전달하고 있습니다. 차후에 ProductThumbnailURL라는 컴포넌트를 분리하고 product가 아닌 다른 정보를 넣는다면 문제가 생기겠죠. 이 방법은 인터페이스 분리 원칙 (ISP)을 준수하고 있지 않습니다.

아래의 예제는 다시 ISP에 맞추어 리팩터링 된 코드입니다:


위의 코드는 ProductThumbnailURL 컴포넌트가 product라는 모든 정보보다는 src와 alt에 필요한 정보만 받고 있습니다. 이렇게 되면 차후에 분리가 되어도 문제가 없어지죠. 이 방법은 인터페이스 분리 원칙 (ISP)을 준수하고 있습니다.



Dependency Inversion Principle (의존 역전 원칙)

“하나의 객체는 추상성이 낮은 클래스보다 추상성이 높은 클래스와 의존 관계를 맺어야 한다.” - Wikipedia

의존 역전 원칙 (DIP)는 높은 위치의 컴포넌트는 낮은 위치의 컴포넌트에 의존하면 안 된다는 뜻이 담겨있습니다. 모듈화에 중점적인 의미가 있는 이 원칙은 관리의 효율성을 중요시합니다.

다음의 예제를 보겠습니다:

BadCustomForm이라는 컴포넌트는 유연성이 없고 수정하기 힘들게 자식과 아주 타이트하게 연관이 되어 있습니다. form submit의 이벤트가 정해져 있는 컴포넌트가 만들어지므로 추상성이 배제된 코드이죠. 분리가 되면 사용하지 못하는 컴포넌트가 되어 의존 역전 원칙 (DIP)을 준수하지 않는 코드가 됩니다.

이 상황에는 대신에 다음의 코드를 사용합니다:

위의 코드는 AbstractForm 컴포넌트에 추상성을 이용하고 있습니다. onSubmit이라는 함수를 prop으로 받고 form submission에 이용을 하죠. 이렇게 되면 onSubmit이라는 함수에 유연성이 생기고 더 높은의 레벨 컴포넌트를 수정하지 않고도 분리가 되어도 어떤 함수를 사용해도 되는 관리가 쉬워지는 컴포넌트가 만들어집니다.



Conclusion

이 SOLID 원칙들은 개발자들에게 디자인이 잘되고 관리와 확장하기가 편한 코드를 만들어 줍니다. 이런 원칙들을 준수함으로써 모듈화, 코드 재사용, 유연성을 높이고 복잡성을 줄여줍니다.

Comments


pngegg (11)_result.webp

<Raank:랑크 /> 구독 하기 : Subscribe

감사합니다! : Thanks for submitting!

bottom of page