객체 지향 프로그래밍(OOP) 5원칙(SOLID)을 실무 코드에 녹여내는 법
"객체 지향적으로 코드를 짜라"는 말은 개발자들에게 가장 익숙하면서도 막연한 조언입니다. 그 핵심에는 SOLID라고 불리는 5가지 원칙이 있습니다. 하지만 시험 공부하듯 외운 정의는 실무에서 큰 도움이 되지 않습니다. 복잡한 요구사항이 빗발치는 현업에서, 유지보수가 쉽고 변경에 유연한 코드를 만들기 위해 SOLID 원칙을 어떻게 적용해야 하는지 구체적인 사례와 함께 살펴봅니다.
SRP(단일 책임 원칙): 클래스는 단 하나의 이유로만 변경되어야 한다
하나의 클래스가 너무 많은 일을 하고 있지는 않나요? 사용자 관리 클래스가 DB 저장부터 로그 출력, 이메일 발송까지 다 하고 있다면 SRP 위반입니다. 책임을 분리하면 특정 기능을 수정할 때 다른 기능이 망가질 걱정을 덜 수 있습니다. "이 클래스가 하는 일을 한 문장으로 설명할 수 있는가?"를 자문해 보세요.
OCP(개방-폐쇄 원칙): 확장은 열려 있고 수정은 닫혀 있어야 한다
새로운 기능을 추가할 때 기존 코드를 수정해야 한다면 OCP 위반입니다. 인터페이스나 추상 클래스를 활용하세요. 예를 들어 결제 시스템에서 '카카오페이'를 추가할 때, 기존 결제 로직을 건드리지 않고 '결제 인터페이스'를 상속받은 새 클래스를 만드는 것이 정석입니다.
LSP(리스코프 치환 원칙): 자식은 언제나 부모를 대체할 수 있어야 한다
상속 관계에서 자식 클래스가 부모 클래스의 규약을 어겨서는 안 됩니다. 부모가 할 수 있는 일은 자식도 똑같이 (혹은 더 잘) 할 수 있어야 합니다. 만약 자식 클래스에서 특정 메서드를 구현할 때 UnsupportedOperationException을 던지고 있다면, 그것은 잘못된 상속 설계의 강력한 신호입니다.
ISP(인터페이스 분리 원칙): 쓰지 않는 메서드에 의존하지 마라
거대한 인터페이스 하나보다는 구체적인 여러 개의 인터페이스가 낫습니다. '스마트폰' 인터페이스에 '통화', '문자', '무선충전'이 다 들어있다면, 무선충전 기능이 없는 구형 폰도 이를 억지로 구현해야 합니다. 기능을 쪼개어 필요한 인터페이스만 골라 구현(implements)하도록 설계하십시오.
DIP(의존 역전 원칙): 고수준 모듈은 저수준 모듈에 의존해서는 안 된다
구체적인 구현체(Class)가 아니라 추상화(Interface)에 의존하라는 뜻입니다. 연극 배우(구현체)가 바뀌어도 대본(인터페이스)은 변하지 않는 것과 같습니다. 이렇게 하면 하부 시스템(DB 종류, 외부 API 등)이 바뀌더라도 상위 비즈니스 로직은 영향을 받지 않고 평온을 유지할 수 있습니다.
실무 적용의 적: 과도한 추상화
SOLID를 지키려다 오히려 코드가 너무 파편화되고 복잡해지는 경우가 있습니다. 무조건적인 원칙 준수보다는 '변경의 가능성'을 먼저 따져보세요. 평생 바뀔 일이 없는 코드라면 굳이 복잡한 추상화를 도입할 필요는 없습니다. 실무는 이론과 타협점 사이의 예술입니다.
코드 리뷰에서의 SOLID 활용
동료의 코드를 볼 때 "이 원칙을 어겼네요"라고 비난하기보다, "이 부분을 인터페이스로 뽑으면 나중에 기능 확장할 때 편할 것 같아요"라고 제안해 보세요. SOLID는 누군가를 평가하기 위한 잣대가 아니라, 팀 전체의 코드 품질을 높이기 위한 공용 도구입니다.
테스트 코드와 SOLID의 상관관계
SOLID 원칙이 잘 지켜진 코드는 테스트하기가 매우 쉽습니다. 특히 DIP가 적용되어 있으면 외부 환경을 모킹(Mocking)하여 독립적인 단위 테스트를 수행할 수 있습니다. 만약 테스트 코드 작성이 너무 힘들다면, 여러분의 코드가 SOLID 원칙을 어기고 있지는 않은지 점검해 볼 때입니다.
리팩토링의 나침반으로 삼기
처음부터 완벽한 SOLID 코드를 짜기는 어렵습니다. 일단 동작하는 코드를 만든 후, 중복이 보이고 수정이 어려워지는 지점에서 SOLID 원칙을 하나씩 대입해 보며 리팩토링하세요. 코드가 서서히 정돈되는 쾌감을 느낄 수 있을 것입니다.
객체 지향의 본질: 메시지를 주고받는 객체들
결국 SOLID의 목표는 객체들이 서로 적절한 거리(결합도 낮춤)를 유지하면서 명확하게 소통(응집도 높임)하게 만드는 것입니다. 원칙 그 자체에 매몰되기보다, "어떻게 하면 다음 달의 내가 이 코드를 보고 욕하지 않을까?"를 고민하다 보면 자연스럽게 SOLID에 가까워진 자신을 발견하게 될 것입니다.
SOLID 원칙을 실무에 녹여내는 과정은 고통스럽지만 그 열매는 답니다. 깔끔한 설계는 개발자의 스트레스를 줄여주고 제품의 생명력을 연장합니다. 오늘 여러분의 코드 한 줄에 SRP 원칙 하나만이라도 적용해 보는 것은 어떨까요?
댓글
댓글 쓰기