SOLID 원칙과 단일 책임 원칙(SRP) | Today I Learned

hoya·2022년 8월 15일
0

Today I Learned

목록 보기
7/11
post-thumbnail

피드백은 언제나 환영합니다 :)


🤔 SOLID 원칙?

회사에서 여러가지 일을 하다보면, 변경 사항이 생기기 마련이다. 기획이 변경될 수도, 디자인이 변경될 수도, 마케팅 중점사항이 변경될 수도 있다. 이런 상황에 맞춰 개발자는 늘 영리하고 기민하게 움직여야 한다. 이렇게 급박하게 흘러가는 현대 사회 속에서 변경 사항에 유연하게 대처할 수 있는 객체 지향 언어가 나오기 시작했고, 올바른 객체 지향 설계를 위해 SOLID 원칙이 탄생하게 되었다.

SOLID 원칙은 객체 지향 프로그래밍을 하는 개발자라면 지켜야 하는 5대 원칙으로, SRP (단일 책임 원칙), OCP (개방 폐쇠 원칙), LSP(리스코프 치환 법칙), ISP(인터페이스 분리 원칙), DIP(의존성 역전 원칙) 으로 구성되어 있다.

SOLID 원칙의 최우선 목적은, 응집도를 높이고 결합도를 낮춰 유지보수와 확장에 용이하도록 만드는 것이다. 이 원칙을 적절하게 적용한 프로젝트는, 시간이 지나더라도 변경 사항에 기민하게 대응할 수 있을 것이다.

🤔 응집도? 결합도?

  • 응집도 : 모듈 '내부' 요소들의 연관 정도를 의미한다.
  • 결합도 : 모듈 '내부'가 아닌 '외부' 모듈 간의 상호 의존성을 나타내는 정도를 의미한다.

일반적으로, 응집도가 높고 결합도가 낮은 애플리케이션이 이상적인 애플리케이션이라고 불린다.


🚶🏻 단일 책임 원칙 (Single Responsibility Principle)

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

책임 이라는 말이 선뜻 다가오지 않는데, 아래의 코드를 보면서 천천히 이해해보자.

class 개발자 {
    private var 기획서 = "기획 내용"
    private var 디자인_시안 = "디자인 내용"
    private var 개발_내용 = "안드로이드 앱"

    fun 기획하기(변경_기획서: String) {
        기획서 = 변경_기획서
    }
    fun 디자인하기(변경_디자인: String) {
        디자인_시안 = 기획서 + 변경_디자인
    }
    fun 개발하기(개발_사항: String) {
        개발_내용 = 디자인_시안 + 개발_사항
    }
    fun 컴퓨터_수리하기() { }
}

정승 네트워크에 취업한 개발자 A씨는 턱없이 부족한 인력과 사장의 압박으로 인해 개발 외에도 여러 책임을 지고 있는 것을 알 수 있다. 이런 상황 속에서, 사장의 요구로 기획에 변경 사항이 생기면 어떤 일이 일어날까?

1. 개발자 A가 기획서를 변경한다.
2. 변경된 기획에 맞춰 디자인을 변경한다.
3. 변경된 디자인에 맞춰 애플리케이션 개발을 진행한다.
4. 시간이 너무 오래 소요된다.
5. 개발이 끝나갈 무렵 디자인을 변경하라는 사장의 요구를 받는다.
6. 🤬

이렇게, 책임이 많아지면 개발자 A의 작업 시간도 길어짐과 동시에, 수정 사항이 생기면 기민하게 대처하기도 어려운 것을 볼 수 있다.

그렇다면, 평행 세계 속 공부를 무척 열심히 하여 대기업에 입사한 개발자 A씨의 삶은 어떨까?

class 개발자 {
    var 개발_내용 = "안드로이드 앱"

    fun 개발하기(디자인_시안: String, 개발_사항: String) {
        개발_내용 = 디자인_시안 + 개발_사항
    }
    
    fun 코틀린_공부하기(목차: String) {
        print("$목차 공부 중. . .")
    }
}

class 기획자 {
    var 기획서 = "기획 내용"

    fun 기획하기(변경_기획서: String) {
        기획서 = 변경_기획서
    }
}

class 디자이너 {
    var 디자인_시안 = "디자인 내용"

    fun 디자인하기(기획서: String, 변경_디자인: String) {
        디자인_시안 = 기획서 + 변경_디자인
    }
}

class 컴퓨터_수리기사 {
    fun 컴퓨터_수리하기() {}
}

fun main() {
    val 기획자 = 기획자()
    val 디자이너 = 디자이너()
    val 개발자 = 개발자()

    기획자.기획하기("기획 내용")
    디자이너.디자인하기(기획자.기획서, "디자인 내용")
    개발자.개발하기(디자이너.디자인_시안, "iOS 앱")
}

책임을 분리할 사람이 생기자 개발자 A씨의 삶이 훨씬 윤택해진 것을 볼 수 있다. 심지어, 개인 공부도 진행하고 있다!


예제를 보면 어느정도 단일 책임 원칙에 대해 어느정도 감이 잡혔을 것이다.

👦🏻 : 저기요, 개발자들이 개발 관련 일만 하는 것도 아니고, 다른 일도 많이 할 수 있잖아요.

무의미하게 들릴 수도 있지만, 책임의 기준을 정하는 것은 어디까지나 개발자의 몫이다. 잼민이가 이야기한 것과 같이 더 세부적으로 나눌 수도 있다. 만약 책임을 정하는게 어렵다면, SOLID의 창시자인 밥 아저씨가 남긴 말을 생각하면 좋을 것 같다.

같이 수정해야 할 것은 묶고, 따로 수정해야 할 것은 분리한다.

만약 대기업의 개발자들이 정말 개발 관련 일만 하고 있었다면 단일 책임 원칙을 지킨 케이스라고 볼 수 있다.

하지만, 어떤 개발자는 단순 개발뿐 아니라 설계까지 맡고 있었다면 어떻게 해야할까?

class 개발자 {
    fun 개발하기() {
        println("개발 중 . . .")
    }
    
    fun 설계하기() {
    	println("설계 중 . . .")
    }
}

회사 내에서 개발자가 설계하는 것까지 함께 하는 것이라고 명시했다면, 위의 코드 역시 단일 책임 원칙을 지킨 케이스가 될 수 있다. 그러나, 회사 내에서 설계는 대부분의 개발자가 맡는 역할이 아니라고 한다면, 설계하기() 메소드를 다른 곳으로 이동시켜야 단일 책임 원칙을 지킨 케이스가 될 수 있을 것이다.

이렇게 같은 코드를 보더라도 내부의 상황에 따라 단일 책임 원칙을 지켰는지에 대한 여부가 달라지게 되는데, 이 때는 함께 개발하는 사람들과 많은 이야기를 나누며 정확히 컨벤션을 지정하는게 중요하다.


✍️ TL;DR

  • 클래스 내부가 방대해지는 것을 방지할 수 있다.
  • 클래스 내부를 변경하더라도 파급 효과가 적어진다.
  • 이로 인해 쉬운 유지 보수가 가능해지고, 변경 사항을 빠르게 적용할 수 있다.

참고 및 출처

널널한 개발자 TV
위키피디아

profile
즐겁게 하자 🤭

0개의 댓글