티스토리 뷰
안녕하세요~ 오늘은 19년도에 올라온 영상이지만 아직까지도 도메인 설계에서 주력으로 사용하고 있는 내용을 잘 설명해주시고 있는 우아한테크세미나 영상을 하나 가져왔습니다. 바로 우아한형제들의 개발실장님이신 조영호님께서 올려주신 내용입니다.
이 영상에서는 JPA를 활용하여 어떻게하면 Dependency, 즉 의존성을 최소화하고 대용량 데이터를 트랜잭셔널하게 핸들링할 수 있는 도메인 설계 방법에 대해 올려주셨었는데, 아직까지도 공부를 하고 있는 저에게 있어 많은 도움이 되서 공유 링크를 올립니다 :)
https://www.youtube.com/watch?v=dJ5C4qRqAgA
해당 내용에서는 ORM 기법을 사용하여 사용하고 있는 Java 내용을 '주문' 이라는 비즈니스 로직에 빗대어 설계를 한 프로세스 과정과 그 과정을 코드로 어떻게 묘사를 하였는지, 그리고 의존성을 낮추기 위한 방법 (응집도를 높이고 결합도를 낮추는 소프트웨어적 설계 방법)에 대해 묘사를 해주셨습니다.
객체 간의 참조가 많이 되어 있는 경우, 즉 A와 B의 연관관계가 있을 때 A객체가 수정되었을 때 B객체가 수정되는 것을 방지하기 위해 객체 참조를 많이 끊어주는 것이 효율적인 프로그래밍 방법이라고 합니다. 실제로 A : B = 1 : n 일 때 A class 내의 Collection으로 B를 가지고 있는 것 보다(@OneToMany) B 객체 안에 A객체를 하나 가지고 있는 방법이 효율적입니다. (@ManyToOne)
Repository 안에 검색 방법을 넣는 것도 결합도를 낮추는 좋은 방법 중에 하나라고 합니다. Shop을 조회하기 위해 order를 활용해야 하는 경우 Shop class 내에 order 객체를 List로 넣는 것보다 Order class에 shop 객체를 가지고 있는 방법인 예제입니다. 즉, 인터페이스를 적극 활용하여 결합도를 낮추는 것이죠.
이는 트랜잭션과도 연관관계가 깊은데요, 사실 서버의 입장으로서 트랜잭션을 관리한다는 것 자체가 엄청난 리소스를 소모하는 일이고 특정 쿼리에서 병목이 걸렸을 때 이를 해소하기 위한 방법을 찾기보다는 애초에 개발 과정 중에 ORM 구성을 명확히 하여 Lazy Loading을 주력으로 트랜잭션을 관리하는 방법이 훨씬 효율적이기 때문입니다.
그래서 우리는 이러한 트랜잭션 관리를 하기 위한 방법으로 '조회 경계'라는 단어를 사용합니다.
MongoDB 의 경우 다음과 같이 계층형 구조로 이루어져 있는 것이 아닌 컬렉션의 형태로 되어 있어 조회를 하는데 큰 무리가 없이 Fetch Join 의 쿼리로 나가도 리소스 영향도가 적습니다. 하지만 MySQL의 경우는 RDBMS이다 보니 실체가 다소 다릅니다. 적어도 2번의 Join이 되어 있고 주문옵션들의 리스트가 많은 경우 테이블은 여러 차례 조회가 되며 하나의 트랜잭션의 단위가 되어 순차적으로 쿼리가 작동합니다.
객체 참조가 떨어지다 보니 아무래도 Entity 클래스 안에서 참조를 하여 검증하는 로직이 컴파일 에러가 날 수 있는데 이런 경우에 대한 해결 방법입니다.
그 말은 즉슨, 객체 지향 프로그래밍 보다 절차 지향 프로그래밍이 도메인 설계를 하는 입장에서는 더 유리할 수 있다는 점으로 들리는데, 실제로 MySQL은 절차 지향형으로 쿼리가 작동하는 DBMS이다 보니 일맥 상통하는 말이기도 하네요.
다른 한가지의 해결 방법은 도메인 이벤트를 퍼블리싱하여 주문 안에 배달과 가게에 대한 서비스를 핸들링하는 방법입니다.
하지만 이런 경우에도 문제가 발생하는 프로세스 부분이 바로 서로 서비스간 호출하여 발생하는 의존성 사이클입니다. 즉, order 계층과 delivery 계층이 서로를 호출하는 구조로 이루어져 있는 현상이 발생하는 것이죠.
이를 해결하는 프로세스 로직은 애초에 delivery 계층에 서비스를 구성하여 order가 delivery를 호출하지 못하도록 재구성하는 방법이 있습니다. 쉽게 말해 순환 참조되는 것을 원천적으로 차단하는 방법입니다.
오늘은 이러한 예제를 통해 객체 상호간의 의존성을 낮추고 응집도를 높이는 도메인 설계 방법과 실제로 그러한 케이스에 대해서 살펴보았습니다. 저에게는 낯선 도메인 설계이다 보니 현업에서도 직접 도입을 하면 성능적으로도 발전하는 부분이지만, 개인적으로도 앞으로의 개발 방향성을 잡는 데에 많은 도움이 된 방법이라고 생각합니다. 보다 명확한 내용이 궁금하신 분들은 영상 링크를 참조하였으니 시간이 되실 때 봐주시면 좋을 것 같아요. 읽어주셔서 감사합니다!
https://www.youtube.com/watch?v=dJ5C4qRqAgA
'Server' 카테고리의 다른 글
Jenkins 글로벌 변수 설정하기 (1) | 2022.03.14 |
---|---|
Spring Batch 실행 명령어 (0) | 2022.03.13 |
Ktor 프레임워크 공부하기 (1) | 2022.03.12 |
[Java] JPA Detached Entity passed to persist 에러 해결 로그 (2) | 2022.02.14 |
[Java] Rest Template 을 사용하여 API 통신하기 (1) | 2022.02.07 |
[Java] Encode, Decode 함수 사용하기 (4) | 2022.02.04 |