좋은 설계란 시스템의 요구 사항이나 변경사항이 있을 때, 영향을 받는 범위가 적은 구조를 말한다. 그래서 시스템에 예상하지 못한 변경사항이 발생하더라도, 유연하게 대처하고 이후에 확장성이 있는 시스템 구조를 만들 수 있다.
객체 지향 프로그래밍을 설계하면서 SOLID OOP 설계 원칙을 적용하게 되면, 코드를 확장하고 유지보수가 쉬워지며, 불필요한 복잡성을 제거해 개발의 생산성을 높일 수 있다.
SOLID
SOLID 원칙이란 객체 지향 설계에서 지켜줘야 할 5개의 소프트웨어 개발 원칙을 말한다.(SRP, OCP, LSP, ISP, DIP)
- SRP(Single Responsibility Principle) : 단일 책임 원칙
- OCP(Open-Closed Principle) : 개방 폐쇄 원칙
- LSP(Liskov Substitution Principle) : 리스코프 치환 원칙
- ISP(Interface Segregation Princple) : 인터페이스 분리 원칙
- DIP(Dependency Inversion Principle) : 의존관계 역전 원칙
SRP
SRP(Single Responsibility Principle)은 "단일 책임 원칙"으로 클래스나 모듈은 하나의 책임 또는 역할만 가져야 한다.
즉, 한 클래스는 한 가지 기능 또는 책임에 집중되어야 한다.
이를 통해 코드의 가독성, 유지보수성, 재사용성이 향상된다.
Ex)
회원 관리 기능을 담당하는 Member 클래스는 회원 정보를 저장하고 조회하는 역할을 수행한다.
만약 Member 클래스가 로그인 기능, 이메일 전송 기능도 담당한다면, SRP에 어긋나게 된다.
이 경우, Member 클래스는 단일 책임을 가지도록 분리하여,
회원 관리에 집중하는 Member 클래스, 로그인 및 이메일 전송 등의 다른 기능을 담당하는 별도의 클래스로 분리할 수 있다.
OCP
OCP(Open-Closed Principle)은 "개방 폐쇄 원칙"으로 기존의 코드를 수정하지 않고도 기능을 확장할 수 있도록 설계해야 한다.
이를 통해 코드의 안정성과 확장성이 증가한다.
Ex)
결제 처리 기능을 담당하는 Payment 클래스는 신용카드 결제 기능만을 처리하고 있다.
그런데 나중에 현금, 모바일 결제 등의 다른 결제 수단을 추가하고자 한다면, 기존의 Payment 클래스를 수정하는 것은 OCP에 어긋난다.
그렇기 때문에, 새로운 결제 수단을 처리하는 클래스를 추가하고, Payment 클래스의 추상화된 인터페이스를 통해 확장성 있게 처리할 수 있다.
LSP
LSP(Liskov Substitution Principle)는 "리스코프 치한 원칙"으로 자식 클래스는 언제나 부모 클래스의 자리르 대체할 수 있어야 한다.
즉, 상속 관계에서 자식 클래스는 부모 클래스의 기능을 확장하거나 변경하지 않고, 일관된 방식으로 사용될 수 있어야 한다.
이를 통해 다형성과 유연성이 확보된다.
Ex)
상속 관계에서 부모 클래스인 Animal이 있고, 이를 상속받는 자식 클래스로 Dog와 Cat이 있다.
LSP에 따르면 Animal 객체를 사용하는 코드에서는 Dog나 Cat 객체로 대체해도 문제가 없어야 한다.
즉, Animal 객체의 메서드를 사용하는 코드는 Dog나 Cat 객체에서도 동일하게 작동해야 한다.
ISP
ISP(Interface Segregation Principle)은 "인터페이스 분리 원칙"으로 클라이언트는 자신이 사용하지 않는 인터페이스에 의존하도록 강요받지 말아야 한다.
즉, 큰 덩어리의 인터페이스를 작은 단위로 분리함으로써, 클라이언트는 필요한 인터페이스만 사용할 수 있게 된다.
이를 통해 결합도를 낮추고, 인터페이스의 재사용성과 유연성을 향상시킬 수 있다.
Ex)
회원 관리 기능을 담당하는 인터페이스인 MemberService는 회원 등록, 회원 조회, 회원 삭제 등의 메서드가 정의되어 있다.
그런데 회원 삭제 기능을 사용하지 않는 다른 기능에 경우, ISP에 따라 MemberService 인터페이스를 적절히 분리하여, 회원 삭제 기능을 담당하는 별도의 인터페이스를 만들고, 필요한 기능만 사용할 수 있도록 인터페이스를 분리할 수 있다.
DIP
DIP(Dependency Inversion Principle)는 "의존성 역전 원칙"으로 고수준 모듈은 저수준 모듈에 의존해서는 안되며, 양쪽 모듈 모두 추상화에 의존해야 한다.
즉, 추상화를 통해 상위 수준의 모듈과 하위 수준의 모듈 간의 의존성을 역전시켜야 한다.
이를 통해 모듈 간의 결합도를 낮추고 유연성과 확장성을 향상시킬 수 있다.
Ex)
자동차와 타이어의 관계를 생각해 보자. 타이어는 소모품이고, 계절에 따라 교체될 수 있다.
따라서 자동차와 타이어의 관계를 설정할 때 자동차가 스노우타이어라는 구체적인 클래스를 의존하는 ㅇ것보단, 스노우타이어, 일반 타이어, 광폭 타이어가 구현하고 있는 타이어라는 인터페이스를 새로 정의하고, 자동차는 타이어 인터페이스를 의존하게 하는 것이 좋다.
실전
Q. SOLID 원칙에 대해 설명해 주세요.
A. 객체 지향 프로그래밍을 설계할 때 지켜줘야 할 5개의 설계원칙을 말합니다. SRP, OCP, LSP, ISP, DIP가 있으며 SRP는 단일 책임 원칙으로 클래스나 모듈은 하나의 책임만 가져야 합니다. OCP는 개방 폐쇄 원칙으로 기능 확장에는 열려 있고, 변경에는 닫혀 있어야 합니다. LSP는 리스코프 치환 원칙으로 하위 타입은 상위 타입을 대체 가능해야 합니다. ISP는 인터페이스 분리 원칙으로 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺도록 강요받지 않아야 합니다. DIP는 의존관계 역전 원칙으로 의존 관계는 추상화에 의존해야 하며, 구체화에는 의존하지 않아야 합니다.
참고
'멋진 개발자 > ETC..' 카테고리의 다른 글
개발자 성장 기록 62 - OAuth (0) | 2024.05.22 |
---|---|
개발자 성장 기록 41 - 단위 테스트와 TDD(테스트 주도 개발) (0) | 2024.04.06 |
개발자 취준 기록 36 - 프로세스와 스레드 (0) | 2024.03.31 |
[항해 취업코스] 개발자 취준 기록 26 - 객체 지향 프로그래밍 (0) | 2024.03.20 |