ㅁㄴㅇㄻㄴㅇㄹ

SOLID를 정리해보자! - 01 본문

객체 지향

SOLID를 정리해보자! - 01

hanbin8269 2021. 1. 28. 19:41

객체지향의 5원칙 : SOLID

객체 지향 언어를 사용하는 개발자라면 SOLID 법칙은 모두 알고 있어야 한다고 생각한다. 면접에서 질문이 들어와도 곧바로 대답할 수 있도록 제대로 공부해야 겠다는 생각에 정리하게 되었다.

SOLID란 클린코드의 저자 로버트 마틴이 객체 지향 프로그래밍의 다섯 가지 기본 원칙 

SRP, OCP, LSP, ISP, DIP을 정리했는데, 이 원칙들의 앞자리를 따서 부르는 이름이다.

  • SRP(Single Responsibility Principle) - 단일 책임 원칙
  • OCP(Open/Closed Priciple) - 개방/폐쇄 원칙
  • LSP(Liskov Substitution Principle) - 리스코프 치환 원칙
  • ISP(Interface Segregation Principle) - 인터페이스 분리 원칙
  • DIP(Dependency Inversion Principle) - 의존 역전 원칙

SRP - 단일 책임 원칙

하나의 클래스는 하나의 책임만 가져야 한다”

위 문장은 단일 책임 원칙을 잘 표현한 문장이다. 하지만 무작정 책임을 분리해야 한다고 설명하면 이해가 잘 가지 않는다. 예제 상황과 코드를 보면서 무엇이 책임이고  분리해야 하는지 알아보자

(예제 상황) 
나는 도서관에서 사용할 자리 예약 서비스를 개발하고자 한다.
자리를 예약하는 기능을 개발하려고 하는데, 프로세스는 이렇다.

- 매개변수로 유저의 ID, 빌릴 자리의 번호를 입력받는다.
- 유저가 있는지 확인하고 예약 객체를 생성해서 반환해준다.

매우 간단한 과정이다. java로 구현해보자

public class ReservationService {
    
    private UserRepository userRepository; // UserRepository 인터페이스를 자료형으로 선언했다.

    public ReservationService(){
        userRepository = new MYSQLUserRepository(); // UserRepository를 구현한 MYSQLUserRepository 객체를 "생성"했다.
    }

    public Reservation createReservation(int userID, int seatID){ // 예약을 "실행"한다.
        User user = userRepository.findUserByID(userID);

        return new Reservation(user,seatID);
    }
}

위 예제를 보면 ReservationService 클래스는 두 가지 일을 하고있다.

  • MYSQLUserRepository의 객체를 생성
  • createReservation메서드로 예약을 실행

이 말은 ReservationService클래스가 생성해야하는 책임과 실행해야하는 책임 두 가지를 가지고 있다는 것이다.

이제 분리해야 하는 책임이 무엇인지는 알았다. 그러면 분리해야하는 이유는 무엇일까? 아래 상황을 보자

 

당신은 예약기능을 구현하고 더 많은 기능을 개발하게 되었다. 
유저 조회 기능, 유저 생성 기능 등의 매우 많은 기능을 개발했다.

그런데 MYSQLUserRepository 클래스에 문제가 생겨 MongoDBUserRepository로 교체하고자 한다.

교체하기 위해 MYSQLUserRepository 객체를 생성하는 파일을 수정해줘야 하는데,
유저 조회 기능, 유저 생성 기능, 예약 기능 등을 구현한 10개 이상의 클래스가
MYSQLUserRepository 객체를 생성하는 코드을 가지고 있었다.

당신은 이제 10개 이상의 클래스 모두 직접 수정해줘야 한다.
= 변경에 따른 파급효과가 크다

 

위 상황을 보면 10개 이상의 클래스가 객체를 생성해야 하는 책임과 각자의 역할을 실행하는 책임 모두를 가지고 있었기 때문에 변경에 따른 파급효과가 매우 커지게 되었다.

 

단일 책임 원칙은 위와 같은 상황이 생기지 않도록. 즉 변경에 따른 파급 효과가 크게 생기지 않기 위해 지키는 원칙이다.

 

그러면 처음에 작성한 코드를 어떻게 변경하면 될까? 객체 생성 기능 실행 책임을 분리해주면 된다.

한가지 해결 방안을 소개시켜주겠다.

public class AppConfig{

    public UserRepository getUserRepository(){
        return new MYSQLUserRepository();
    }
}
-----------------------------------------------------

public class ReservationService {
    
    private UserRepository userRepository;

    public ReservationService(){
        AppConfig appConfig = new AppConfig();
        userRepository = appConfig.getUserRepository(); // 
    }

    public Reservation createReservation(int userID, int seatID){ // 예약을 "실행"한다.
        User user = userRepository.findUserByID(userID);

        return new Reservation(user,seatID);
    }
}

위 코드를 보면 이제ReservationService클래스가 UserRepository객체 생성의 책임이 없어졌다. 위와 같이 책임을 분리해준다면 단일 책임 원칙을 지킬 수 있다.

 

다음 글에서는 OCP에 대해서 알아보자

'객체 지향' 카테고리의 다른 글

[객체 지향] Python 1급 객체란?  (0) 2021.05.09