티스토리 뷰

카테고리 없음

객체지향의 원칙 (SOLID)

hodumarustory 2024. 7. 30. 15:09

객체 지향 설계인 OOD(Object Oriented Design)의 5원칙을 SOLID라고 할수있는데

 

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

 

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

 

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

 

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

 

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

 

객체 지향 설계를 하기위해서는 위의 5원칙을 지키면서 설계해야 좋은 설계라고 볼수있는데

 

응집도를 높이고 결합도는 낮추자는 취지를 가지고 있다.

 

객체 지향 프로그램을 구성하는 속성,메서드,클래스, 객체, 패키지 등등 여러곳에 적용되는것이라서 

 

막상 SOLID가 적용된건지 아닌지 애매모호하거나 보는사람의 관점마다 다를수있는 이유는 SOLID가 개념적인것이기 때문이다.

 

SOLID를 사용하여 설계하면 그렇지않은 소프트웨어에 비해  상대적으로 이해하기 쉽고

 

리팩터링과 유지보수가 수월하고 논리적이다.

 

SRP(Single Responsibility Principle) 단일 책임 원칙이란?? 

 

어떤남자가 사람이 한가정에 가장 역할을하고 아이의 아빠역할도 하고 회사에서는 부장의 직책을 가지고있다고 가정하면

 

여러가지 일을 한번에 처리하려면 힘들지만 필요할때 한가지 역할을 맏아서 하면 훨씬 수월 하게 될것이다.

 

가장인 남자는 이혼하더라도 아이의 아빠는 영향을 받지 않고 부장역할도 영향을 받지 않는것이다.

 

클래스를 역할과 책임에 따라 분리해서 각각 하나의 역할과 책임만 갖게 하니 혹시 가정에 문제가 생기더라도

 

다른부분에는 문제가 생기지 않고 문제가 생긴부분만 해결하면 되기때문에 결합도가 낮아진것이다.

 

단일책임 원칙은 잘된경우를 보는것보다 잘못된경우를 보는경우에 이해하기가 쉽다.

 

Class 사람 {

        String 군번;

        int 나이; 

        void 말한다() {};

        void 먹다() {};

}

 

위에 사람이라는 클래스를 보면 우리나라는 여자는 군대를 가지 않기 때문에 군번이라는 속성이 필요가 없다.

 

Class 남자 extend 사람 {

       String 군번;

}

 

Class 여자 extend 사람 {

       

}

 

그래서 단일책임원칙 SRP를 지키게 만들어보면  위의 코드처럼 남자클래스에는 군번의 속성을 넣어주고

여자클래스에는 굳이 넣어주지 않아도 된다.

 

그렇게되면 같은 사람이지만 남자는 남자의 역할을 여자는 여자의 역할을 나눠서 구분하면서

 

사람으로서 하는 일을 둘다 가능하다고 볼수있다.

 

 

 

OCP(Open Closed Principle) 개방 폐쇄 원칙이란?

 

개방 폐쇄 원칙이란 엔티티(클래스,모듈, 함수)는 확장에는 열려있고 주변 변화에대해서는 닫혀있어야한다 라는 개념이다.

 

예를 들면  어떤 운전자가 마티즈를 구입했다 그리고 운전을하면서 마티즈에 적을되었지만

 

수입이 늘어서 마티즈를 판매하고 쏘나타 차량을 구매했다고 가정하면 차량이 다르기에 조작방법은 조금씩 다를수있어도

 

운전자체에는 영향이 없다고 볼수있다.

 

interface 자동차 {

       창문조작();

       기어조작();

}

 

 

class 마티즈 implement 자동차 {

       @Override

       창문조작() {};

       @Override

       기어조작() {};

}

 


class 쏘나타 implement 자동차 {

  

        @Override

        창문조작() {};

        @Override

       기어조작() {};

}

 

class 운전자 {};

 

운전자 클래스와 쏘나타 마티즈 사이에  인터페이스를 둠으로써 다양한 자동차가 생긴다고해도

 

객체 지향 세계의 운전자는 운전 습관에 영향을 받지 않는다. 이렇게되면 확장에 대해서는 열려있고

 

운전자(사용자) 입장에서는 변화에는 폐쇄되어있는것처럼 변한다.

 

데이터베이스 프로그래밍 경험이 있다면 위의 방식을 사용해본적이 있을수도 있다.

 

 

OCP예시

위의 사진처럼 JDBC를 사용하는 사용자는 데이터 베이스가 변경 되더라도 Connection부분을 설정하는

부분 외에는  따로 수정할 필요가 없어진다. Connection부분을 별로의 설정 파일로 분리해두면

클라이언트 코드는 단 한줄도 변경할 필요가 없는것을 보여주는 좋은 예시이다.

 

JDBC뿐 아니라 iBatis, MyBatis등등 데이터 베이스 프로그래밍을 지원하는 라이브러리와 프레임워크에서도 개방 폐쇄 예를 볼수 있다.

 

개방 폐쇄 원칙은 자바에도 잘 적용 돼 있는데 자바 개발자가 작성하고 있는 코드를 윈도우에서 구동할지

리눅스에서 구동 하는지 또는 다른 운영체제에서 구동될지는 걱정할 필요가 없다 각 운영체제별 JVM( Java Virtual

Machine)과 목적 파일이 있어서 개발자는 다양한 구동 환경에 대해 걱정하지 않고 본인이 작업하는 PC에설치된 JVM에서

구동되는 코드를 작성하면 된다. 이러한 예시들이 변화에는 닫혀있고 확장에는 열려있는 예시를 보여주는 것들이다.

 

 

LSP(Liskov Substitution Principle) - 리스코프 치환 원칙이란?? 

 "서브 타입은 언제나 자신의 기반 타입(base type)으로 교체할 수 있어야 한다." - 로버트C.마틴

 

상속에 대해 설명하면서 객체 지향에서의 상속은 조직도나 계층도가 아닌 분류도가 돼야 한다고 했다.

객체 지향의 상속은 다음의 조건을 만족해야 한다.

 

하위 클래스 is a kind of 상위 클래스 - 하위 분류는 상위 분류의 한 종류다.

구현 클래스 is able to 인터페이스 - 구현 분류는 인터페이스할 수 있어야 한다.

 

위 두 개의 문장대로 구현된 프로그램이라면 이미 리스코프 치환 원칙을 잘 지키고 있다고 할 수 있다.

하지만 위 문장대로 구현되지 않은 코드가 존재할 수 있는데 바로 상속이 조직도나 계층도 형태로 구축된 경우다.

 

아버지를 상위 클래스(기반 타입)으로 하는 딸이라는 하위 클래스(서브 타입)이 있다고 가정해보면

전형적인 게층도 형태이며 객체 지향의 상속이 잘못 적용한 설명이다. 아래 설명을 보면 이해 할것이다.

 

아버지 춘향이 = new 딸();

 

??? 위의 설명을 보면 말도안되는 일이라는걸 알수있다. 춘향이는 아버지형 객체 참조 변수이기에 아버지 객체가 

가진 행위(Method)를 할수있어야한다. 춘향이에게 아버지의 어떤 역할을 시킬수있을까???

바른 예시를 보여주면 

 

동물 펭구 = new 펭귄();

 

위의 설명처럼 만들면 논리적으로 크게 문제가 없다 펭귄이 태어나 펭구라는 이름을 짓고 동물의 행위(Method)를 하게

하는것에는 전혀 위화감이 없다.

 

아버지 - 딸 구조는 리스코프 치환 원칙을 위배하고 있는것이고 동물 - 펭귄 구조는 리스코프 치환 원칙에 만족하는 것이다.

 

사람의 상속 계층도는 사실 상속이라는 개념에 맞는 말이지만 정확히 말하면 extends는 상속 보다 확장개념이라서

 

위의 동물의 계층도가 맞다고 볼수있다.

 

 

ISP(Interface Segregation Principle) 인터페이스 분할 원칙란???

 

"클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다." - 로버트C.마틴

 

위에 단일책임 원칙(SRP) 예제를 보면 남자 클래스는 여러가지 역할을 했어야했는데

 

단일책임 원칙(SRP)을 적용한 후에 한가지 역할을 맡아서 수행하게 바뀌었다.

 

이때 다른 방법이 있다면 인터페이스 분할 원칙(ISP)를 사용하는 것이다.

 

ISP원칙 예시

 

위의 이미지 처럼 남자라는 클래스를 각각의 역할을 할수있게 인터페이스로 제한하고 사용하는것이 인터페이스 분할 원칙의 핵심이다.

 

결론적으로 단일책임 원칙(SRP)와 인터페이스 분할 원칙(ISP)는 같은 문제를 해결하는 다른 해결책이라고 설명할수있겠다.

 

프로젝트의 요구사항과 설계자의 취향에 따라 선택해서 설계할수있지만 특별한 경우가 아니라면 단일 책임 원칙(SRP)를 

사용하는것이 더 나은 해결책이라고 볼수있다.

 

인터페이스 분할 원칙을 설명할때 함께 등장하는 이야기는 인터페이스 최소주의 원칙이라는 것인데

인터페이스를 통해 메서드를 외부에 제공할 때는 최소한의 메서드만 제공하라는 것이다. 위 이미지 처럼

남자친구 인터페이스에는 사격하기(), 또는 구보하기()등의 메서드를 제공할필요성이 없다는 것이다.

 

********* ********* ********* ********* ********* ********* ********* ********* ********* *********   (나의 생각)

상위 클래스는 풍성할수록 좋고 인터페이스는 작을수록 좋다. 그 이유는 상위클래스가 하위클래스에서 
사용하는 메서드나 속성들이 겹치게되면 상위클래스가 풍성하지 않을 경우 각각 하위클래스에서

생성 해줘야하지만 상위 클래스가 풍성할수록 하위클래스에서 확장(extends)할때 상위클래스에서

만든 속성이나 메서드들을 따로 만들필요없이 오버라이딩하거나 해서 사용할수있기 떄문이다 

********* ********* ********* ********* ********* ********* ********* ********* ********* ********* *********

 

DIP(Dependency Inversion Principle) 의존 역전 원칙란??

 

 

위의 이미지를 보면 자동차와 스노우 타이어는 의존 관계가 있다. 자동차가 스노우 타이어에 의존하고 있다.

 

하지만 자동차는 겨울에만 스노우 타이어를 사용하면 되는데 일반 타이어로 교체할때 자동차는 그 행위에

영양을 받는 걸 볼수있다. 그래서 아래 이미지를 보면 추상화된 타이어라는 인터페이스에게만 의존하게 

함으로써 타이어가 변경되어도 자동차는 그영향을 받지 않게 된다.

 

위의 이미지 처럼 스노우 타이어를 보면 스노우 타이어는 어디에도 의존하지 않는 클래스였지만

아래 이미지 처럼 추상화된 타이어 인터페이스 사용하게 되면서 스노우 타이어가 타이어 인터페이스에 의존하게 되었다.

이게 바로 의존 역전의 원칙이라고 볼수있다. 중간에 타이어 인테페이스를 두면서 스노우 타이어가

타이어 인터페이스에게 의존하게된 상황이 벌어진 것이다.

이처럼 자신보다 변하기 쉬운 것에 의존하던 것을 추상화된 인터페이스나 상위 클래스를 두어서 변하기 쉬운 것의

 변화에 영향받지 않게 하는 것이 의존 역전 원칙이다.

DIP 원칙

 

 

 

결국  위의 여러가지 원칙을 설명했지만 결국 두고 보면 객체 지향 4대 특성을 활용하는것인데 비슷한 경우의 원칙들이 

많은걸 볼수있다. 

 

SRP(Single Responsibility Principle) 단일 책임 원칙 : 어떤 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 한다.

 

OCP(Open Closed Principle) 개방 폐쇄 원칙 : 자신의 확장에는 열려 있고, 주변 변화에 대해서는 닫혀 있어야 한다.

 

LSP(Liskov Substitution Principle) 리스코프 치환 원칙 : 서브(하위) 타입은 언제나 자신의 기반(상위)타입 으로 교체 가능해야 한다.

 

ISP(Interface Segregation Principle) 인터페이스 분리 원칙 : 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.

 

DIP(Dependency Inversion Principle) 의존 역전 원칙 : 자신보다 변하기 쉬운 것에 의존하지 마라.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함