정적 유틸리티 클래스 -> 인터페이스 기반 설계로: java에서 OCP 원칙을 적용

2024. 2. 5. 16:48Java

728x90

자바 개발자라면 누구나 효율적인 코드 구조와 객체지향적 설계의 중요성을 인식합니다.

특히, 게시물 추적 기능과 같이 데이터를 처리하고 분석해야 하는 경우,

코드의 재사용성과 확장성은 더욱 중요해집니다.

 

이 글에서는 DateBasedPostTracker 클래스를 예로 들어

정적 유틸리티 클래스와 인터페이스 기반 설계의 각각의 장단점을 탐구하고,

어떤 방법이 객체지향적인 설계 원칙, 특히 개방/폐쇄 원칙(OCP)을 더 잘 따르는지 논의해 보겠습니다.

DateBasedPostTracker 클래스 소개

DateBasedPostTracker특정 날짜에 게시된 해축겔 게시판의 정보를 가져오는 기능을 제공하는 클래스입니다.

이 클래스는 세 가지 주요 기능을 포함합니다.

DateBasedPostTracker 의 3가지 메서드

1. findFirstPage(String targetDate): 주어진 날짜에 해당하는 게시물이 처음으로 등장하는 페이지 번호를 찾습니다.

2. findLastPage(String targetDate): 주어진 날짜에 해당하는 게시물이 마지막으로 등장하는 페이지 번호를 찾습니다.

3. estimatePostCountForDate(String targetDate): 주어진 날짜에 생성된 총게시물의 수를 추정합니다.

이 메서드들은 웹 스크래핑 기술을 활용하여, 해외축구 갤러리에서 게시물 데이터를 추출하고 분석하는 데 사용됩니다.

초기 설계에서 이 클래스는 정적 메서드를 사용하는 유틸리티 클래스로 구현되었습니다.

하지만, 객체지향 설계 원칙을 고려하여 인터페이스 기반 설계로 전환하는 과정을 거쳤습니다.

정적 유틸리티 클래스의 한계

초기에는 DateBasedPostTracker라는 클래스를 통해

특정 날짜에 게시된 게시물의 수를 추정하는 간단한 유틸리티 기능을 구현했습니다.

이 클래스는 정적 메서드만을 포함하고 있었으며, 인스턴스 생성 없이 사용할 수 있었습니다.

public class DateBasedPostTracker {
    private DateBasedPostTracker() {}

    public static int estimatePostCountForDate(String targetDate) {
        // 구현...
    }
    
    public static int findFirstPage(String targetDate) {
        // 구현...
    }
    
    public static int findLastPage(String targetDate) {
        // 구현...
    }
}

그러나, 이 접근법은 확장성과 테스트 용이성 측면에서 제한적이라는 판단이 들었습니다.

정적 메서드는 오버라이드가 불가능하여 다양한 시나리오, 즉 변화에 취약하다고 생각했습니다.

또한 추후 테스트를 한다고 했을때 모킹이 어려워 단위 테스트 작성에 제약이 있을거라 생각했습니다.

OCP 원칙과 인터페이스 기반 설계

OCP 원칙은 소프트웨어 구성 요소(클래스, 모듈, 함수 등)가

확장에는 열려 있어야 하지만 변경에는 닫혀 있어야 한다고 말합니다.

이 원칙을 적용하기 위해, DateBasedPostTracker의 구현을 인터페이스 기반으로 전환했습니다.

public interface IDateBasedPostTracker {
    int estimatePostCountForDate(String targetDate);
    int findFirstPage(String targetDate);
    int findLastPage(String targetDate);
}

이 인터페이스를 구현하는 방식으로 클래스를 재설계함으로써, 다양한 데이터 소스나

알고리즘으로 쉽게 확장할 수 있는 구조를 마련했습니다.

이는 유연성을 대폭 향상하고, 테스트 과정에서도 다양한 구현을 모킹 하여 사용할 수 있게 만들었습니다.

결론: 어떤 방법이 더 객체지향적인가?

객체지향적인 설계는 유연성, 확장성, 유지보수성을 중시합니다.

정적 유틸리티 클래스는 간단한 기능을 빠르게 구현할 때 유용하지만,

복잡한 시스템에서는 OCP 원칙을 따르는 인터페이스 기반 설계가 더 많은 이점을 제공합니다.

 

인터페이스를 사용하는 설계는 시스템을 더 모듈화하고,

테스트 용이성을 향상하며, 장기적으로 유지보수와 확장에 더 효과적입니다.

따라서 복잡도가 높은 애플리케이션 개발에서는 인터페이스 기반 설계를 선호하는 것이 좋습니다.

둘다 길이다

하지만, 단순한 유틸리티 기능을 구현하는 경우에는 정적 유틸리티 클래스도 여전히 유용할 수 있습니다.

결국 중요한 것은 각각의 사례에 맞는 올바른 도구를 선택하는 것이 결국 정답이라고 생각합니다.

전체코드

https://github.com/xpmxf4/GalleryCrawler/tree/main/src/main/java/org/example/crawler/util

 

728x90