[너나드리] 글 조회 범위 선별 구조를 어떻게 가져가야 할까

eora21·2024년 3월 14일
0

너나드리 개발기

목록 보기
2/8
post-thumbnail

이전 글에서 구글맵의 줌 레벨에 따라 주변 탐색 로직을 둘로 나누었습니다(MySQL Geometry, H3).
이를 효율적으로 적용할 방법을 고민하고 있습니다.

OOP를 지킬 수 있는 구조

사용자의 구글맵 줌 레벨에 따라 선택되는 방법인 MySQL Geometry 탐색과 H3 탐색 모두 '범위 제한'으로 볼 수 있습니다. 줌 레벨이 12 이상일 때는 주변 x미터의 글만 조회하고, 11부터는 더 넓고 분할된 지역의 글들을 조회하기 때문입니다.

좀 더 명확히 표현해보겠습니다.
Geometry는 내부적으로 몇 m의 범위를 탐색할지 지니고 있으면 됩니다.
해당 범위만 검색 조건에 전달하면 되기 때문에, record로 만들어 사용하면 좋을 듯 합니다.

다만 H3는 DB에 각각의 필드가 존재하므로, enum으로 res 4와 res 6을 선언하겠습니다(실제 객체명이 아닌, 이해를 위해 간단하게 선언하겠습니다).
DB에서 조회할 때 사용되는 필드가 다르기 때문입니다.

글을 조회할 때 해당하는 범위 제한이 필요할 것입니다. 따라서 PostService의 메서드는 범위 제한 인터페이스를 내부 변수로 사용할 것입니다.
또한 PostService는 그렇게 구한 범위 제한을 PostRepository에게 넘겨 각각에 알맞는 쿼리를 동작시킬 것입니다.

예상되는 문제점

하위 클래스

PostService까지는 범위 제한 인터페이스만을 알고 있었으나, PostRepository에서는 하위 클래스인 Geometry, Resolution을 알아야만 알맞는 쿼리를 선별할 수 있습니다.

해당하는 OOP를 지키기 위해선 PostRepository가 각각의 하위 클래스를 알지 못 하게 해야 하므로, 이러한 참조 관계를 반대로 해 봅시다.

범위 제한 인터페이스에 PostRepository를 파라미터로 받는 메서드를 정의하고, 각각의 하위 클래스에서 어떤 메서드를 동작시킬 지 선언하면 될 것입니다.
다만, 이 또한 문제가 존재합니다.

오남용

PostRepository 자체를 파라미터로 받아 동작시킬 경우, 원래의 의도와는 다르게 각각의 클래스에서 사용해선 안 될 메서드를 동작시킬 가능성이 생겨버립니다.
예를 들면, Geometry 클래스에서 PostRepository의 save 메서드를 사용할 수 있게 됩니다. 이는 원래의 의도와는 매우 벗어난 형태이므로, 중간에 인터페이스를 두도록 합시다.

LocationDao를 선언하고 Location 조회를 위한 메서드만 골라 작성합니다. PostRepository는 LocationDao를 implement한 후 각각의 메서드를 구현합니다.

이렇게 되면 Geometry, Resolution에서는 PostRepository의 메서드를 함부로 동작시킬 수 없게 됩니다.

Resolution에서는 Res4와 Res6을 따로 구분해야 하므로 LocationDao의 H3 조회 메서드를 오버로딩하면 될 것입니다(비지터 패턴처럼 구현).

의문

여기까지 설계하면서 큰 의문이 생겼습니다.
과연 이게 올바른 구조일까? 라는 것입니다.

Geometry와 Resolution은 조회 쿼리를 다르게 분류하기 위함입니다. Dao를 넘기면서까지 이를 분류해야 할 지 확신이 서지 않았습니다.

조회를 위한 파라미터들은 조회 범위와는 무관한 것들이 존재할 수 있습니다. 사용자의 정보(사용자의 비공개 글들을 조회하기 위함), 페이징 처리 정보, 동적쿼리 등이 있을 수 있습니다.
위와 같은 구조라면 LocationDao에서 이러한 파라미터들을 알아야 하고, 각각의 클래스에서도 해당 파라미터 타입에 의존성이 생겨 버립니다. 물론 Service에서 제공한 파라미터들을 Dao에 단순히 전달하는 형태일 터이므로 큰 영향은 없을 수 있겠으나, 이 또한 마음만 먹는다면 각각의 파라미터에 영향을 주는 코드를 충분히 집어넣을 수 있으므로 오남용 가능성이 생기게 됩니다.

좀 더 쉬운 구조를 생각해본다면, PostService 혹은 PostRepository에서 getClass() 메서드를 사용해 하위 타입이 무엇인지 정확히 판단하고, 이를 통해 메서드를 동작시키면 (OOP가 상대적으로 약하더라도) 팀원들이 로직의 플로우를 따라가는 데 전혀 무리가 없을 것입니다.

결정

Geometry 조회와 Resolution 조회 구분은 변화 가능성이 매우 적은 부분이라 판단했습니다. 따라서 코드의 복잡도를 높이기보단, 보다 간단하게 로직을 작성하여 진행하기로 했습니다.
프로젝트 도입부부터 너무 깊은 고민에 의해 진행 속도가 늦어지는 건 모두가 바라지 않던 길이었습니다. 근시일내에 코드를 구축하도록 했습니다.

만약 추후 급격한 변화가 이루어진다면 그 또한 좋은 경험일 것입니다. 이 결정이 후회가 될 수는 있으나, 한 단계 성장하는 기회로 생각하기로 했습니다.

profile
나누며 타오르는 프로그래머, 타프입니다.

0개의 댓글