전략 패턴을 활용한 파일 암복호화 로직 리팩터링

전략 패턴을 활용한 파일 암복호화 로직 리팩터링

들어가며

최근 프로젝트 내 파일 암호화 솔루션을 기존 DRM에서 새로운 MIP로 전면 교체하는 작업을 진행했습니다.

단순히 모든 파일만 MIP로 처리한다면 간단했겠지만, 과거에 다운로드된 기존 DRM 파일들의 업로드 호환성도 함께 유지해야 하는 것이 요구사항에 있었습니다. 즉 파일 업로드 시 DRM과 MIP라는 두 가지 암복호화 체계가 공존하며 상황에 맞게 동작해야 했습니다.

이러한 요구사항을 기존 구조에 억지로 맞추다 보니 여러 한계에 부딪혔고, 이를 전략 패턴을 통해 객체지향적으로 리팩터링한 경험을 공유하고자 합니다.

기존 코드의 문제점: static 유틸리티의 한계

기존 파일 암복호화 로직은 공통 유틸리티 클래스 내에 static 메서드로 굳어져 있었습니다.

당장의 요구사항만 처리하려면 내부에 단순 분기문을 추가할 수도 있었지만, 저는 이 방식을 유지할 경우 다음과 같은 구조적 문제들이 발생할 것이라고 판단했습니다.

  1. 산탄총 수술의 위험성과 높은 결합도 : 암복호화 로직을 호출하는 비즈니스 로직이 12곳이 넘었습니다. 기존 방식을 유지하면 암호화 방식이 추가되거나 변경될 때마다 12곳을 일일이 찾아가서 코드를 수정해야 하는 전형적인 산탄총 수술 현상이 발생하여 시스템이 매우 경직됩니다.
  2. 파라미터의 통일성 및 확장성 부족 : DRM과 MIP는 요구하는 파라미터가 서로 다릅니다. 이를 단일 함수에서 개별 인자로 받으면, 새로운 솔루션 도입 시마다 메서드 구조가 변하고 기존 호출부가 모두 깨집니다. 따라서 파라미터들을 하나의 DTO 클래스로 묶어 통일성을 부여해야만 유연한 확장이 가능합니다.
  3. 단위 테스트 작성의 어려움 : static 메서드는 객체의 상태를 가지지 않아 Mocking이 매우 까다롭기 때문에, 이를 의존하는 핵심 비즈니스 로직의 독립적인 테스트 코드 작성을 어렵게 만듭니다.

해결 방안: 전략 패턴을 통한 변하는 것과 변하지 않는 것의 분리

비즈니스 로직은 요구사항에 맞춰 동적으로 변해야 하는데, 기존의 정적인 구조로는 여러 문제를 발생시킬 것 같았습니다. 이러한 문제들을 근본적으로 해결하기 위해, 디자인 패턴의 원칙인 변하는 것과 변하지 않는 것의 분리를 적용하여 아키텍처를 재설계했습니다.

이를 시스템에 가장 자연스럽게 녹여 내기 위해 전략 패턴을 도입했고, 암복호화 시스템의 책임과 역할을 다음과 같이 명확히 나누었습니다.

  • 변하는 것: DRM, MIP 등 향후 교체되거나 추가될 수 있는 구체적인 암복호화 알고리즘
  • 변하지 않는 것: 파일을 암호화하고 복호화한다는 행위 자체와 데이터를 전달하는 통합 파라미터 규격

결과적으로 변하는 알고리즘들을 구체적인 클래스에 직접 의존하게 두지 않고 인터페이스로 추상화했습니다. 이를 통해 12곳의 클라이언트 로직이 구체적인 암호화 방식에 얽매이지 않고도 유연하게 동작할 수 있는 구조로 변경했습니다. 즉 Interface로 암호화, 복호화, 어떤 암호화되어 있는지 등의 메서드를 만들고 MIP, DRM의 클래스에서 상속하여 기능들을 구현하여 스프링 빈으로 등록 후 다른 모듈에서도 편하게 쓸 수 있도록 변경하여 이를 해결했습니다.

마무리 및 기대 효과

이번 리팩터링을 통해 12곳의 클라이언트 코드는 자신이 어떤 알고리즘을 쓰는지 모른 채 FileEncryptor라는 암호화클래스만 호출하면 되는 개방-폐쇄 원칙을 달성했습니다.

딱딱한 static 메서드를 걷어내어 단위 테스트 작성이 수월해졌고, 훗날 제3의 암호화 솔루션이 도입되더라도 기존 서비스 로직은 단 한 줄도 수정할 필요가 없는 유연한 아키텍처가 완성되었습니다. 단순히 눈앞의 분기 처리를 넘어, 추후 유지보수를 담당할 동료 개발자들을 위해 시스템의 확장성을 치열하게 고민해 본 값진 경험이었습니다. 감사합니다.

pong