정말 많이 듣고 쓰는 용어지만 머릿속에 정리가 안되어 정리했습니다
웹애플리케이션 개발자로서 소프트웨어 개발 및 유지보수시 프로그램을 설계하는일이 대부분입니다
가장 중요한 개념이라고 하면 "관심사 분리"라고 말할 수 있습니다
관심사 분리(Separation of Concerns, SoC):
정의: 프로그램을 구별된 부분으로 분리하여, 각 부분이 단일 관심사를 다루도록 하는 설계 원칙입니다.
목적:
- 코드의 모듈성 향상
- 유지보수성 개선
- 재사용성 증가
- 테스트 용이성 제고
주요 이점:
- 코드 복잡성 감소
- 변경의 영향 범위 최소화
- 병렬 개발 가능
적용 방법:
- 계층화 (예: 프레젠테이션, 비즈니스 로직, 데이터 접근 계층)
- 모듈화
- 인터페이스 사용
이제 코틀린으로 출퇴근 관리 시스템의 일부를 구현하는 예시를 들어보겠습니다:
// 데이터 액세스 계층
interface AttendanceRepository {
fun saveAttendance(employeeId: String, time: LocalDateTime, type: AttendanceType)
fun getAttendance(employeeId: String): List<Attendance>
}
class DatabaseAttendanceRepository : AttendanceRepository {
override fun saveAttendance(employeeId: String, time: LocalDateTime, type: AttendanceType) {
// DB 연결 및 저장 로직
}
override fun getAttendance(employeeId: String): List<Attendance> {
// DB에서 출퇴근 기록 조회 로직
return emptyList()
}
}
// 비즈니스 로직 계층
class AttendanceService(private val repository: AttendanceRepository) {
fun clockIn(employeeId: String) {
val now = LocalDateTime.now()
repository.saveAttendance(employeeId, now, AttendanceType.CLOCK_IN)
}
fun clockOut(employeeId: String) {
val now = LocalDateTime.now()
repository.saveAttendance(employeeId, now, AttendanceType.CLOCK_OUT)
}
fun getAttendanceHistory(employeeId: String): List<Attendance> {
return repository.getAttendance(employeeId)
}
}
// 프레젠테이션 계층 (예: REST API)
@RestController
class AttendanceController(private val attendanceService: AttendanceService) {
@PostMapping("/clock-in")
fun clockIn(@RequestBody request: ClockInRequest) {
attendanceService.clockIn(request.employeeId)
}
@PostMapping("/clock-out")
fun clockOut(@RequestBody request: ClockOutRequest) {
attendanceService.clockOut(request.employeeId)
}
@GetMapping("/attendance/{employeeId}")
fun getAttendance(@PathVariable employeeId: String): List<Attendance> {
return attendanceService.getAttendanceHistory(employeeId)
}
}
// 데이터 모델
data class Attendance(
val employeeId: String,
val time: LocalDateTime,
val type: AttendanceType
)
enum class AttendanceType {
CLOCK_IN, CLOCK_OUT
}
예시 설명
AttendanceRepository는 데이터 접근 관심사를 다룹니다. DB 연결 및 쿼리 실행에 대한 세부사항을 캡슐화합니다.
AttendanceService는 비즈니스 로직 관심사를 다룹니다. 출퇴근 기록 저장, 조회 등의 핵심 기능을 구현합니다.
AttendanceController는 프레젠테이션 관심사를 다룹니다. HTTP 요청을 처리하고 적절한 응답을 반환합니다.
이렇게 관심사를 분리함으로 얻는 이점
- 데이터베이스 구현을 변경해도 비즈니스 로직에는 영향을 주지 않습니다.
- 비즈니스 로직을 수정해도 프레젠테이션 계층에는 영향을 주지 않습니다.
- 각 계층은 독립적으로 테스트할 수 있습니다.
- 코드의 재사용성이 높아집니다 (예: 다른 프로젝트에서 AttendanceService 재사용 가능)
그러면 관심사 분리는 알았으니 무엇을 관심사로 부를수 있는가? 라는 의문이 생깁니다
무엇을 관심사로 부를수 있는가?
'관심사'란 소프트웨어의 특정 기능이나 목적을 의미합니다. 일반적으로 다음과 같은 것들을 관심사로 볼 수 있습니다:
- 기능적 요소: 특정 비즈니스 로직이나 알고리즘 등
- 데이터 관리: 데이터베이스 접근, 데이터 처리 등
- 사용자 인터페이스: UI/UX 관련 코드
- 보안: 인증, 권한 관리 등
- 로깅: 시스템 로그 기록
- 에러 처리: 예외 처리 및 오류 관리
- 통신: 네트워크 프로토콜, API 통신 등
- 설정 관리: 애플리케이션 설정 및 환경 변수 관리
- 성능 최적화: 캐싱, 메모리 관리 등
- 테스팅: 단위 테스트, 통합 테스트 등
이러한 관심사들을 분리함으로써 코드의 모듈성, 재사용성, 유지보수성을 향상시킬 수 있습니다. 각 관심사는 독립적으로 개발, 테스트, 배포, 수정될 수 있어야 합니다.
그렇다면 왜 관심사 분리가 중요할까요?
프로젝트는 아이디어에서 시작해 개발, 배포 단계를 거치면서 지속적인 요구사항으로 인해 점차 복잡한 시스템으로 발전합니다. 이러한 복잡한 시스템을 효과적으로 유지보수하려면 다양한 관심사들을 적절히 분리하여 관리해야 합니다. 이를 통해 필요한 부분을 고도화하는 것이 간단해지고, 유지보수에 들이는 시간을 줄여 새로운 요구사항 개발에 더 많은 시간을 할애할 수 있습니다.
이는 마치 집안의 물건들이 잘 정리정돈되어 있는 것과 같습니다. 물건들이 체계적으로 정리되어 있을수록 필요한 것을 쉽게 찾을 수 있고 사용하기도 편리해집니다. 소프트웨어 개발에서도 마찬가지로, 관심사가 잘 분리된 시스템은 더 효율적으로 관리되고 발전할 수 있습니다.
'디자인패턴' 카테고리의 다른 글
SOLID - SRP (0) | 2024.09.19 |
---|---|
전략패턴 (0) | 2024.06.16 |
템플릿 메서드 패턴 (0) | 2024.06.16 |