-
SOLID - SRP (단일 책임 원칙)Clean Architecture 2025. 10. 5. 23:07
안녕하세요! 오랜만이에요 9월에 캡스톤이랑 다른 활동들이 겹쳐 잠깐 포스팅을 쉬게 되었어요. 이번 달부터 다시 일주일에 한번씩 포스팅을 주기적으로 올리려고 합니다 🙂 오늘은 SOLID 원칙이라는 따끈따끈한(?) 새로운 주제를 가져왔습니다! 한번 알아볼까요?
1. SOLID 원칙이란?
취업 준비할 때 면접 단계에서 자주 나오는 단골 질문 중에 하나죠. 저도 관련 인턴 공고 조건에서도 SOLID 원칙에 대한 이해를 자격 요건으로 두는 경우를 가끔씩 보았던 것 같습니다. SOLID 원칙은 객체 지향 프로그래밍에서 견고하고 유지보수 가능한 프로젝트를 설계하기 위한 원칙입니다. SRP, OCP, LSP, ISP, DIP 이렇게 5가지 원칙의 앞글자를 따서 만들었습니다. 클린 아키텍처의 기반이 되며, 모듈화 계층화를 통해 코드의 유연성과 확장성을 높일 수 있습니다.
2. SRP 란?
SOLID의 첫 번째 원칙인 단일 책임 원칙(Single Responsibility Principle)입니다. 말 그대로 여러 개의 책임이 아니라 단일 책임만을 갖는 것인데요. 안드로이드에서 SRP는 클래스가 하나의 책임만 가지며, 오직 하나의 이유로만 변경되는 것을 의미합니다. 이를 통해 복잡성을 줄일 수 있고 여러 책임을 가질 때 발생할 수 있는 변경의 부담을 줄일 수 있습니다. 클래스를 단일 책임으로 제한함으로써, 코드의 가독성과 유지보수성 또한 향상시킬 수 있습니다. 한 가지 목적에 집중된 클래스는 이해하기 쉽고, 변경이 필요할 때 변경의 영향을 최소화할 수 있습니다. SRP 원칙을 준수하지 않아서 안드로이드 앱의 구성요소들이 점점 무거워지면, 화면 전환 시 속도가 느려지거나 메모리 누수 및 뷰 상태 저장 문제 등이 발생할 수 있습니다.
3. 예제 코드 (코틀린)
class CinemaManager { fun inspectTheater(category: String) { // 전반적인 영화관 점검 } fun assistCustomer(user: User) { // 손님 응대 } fun prepareFood(food: String) { // 팝콘, 핫도그 등 음식 제조 및 준비 } fun cleanFacility(place: String) { // 영화관 내부 시설 청소 } }
예제 코드를 보겠습니다. 영화관 매니저 클래스가 여러 책임을 갖는 상황입니다. 매니저가 슈퍼맨이 아니라면 혼자서 이렇게 책임을 많이 갖는건 여러 측면에서 좋지 않을 것 같습니다. 단일 책임 원칙(SRP)을 위반한 상태네요. 이런 경우에 어떻게 해결하는게 좋을까요?
class CinemaManager { fun inspectTheater(category: String) { // 전반적인 영화관 점검 } } class CinemaStaffOne { fun prepareFood(food: String) { // 팝콘, 핫도그 등 음식 제조 및 준비 } } class CinemaStaffTwo { fun assistCustomer(user: User) { // 손님 응대 } } class CinemaStaffThree { fun cleanFacility(place: String) { // 영화관 내부 시설 청소 } }
과중한 업무를 맡은 영화관 매니저가 3명의 알바생을 뽑고 각각에게 역할을 하나씩 부여함으로써 문제를 해결할 수 있었습니다. 단일 책임 원칙(SRP)을 준수하게 되었습니다. 실제 안드로이드에 적용한 예시도 살펴보겠습니다.
4. 예제 코드 (안드로이드)
class MainActivity: AppCompatActivity() { override fun onCreate() { super.onCreate() fetchData() } fun fetchData() { // 1. 네트워크 요청 val data = apiService.getData() // 2. 데이터 처리(가공) val processedData = processData(data) // 3. UI 업데이트 updateUI(processedData) } }
데이터를 가져와서 UI 에 바인딩하는 예시가 있습니다. 이때 네트워크 요청, 데이터 가공처리, UI 바인딩 세가지가 필요합니다. 현재 코드에서는 해당 3가지 역할을 UI 레이어에서 전부 처리하는 상황입니다. 한가지 역할이 아닌 여러 개의 책임을 갖기에 SRP를 위반한 상황이죠. 여기서 3개의 기능 중 단 한개라도 변경되면 fetchData 메소드가 항상 변경되어야 합니다.
아까 영화관 예시에서 음식 조리에 이상이 있거나, 청소가 제대로 안되어 있거나, 손님이 매표소에서 발권이 어려운 경우 항상 매니저를 불러야하는 상황으로 비유할 수 있습니다. 이러한 문제를 해결하기 위해 한번 책임을 분리시켜봅시다.
// 네트워크 요청 class DataRepository(private val apiService: ApiService) { fun fetchData(): Model { return apiService.getData() } } // 데이터 처리 및 관리 class MainViewModel(private val dataRepository: DataRepository): ViewModel() { private val _data = MutableLiveData<Model>() val data: LiveData<Model> get() = _data private fun loadData() { _data.value = dataRepository.fetchData() } } // UI 업데이트 class MainActivity: AppCompatActivity() { private val viewModel: MainViewmodel by viewModels() override fun onCreate() { super.onCreate() viewModel.data.observe(this) { data -> updateUI(data) } viewModel.loadData() } }
세 가지의 역할을 단일 책임 원칙(SRP)을 준수하며 분리해보았습니다. 위의 코드를 보면 네트워크 요청은 레포지토리(repository)에서, 데이터 가공 및 관리는 뷰모델(viewModel)에서, UI 업데이트는 액티비티,프래그먼트와 같은 안드로이드 컴포넌트에서 합니다. 이렇게 기존에 UI 에서 부담했던 3가지 역할을 뷰모델, 레포지토리 각각에게 1개씩 책임을 주면서 해결할 수 있었습니다. 영화관으로 비유하자면, 매니저가 알바생을 고용하여 각각의 역할을 부여한 상황입니다.
6. 클린 아키텍처와의 연관성
SOLID 원칙 중 단일 책임 원칙(SRP)이 클린 아키텍처와 무슨 관련이 있을까요? 클린 아키텍처에서 데이터, 도메인, 프레젠테이션 같은 각각의 계층은 자신의 책임만을 가져야 하며, 이를 통해 모듈 간 결합도를 낮추고 유지보수를 용이하게 할 수 있습니다. 예를 들어, 도메인 레이어는 비즈니스 로직만 담당하고, 데이터 레이어는 데이터 처리를 담당하며, 프레젠테이션 레이어는 UI 와 사용자 상호작용을 담당합니다. 각 계층을 SOLID 원칙의 단일 책임 원칙(SRP)에 맞게 분리함으로써 하나의 변경이 다른 계층에 영향을 주지 않고, 해당 계층만 수정하여 해결해야 하는 문제의 규모 및 범위를 줄일 수 있습니다.
오늘은 SOLID 원칙 중 단일 책임 원칙에 대해 알아보았습니다! 다음 시간에는 두번째 원칙인 개방 폐쇄 원칙(OCP)에 대해 알아보겠습니다! 즐거운 추석 되세요 🙌
'Clean Architecture' 카테고리의 다른 글
UI 레이어란? (3) 2025.08.24 Presentation 레이어란? (8) 2025.08.17 Local 레이어란? (4) 2025.08.10 Remote 레이어란? (6) 2025.08.03 Data 레이어란? (2) 2025.07.27