새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.

3 분 소요

📌 2025-03-04 TIL

1. 오늘의 학습 주제

  • SOLID를 상속해서 오버라이딩을 해보자.

2. 학습 내용

SRP 단일 책임 원칙

단일 책임 원칙은 하나의 객체가 하나의 역할만 책임지는 것을 말합니다.

하나의 역할이란 클라이언트의 요구사항으로 변경될 경우 변경 사항이 하나라는 겁니다.

SRP를 잘 지키는 것은 생활 가전 이라고 생각합니다.

처음에 드럼 세탁기가 등장하고 통돌이에 넣지 못하던 기능을 넣었습니다.

생활 가전은 사용자들의 요구사항을 빠르게 반영하여 선점하는 것이 중요하다고 생각합니다.

처음 드럼 세탁기가 등장하고 세탁 기능 외에 다양한 책임을 넣으려고 했습니다.

건조기 기능을 넣게 되었습니다. 건조 기능을 보여주는 것과 세탁기 기능까지 하나의 화면에서 보여주는 것인 사용자들이 사용하기 어렵고, 사용자들이 원하는 다양한 기능은 세탁기 구조내에서 추가하기 어려웠습니다.

단일 책임 원칙에서 말하듯 건조 기능이 추가된 세탁기는 건조기가 고장나도 세탁기 부품에 손을 대야하며 세탁 기능이 고장나도 건조기 부품을 열어야 했습니다. 수리 이후에는 둘다 정상 동작하는지 확인하는 과정이 발생하게 됩니다.

이런 구조는 두 기능이 수리하거나 새로 요구사항이 들어와도 내부 구조에서 해결하려면 다른 기능에 영향이 없는지 확인하는 불필요한 과정이 생기게 되었습니다.

따라서 건조기는 별도로 나오게 되었고 세탁기 기능은 세탁 기능만, 건조기는 건조 기능을 가지는 것이 추가 기능이나 요구사항에 대해 변경이 이루어진다고 하더라도 다른 관심사에 대해서 테스트를 하지 않아도 되는 것이 장점이라고 생각합니다.

OCP

개방 폐쇄 원칙은 역시 생활 가전에서 찾아볼 수 있습니다.

무선 청소기나 유선 청소기입니다.

우리가 청소하는 환경에 따라 다양한 청소기 헤더를 선택합니다.

창틀, 카페트, 천장, 거친 시멘트바닥 등 그때 마다 알맞는 청소기 헤더를 선택합니다.

우리가 청소기 헤더를 교체할 때마다 청소기 내부를 열어서 청소 환경에 맞는 구조로 변경하지 않습니다.

어떻게 변경하나요?

청소기 헤더에 버튼 누르고 살짝 힘준다음 뺍니다.

그리고 변경하려는 청소기 헤더를 살짝 힘주면 끝입니다.

청소기 헤더와 청소기 호스는 서로 어떤 모양인지 모릅니다.

정해진 규격(인터페이스)에 맞춰져 있을 뿐입니다.

공기 청정기도 마찬가지입니다.

공기 청정기도 공기를 흡수하고 뱉는게 끝입니다.

그때 공기를 흡수할 때 공기 청정기 규격에 맞는 공기 청정기 필터를 고르면 됩니다.

그래서 정품 필터를 사용할 수도 있고 저렴한 해외 필터를 사용할 수도 있습니다.

이렇게 정해진 규격을 만들면 기존 코드(몸체)를 변경하지 않고 다양한 기능(청소기 헤더)를 변경할 수 있습니다.

LSP

이것도 생활 가전에서 답이 있습니다.

상위 오브젝트를 일반 오븐이라고 하겠습니다.

하위 오브젝트는 전자레인지 기능이 있는 오븐, 에어프라이기가 있는 오븐, 전자레인지 기능과 에어프라이기 기능도 있는 오븐

상위 오브젝트를 확장하여 더 다양한 기능을 제공하는 오븐이 있습니다.

사용자가 오븐을 사용하기 위해 오븐 기능을 가지는 것을 아무거나 집어도 동일한 기능으로 제공합니다.

이때 상위 기능을 잘못 상속하면 특정 상황에서 동작을 안할 수 있습니다.

만약 가열이라는 기능이 있는 가스레인지가 있습니다.

이걸 상속한 인덕션이 있습니다. 가열이라는 기능을 오버라이딩 했습니다.

그런데 사용자가 가스레인지에서 사용가능한 알류미늄 냄비를 인덕션에서 사용하려고 합니다.

냄비는 가열되지 않습니다. 인덕션에서 허용하지 않은 냄비이기 때문입니다.

이처럼 하위 클래스는 가열이라는 어떠한 물건이 와도 열을 전달할 수 있어야하지만 인덕션은 인덕션 제품만 가능한 상황입니다. 이런 경우가 잘못된 설계라고 할 수 있습니다.

ISP 인터페이스 분리 원칙

클라이언트는 자신이 사용하지 않는 메서드(인터페이스)에 의존하지 않는다.

이것도 마찬가지로 생활 가전인 식기 세척기를 예로 들 수 있습니다.

만약 설계를 오염을 제거하는 세탁기를 의존했다면 아래와 같은 기능을 구현해야합니다

  1. 세탁
  2. 행굼
  3. 탈수
  4. 회전

그런데 만약 식기 세척기를 회전 한다면 그릇은 모두 깨지게 될겁니다.

식기 세척기에는 회전 기능이 필요 없습니다. 필요없는 인터페이스를 구현해야하므로 큰 인터페이스인 세탁기를 분리하여

세탁 할수 있는,행굼할 수 있는,탈수 할 수 있는,회전할 수 있는으로 작게 분리하여 필요한 인터페이스만 의존하는 것이 인터페이스 분리 원칙을 말합니다.

DIP

의존성 역전 원칙은 상위 모듈은 하위 모듈에 의존하면 안되고, 둘 다 추상화에 의존해야 한다는 내용입니다.

그래야 객체지향 프로그래밍의 장점인 유지보수와 확장성을 활용할 수 있습니다.

이것도 마찬가지로 생활 가전으로 설명해보겠습니다.

제가 가스레인지를 어떤 것을 가져와도 동작 방식은 간단합니다.

  1. 가스레인지에 가스 호스를 연결한다.
  2. 가스레인지에 1.5V 건전지를 넣는다.
  3. 가스레인지 레버를 오른쪽으로 돌리면 켜진다.
  4. 가스레인지 레버를 왼쪽으로 돌리면 꺼진다.

우리는 우리나라에서 판매하는 어떤 가스레인지를 가져와도 1~4번 방식으로 동작합니다.

직접 SK매직 가스레인지만 사용할 줄 아는게 아니라 이런 기능이 있다는 공통적인 사항을 알고 있을 뿐입니다.

가스레인지 내부 구현 방식도 동일합니다. 다양한 가스 용량을 조절하거나 안전 기능을 넣어도 1~4번을 기반으로 만들기만 하면 됩니다. 뜬금없이 왼쪽으로 돌리면 켜지거나 그렇게 만들지만 않으면 어떤 사용자가 사용할지 모르지만 정해진 추상화로 만들기만 하면 됩니다.

댓글남기기