반응형
Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 디자인패턴
- 버전관리
- 데이터분석
- 빅데이터
- 네트워크보안
- 데이터구조
- 네트워크
- 컴퓨터과학
- 딥러닝
- Yes
- 보안
- 프로그래밍언어
- 인공지능
- 자바스크립트
- 컴퓨터공학
- 소프트웨어
- 머신러닝
- 사이버보안
- 프로그래밍
- 데이터베이스
- 알고리즘
- springboot
- 자료구조
- I'm Sorry
- 웹개발
- 컴퓨터비전
- 데이터과학
- 파이썬
- 클라우드컴퓨팅
- 소프트웨어공학
Archives
- Today
- Total
스택큐힙리스트
객체지향 × SOLID: UML로 한눈에 잡는 핵심 원칙 본문
반응형
“패턴은 결국 객체지향(OOP) 원칙이라는 튼튼한 그릇 위에 담긴다.”
클린 코드·디자인 패턴 공부를 시작할 때 가장 먼저 부딪히는 질문이 “왜 OOP가 그렇게 중요할까?”입니다. 답은 간단합니다. 캡슐화·상속·다형성이라는 세 축이 변화를 흡수하고, 그 위에 SOLID 5대 원칙이 “유지보수성”을 보증하기 때문이죠. 이번 글에서는 UML 다이어그램으로 관계를 시각화하고, 간단한 예제로 SOLID 원칙을 재구현하면서 개념-실천-코드의 세 박자를 맞춰보겠습니다.
1. UML로 보는 관계 표현 연습
1-1. 클래스 다이어그램 빠르게 그리기
- 식별할 객체: Order, Payment, Shipping
- 관계
- Order aggregates Payment
- Order associates Shipping
- PlantUML 예시
@startuml class Order { +id: Long +addItem() +confirm() } class Payment { +amount: Money +pay() } class Shipping { +address: String +ship() } Order o-- Payment Order --> Shipping @enduml
코드 없이도 팀원이 구조를 바로 파악할 수 있습니다.
1-2. 시퀀스 다이어그램으로 흐름 잡기
@startuml
actor User
User -> Order : place()
Order -> Payment : pay()
Order -> Shipping : request()
Shipping --> User : trackingNumber
@enduml
API 호출 순서, 외부 시스템 연동 포인트를 눈으로 확인할 수 있어 리팩터링 때 큰 힘이 됩니다.
2. SOLID 5대 원칙, 캡슐화·상속·다형성으로 재구현
예제 언어: Kotlin (Java 개발자라면 그대로 읽힙니다)
2-1. SRP ― 단일 책임 원칙
class InvoiceSaver {
fun save(invoice: Invoice) { /* DB 처리 */ }
}
class InvoicePrinter {
fun print(invoice: Invoice) { /* PDF 출력 */ }
}
Invoice를 저장하는 역할과 출력하는 역할을 분리해 변경 영향을 최소화했습니다.
2-2. OCP ― 개방·폐쇄 원칙
interface DiscountPolicy { fun apply(amount: Money): Money }
class FixedDiscount(private val value: Money): DiscountPolicy { /* ... */ }
class RateDiscount(private val rate: Double): DiscountPolicy { /* ... */ }
class Checkout(private val policy: DiscountPolicy) {
fun pay(amount: Money) = policy.apply(amount)
}
새 할인 정책을 추가해도 Checkout은 수정되지 않습니다.
2-3. LSP ― 리스코프 치환 원칙
open class Bird { open fun fly() { /* ... */ } }
class Sparrow: Bird()
class Ostrich: Bird() { override fun fly() = error("Can't fly") } // ❌
날 수 없는 타조(Ostrich)는 Bird 대신 FlightlessBird로 분리해 다형성을 보장하세요.
2-4. ISP ― 인터페이스 분리 원칙
interface Printer { fun print() }
interface Scanner { fun scan() }
class MultiFunctionPrinter: Printer, Scanner { /* ... */ }
class SimplePrinter: Printer { /* ... */ }
사용자는 필요한 기능만 구현된 인터페이스를 의존합니다.
2-5. DIP ― 의존 역전 원칙
interface MessageSender { fun send(msg: String) }
class EmailSender: MessageSender { /* ... */ }
class AlarmService(private val sender: MessageSender) {
fun alert() = sender.send("Warning!")
}
상위 모듈이 구체 클래스 대신 추상 인터페이스에 의존하여 테스트와 확장성이 높아집니다.
3. 직접 실천해보기
- 오늘 프로젝트의 핵심 도메인을 골라 클래스 다이어그램을 그려보세요.
- 흐름이 복잡한 기능 하나를 시퀀스 다이어그램으로 표현해보세요.
- 다이어그램을 보며 “SRP가 깨진 곳”, “OCP가 위협받는 부분”을 체크하고 작은 리팩터링부터 시작해보세요.
4. 마무리
객체지향은 설계를 “보기 좋게” 만드는 기술이 아닙니다. 변화에 견디는 튼튼한 뼈대입니다. UML로 구조를 시각화하고, SOLID 원칙을 코드에서 체득하면 디자인 패턴이 왜 필요한지 자연스럽게 느껴질 것입니다. 오늘 당장 UML 도구를 열어 설계의 첫 줄을 그려보세요!
반응형
'개발' 카테고리의 다른 글
확장에 강한 코드: OCP(개방·폐쇄 원칙) 한눈에 마스터 (0) | 2025.07.13 |
---|---|
SRP로 깨끗한 코드: 단일 책임 원칙 한 방 정리 (1) | 2025.07.13 |
파이썬 GIL, 정말 문제일까? ― 병목 원인과 미래 로드맵 (0) | 2025.07.13 |
카오스 엔지니어링으로 ‘예방형’ 포스트모템 쓰기: 장애 터지기 전에 복기하라! (0) | 2025.07.13 |
모놀리스→멀티모듈→마이크로서비스 전환 로드맵 (1) | 2025.07.12 |
Comments