트러블 슈팅

상속 관계 매핑 전략

수달하나 2024. 6. 28. 09:55

기존의 정의된 일련의 로직을 수정하는 것은 어렵지만 그 중에서도 내가 가장 힘들었던 부분은 객체를 완전히 재정의 하는 부분이다.

물론 하나의 객체만 재 정의 한다면 크게 문제가 되지는 않겠지만 여러객체들이 서로 상호작용하거나 혹은 복잡한 상속 관계를 포함하고 있다면 얘기는 달라진다.

 

최근 하나의 테이블이 너무 많은 정보를 포함하고 있다는 생각이 들어서 리팩토링을 하기로 결정했고 어떠한 방식으로 테이블을 쪼갤 수 있을까를 고민했다.

 

테이블의 구조는 다음과 같다

A 부터 G 까지의 7가지 상태를 모두 단 하나의 테이블로 표현 할 수 있었다.

각 상태는 target 이라는 Enum 타입에 따라서 각자 상태의 종류를 구분 할 수 있는 형태였다.

target 에 따라서 필요한 필드 값이 모두 다르기 때문에 단일 테이블에서는 7개의 상태를 표현 할 수 있는 모든 필드 값들을 가지고 있어야 했다.

따라서 하나의 객체가 가지고 있는 필드들은 실제로 값이 존재하는 필드 보다 값이 존재하지 않는, null 값이 들어가 있는 필드 들이 더 많았다.

 

테이블은 복합키를 통해서 구분 되어졌다.

어떠한 상태를 나타내는지를 알 수 있는 target (enum) 정보와, String 타입의 associationKey 를 통해서 구분 할 수 있도록 복합키 형태로 구성되어졌다.

 

따라서 C 상태를 표현하기 위해서는 C 상태를 대표하는 target 정보와 객체를 구분하기 위한 association key 정보, 그리고 디테일한 정보를 담아내기 위한 filed B 와 field D 의 데이터가 필요했고 그 외의 정보는 모두 null 값이 들어가는 형태로 구성이 됬다.

 

위와 같은 형태는 7가지의 형태를 표현한 다는 점에서는 같은 책임을 지고 있지만 각자 다른 상태의 형태라는 점에서 단일 책임을 수행하고 있다고 생각되지 않았다.

객체 지향적 설계를 위한 가장 대표적인 특징이 하나의 단일 책임을 갖도록 해야 한다는 것 인데 중요한 부분은 하나의 행동 주체가 하나의 책임을 져야 한다는 것.

따라서 위와같은 설계 방식은 단일 책임 원칙을 위배하고 있다는 생각이 들었기 때문에 전체적인 구조를 변경하는 과정이 반드시 필요하다고 생각했다.

 

 

첫 번째 

 

 

가장먼저 생각한 방법은 각각의 상태를 나타내는 테이블을 개별적으로 정의하는 것 이었다. 

각 상태가 공통적인 역할을 하는 것은 분명하다.

 

하지만 그 역할을 수행함에 있어서 책임의 소재가 분명히 다르고 특정 로직에 있어서 크게 영향을 줄 수 있다면 테이블 자체를 분리해서 관리하는 것도 하나의 방법이라는 생각이 들었다.

 

하지만 결과적으로 이러한 방법은 채택될 수 없었다.

이 방법의 문제는 기존 프로세스의 너무 큰 성능저하를 발생시키기 때문이었다.

기존의 프로세스는 각각의 상태를 종합하여 통계를 내야하는 과정이 필요했는데 이러한 측면에서 기존의 테이블 전략은 효율적 처리가 가능한 반면 위와 같은 전략은 각각의 테이블에 접근하여 통계를 내야 했기에 DB 접근의 빈도수가 높아지고 그에따른 성능저하가 발생할 수 있기 때문이었다.

 

두 번째

 

 

두 번째로 생각한 방식은 조인 전략이었다.

상위 테이블을 상속받은 하위 테이블을 생성하여 공통적으로 사용하는 필드는 상위 테이블에 위치시키고 각각의 상태를 표현 할 수 있는 정보들은 하위 테이블에 위치키는 방식으로 구성했고 이러한 방법은 기존의 통계를 구하는 로직에 있어서 큰 영향을 미치지 않았다.

 

 

 

 

-> 개수적으로 많이 나오는 컬럼이 아니기 때문에 이런식으로 굳이 테이블을 늘려서 관리범위를 확장하는것이 과연 옳은것일 까 라는 생각을 하게됨.

+ 각각의 필드들은 단순히db 에서 값을 가져와서 쓰는것 뿐 아니라 그 후에 후처리를 해야 하기 때문에 위와같이 필드의 값을 직접 삽입하는 방식이 비효율적이라는 생각을 하게 됨.

 

마지막 해결 책