[OOP]객체지향 5원칙(SOLID)

2022. 4. 8. 21:34Programming theory/OOP

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

 최근에 유튜브 인공지능에 이끌려 '제5원소'라는 영화 소개를 보았습니다. 그 영상을 보고 갑자기 객체지향의 5원칙이 떠올라 글을 쓰게 되었습니다. 5라는 숫자와 원소/원칙 이 비슷해서 그런 것 같아요.

 

위키에 따르면, 객체지향 5원칙 (SOLID)는 다음과 같이 정의된다고 합니다.

 컴퓨터 프로그래밍에서 SOLID란 [로버트 마틴]이 2000년대 초반에 명명한 객체 지향 프로그래밍 및 
설계의 다섯 가지 기본 원칙을 마이클 페더스가 두문자어 기억술로 소개한 것이다.
프로그래머가 시간이 지나도 유지 보수와 확장이 쉬운 시스템을 만들고자 할 때 이 원칙들을 함께 적용할 수 있다.
 
 SOLID 원칙들은 소프트웨어 작업에서 프로그래머가 소스 코드가 읽기 쉽고 확장하기 쉽게 될 때까지
소프트웨어 소스 코드를 리팩터링 하여 코드 냄새를 제거하기 위해 적용할 수 있는 지침이다. 이 원칙들은 
애자일 소프트웨어 개발과 적응적 소프트웨어 개발의 전반적 전략의 일부다.

간단하게 말하면, 프로그래머가 객체지향 프로그래밍을 할 때 지키면 유지/보수/협업에 편리한 원칙들이라고 할 수 있겠습니다. 

 

객체지향의 5원칙을 SOLID라고도 부르는 이유는 각 원칙의 앞글자를 따왔기 때문입니다.

    • 단일 책임 원칙(SRP / Single responsibility principle) : S
    • 개방 폐쇄의 원칙(OCP / Open close principle) : O
    • 리스코브 치환의 원칙 (LSP / Liskov substitution principle) : L
    • 인터페이스 분리의 원칙(ISP / Interface segregation principle) : I
    • 의존성 역전의 원칙(DIP / Dependecy inversion principle) : D

그럼, 각 원칙의 간단한 정리와 적용 방법에 대하여 알아보겠습니다.


1원칙 - 단일 책임 원칙(SRP / Single responsibility principle)

  • 모든 클래스는 하나의 책임만을 가지며 객체가 변경되는 요인은 하나뿐이어야 함
  • 책임영역이 확실해지기 때문에 연쇄작용에서 자유롭고 가독성과 유지보수 용이
  • 가능한 하나(혹은 명확하게 관련이 있는) 책임을 부여 함으로써 객체는 보다 명확해지고 표현 가능해지며,
    느슨한 커플링과 높은 응집력을 얻게 됨
  • 다른 4개의 원칙의 기본이 되는 법칙

이 원칙은 다른 원칙들의 기본인 만큼, 지켜지지 않을 경우 다음과 같은 피해가 있을 수 있습니다.

  • 클래스가 커질 경우 가독성이 떨어짐
  • 의존성이 증가함
  • 클래스 사이의 관계를 잘 못 알고 고칠 경우 다른 기능까지 피해를 봄 (사이드 이펙트)

 


2원칙 - 개방 폐쇄의 원칙(OCP / Open close principle)

  • 확장에는 열려있고, 수정에는 닫혀 있어야 함
  • 요구사항의 변경이나 추가사항이 발생하더라도, 기존 구성요소는 수정이 일어나지 않아야 함
  • 기존 구성요소를 쉽게 확장해서 재사용할 수 있어야 한다는 의미
  • 이를 가능하게 하는 주요 메커니즘은 추상화와 다형성

적용 법은 아래와 같습니다.

  1. 수정될 것과 안 그런 것을 엄격히 구분
  2. 위의 두 구분(만나는 지점)에 인터페이스를 정의
  3. 구현에 의존하기보다는 정의한 인터페이스에 의존하도록 코딩
    Ex) 캐릭터와 움직임 패턴. 캐릭터마다 움직임이 다를 경우 캐릭터 자체의 수정이 아닌 움직임 패턴만 재정의 함

3원칙 - 리스코브 치환의 원칙 (LSP / Liskov substitution principle)

  • 부모는 자식에 관계없이 대체 가능해야 하고, 자식은 부모 타입으로 교체할 수 있어야 함
  • 업 캐스팅을 해도 아무런 문제가 안되어야 한다는 것

적용 법은 아래와 같습니다.

  1. 여러 개체가 똑같은 일을 한다면 이들을 하나의 클래스로 표현하고 이들을 구분하는 필드를 둠
  2. 똑같은 연산을 제공하지만, 이들을 약간씩 다르게 한다면 공통의 인터페이스를 만듦(인터페이스 상속)
  3. 공통된 연산이 없다면 별개의 클래스로 만듦
  4. 추가로 무언가를 더한다면 구현 상속을 이용
    예시) 도형 부모의 특성을 상속받아 확장한 원과 사각형
    • 도형(부모), 자식(원 / 사각형)
    • 도형은 둘레를 가지고 있다 -> (원 / 사각형)은 둘레를 가지고 있다

4원칙 - 인터페이스 분리의 원칙(ISP / Interface segregation principle)

  • 사용하지 않는 기능은 처음부터 배제하고 차라리 인터페이스를 여러 개 만들어 동시에 사용할 수 있도록 분리
  • 사용하지 않는 인터페이스에는 영향을 받지 말아야 함

적용 법은 아래와 같습니다.

  1. 클래스의 상속을 이용하여 인터페이스를 나눔
  2. 객체 인터페이스를 통한 분리(위임)
    EX) 스마트폰 기능.
    전화 기능과 사진 기능은 별개 -> 전화할 때는 사진 기능을 이용하지 않음. 서로 독립적으로 구현

5원칙 - 의존성 역전의 원칙(DIP / Dependecy inversion principle)

  • 상위 모듈은 하위 모듈에 의존해서는 안됨
  • 모든 하위 모듈은 상위 모듈을 상속해야 함
  • 하위 모듈로 갈수록
  • 즉, 탑다운 방향의 의존성이 역으로(바텀업)으로 올라와서는 안됨

적용 법은 아래와 같습니다.

  1. 인터페이스(쉽게 변하지 않는 기능) / 추상 클래스(쉽게 변할 가능성이 있는 기능) 정의
    : 추상화 정도 인터페이스 > 추상 클래스
  2. 변하기 쉬운 순서 설계 (상위일수록 변하기 쉽지 않음)
    ex) 핸드폰 케이스 설계
    • 핸드폰(인터페이스), 스마트폰(핸드폰에 의존하는 자식), 핸드폰 케이스(핸드폰에 의존하는 자식)
    • 핸드폰(핸드폰이라는 특성은 변하지 않음) - 스마트폰(제조사, OS에 따라 변함) - 핸드폰 케이스(핸드폰 모델에 따라 변함)
    • 케이스는 모델에 따라 장식, 색, 재질 등 다양하게 변할 수 있음
    • 스마트폰은 케이스에 구애를 받지 않음, 사실 착용하지 않아도 됨
    • 스마트폰은 핸드폰이라는 틀을 벗어나지 않고, 케이스 역시 핸드폰이 아니면 사용할 수 없음
    • 의존성이 상위 모듈이 하위 모듈에 의존하지 않지만, 하위 모듈은 상위 모듈에 의존하는 상황

 

반응형
LIST

'Programming theory > OOP' 카테고리의 다른 글

[OOP] 가상 함수(Virtual function or Virtual method)  (0) 2022.04.08