정말로 프로젝트가 커지면 data mapper가 유리할까?

Kenneth·2021년 1월 18일
4

active record orm or data mapper orm? 저한테는 vim or emacs? 같은 그저 취향이나 스타일을 묻는 질문으로 들립니다. 여러분은 어떠신가요.

글을 쓰게된 배경

active record 를 사용하다 data mapper로 넘어갔다같은 글도 있고, active record는 antipattern이고, data mapper가 당연히 유리하다고 하는 단정적으로 한 쪽을 채택하는 의견도 있습니다. 가끔 이렇게 검색해서 돌아다니다 보면, data mapper를 선호한다고 드러내는 글은 많아도 active record를 선호하는 글은 잘 없는 것 같습니다.

그래서 이 글에서는 의도적으로 (사심 한 스푼 담아) active record (이하 AR) 편을 들어보겠습니다.

Data mapper를 선호하는 글들을 읽어보면 대체로 이런 이유를 듭니다.

  1. AR에서는 business logic과 db access logic이 섞인다.
  2. AR에서는 객체지향적인 클래스 디자인이 어렵다.
  3. 프로젝트가 커지면 data mapper가 유리하다.

(혹시 또 다른 중요한 이유가 있다면 댓글에 남겨주세요.)

저는 저렇게 말하는 사람들이 왜 저렇게 생각하게 됐을까 고민해봤습니다.

pattern vs orm

active record pattern 과 active record orm은 좀 다릅니다. active record pattern에서는 db의 table 이 class, row 하나가 instance에 대응되고 instance를 통해서 데이터에 접근한다고 하지만, 실제 active record 기반의 orm은 그렇게만 작동하지 않습니다. 패턴과 orm을 혼동하면 곤란합니다. 이 글에서는 패턴이 아니라 orm에 주목하겠습니다.

왜 AR에서 business logic과 db access logic이 섞인다고 할까?

개인적으로 django orm을 쓰면서 이런 이슈를 잘 못 느껴서 몇 가지 추측을 해봤습니다.

  1. 스키마 변경이 잦을 경우?
    D팀장님께 배우는 동안은 db 스키마에 대한 작업은 반드시 충분한 검토를 거쳤고 웬만해서 변경은 잘 없었습니다. 변경 할 때 수정해야 할 파일이 많은 경우도 있었지만, IDE와 test의 보조로 특별히 대응하기 까다롭다는 생각은 들지 않았습니다.

  2. AR에서는 business logic 한가운데 db access logic이 반드시 들어간다는 오해.
    그렇지 않게 구현해도 전혀 상관 없습니다. 그렇게 구현하기 편하고, 특별한 경우가 아니라면 굳이 분리할 필요가 없어서 안할 뿐. 필요하면 부분적으로 data mapper와 유사한 형태로 추상화하면 되지요. business logic과 db access logic이 섞여서 불편한 경우가 생겼다면, 개발 실력이나 개발 스타일의 문제지 그게 orm 방식에서 비롯되는 구조적인 문제는 아닙니다.

왜 AR에서는 객체지향적인 클래스 디자인이 어렵다고 할까?

java스타일의 pure-oop 실무 경험은 없는 편이라 놓치는 부분이 있을 수 있습니다만.

AR orm이라고 해서 반드시 클래스와 DB가 1:1로 구성되지는 않습니다. 어느정도의 추상화나 객체지향적인 설계는 가능합니다.

저는 오히려 클래스와 DB가 완전히 분리되어있어야 할 정도의 상황은 어떤 상황일까 궁금합니다.

  • 이미 주어진 legacy db 위에 무언가 새롭게 만들 때?
  • 백엔드 엔지니어와 DB 엔지니어가 서로 다른 생각을 하면서 따로 작업할 때?

당장은 이 두 가지 경우가 떠오르는데, 둘 다 별로 좋은 상황은 아닙니다. 이런 상황을 만들지 않으면 - legacy DB는 한번 정리하고 넘어가면, 혹은 백엔드와 DB 엔지니어가 충분히 협의해서 작업하면, 피할 수 있습니다.

프로젝트가 커지면 data mapper가 유리하다.

프로젝트가 커진다는 말은 보통 코드베이스가 커지고, 사람이 늘어나고, 퍼포먼스를 신경써야 하는 단계라는 말과 동일하지요.

코드베이스가 커지면 data mapper가 유리할까요? 위에서 active record도 객체지향적인 디자인이 가능함을 확인했습니다. 사람이 늘어나면 data mapper가 유리할까요? 작업을 잘 나누면 무관합니다. 퍼포먼스를 신경써야 하면 data mapper가 유리할까요? 퍼포먼스를 위해 raw sql을 써야 한다면 그건 이미 ORM을 벗어났지요. data mapper에서만 직접 sql을 작성할 수 있는게 아닙니다.

그것도 아니라면 뭘 기준으로 유리하다고 해야하는 걸까요.

좀 다른 이야기

좀 올드한 느낌의 팀에서 백엔드 작업하는걸 짧게 견식(?)한 적이 있습니다. 데이터 관련 작업을 할 때, db 스키마부터 어떻게 변경할지 먼저 작업하고 그 다음에 테이블을 바라보는 클래스를 바꾸는 형태로 작업하는걸 보고 좀 놀랐었습니다. 거의 3nf 수준의 정규화를 하려고 항상 같이 쓰게 될 데이터를 별도 테이블로 쪼개는걸 보고 두번 놀랐었구요. db migration 코드 없이 수작업으로 마이그레이션 하는걸 보고 세번 놀랐었습니다.

이건 마치 db schema 내부적인 부분만을 생각하며 최적화를 해서 local maxima는 얻었을지언정 global maximum에서는 더 멀어진 듯, 서비스 레이어와 db 레이어가 비슷할 때 얻을 수 있는 편리함과 생산성에서의 이점이라던가, 예전만큼 중요하지 않은 제약 (테이블 사이즈 등)에 아직도 얽매인다거나, 별도의 dba가 있어 db에 대한 주도권이 없을 상황을 상정한다거나... 그런 접근법이나 작업방식이 익숙하다면 data mapper를 더 선호하지 않을까 하는 생각을 했었습니다.

비슷한 이야기 - strong typed 언어 vs script 언어

strong typed 언어와 script 언어의 취향 차이와도 좀 같이 가는 부분이 있는 것 같습니다. 아마 strong typed 언어를 선호하시는 분들은 data mapper를 선호하고, script 언어를 선호하시는 분들은 active record를 선호할 것 같습니다. 한번 투표에 붙여봐도 재미있겠네요.

결론, 뭣이 중헌디

그래서 제 지금의 결론은 스타일의 차이라는 것입니다.

제가 여태까지 개발했던 프로젝트들은 대체로 트래픽이 낮았고 정확하게만 구현되면 됐고, 퍼포먼스 최적화보다는 정확한 구현과 유지보수에 대한 필요성이 더 컸기 때문에 최적화된 로직의 가독성이 낮을 경우 의도적으로 포기하고 가독성을 더 살리곤 했습니다. 그게 회사에 더 큰 가치이기 때문입니다.

오해는 하지 말아주세요. 저도 개발자로서 최적화에 대한 열망(?)은 항상 있습니다. 10년 전 인턴 시절, CUDA (GPGPU)가 등장한지 얼마 안됐을 때 CUDA-C 코드최적화를 고민하며 성과를 냈을때는 가독성이 아닌 퍼포먼스가 KPI였기 때문에 적절한 문서와 주석 없이는 난해한 코드로 극한의 최적화를 추구해보기도 했습니다. 다만 퍼포먼스가 중요하지 않은 여러 개발 프로젝트에서는 좋은 설계와 명확함, 가독성 등이 더 가치있음을 알 뿐입니다.

상대적으로 data mapper쪽은 사용 경험이 적어서, 깊이 있게 써보게 된다면 다시 한번 이 글로 돌아와 첨언이나 자기반성을 해보도록 하겠습니다. :)

profile
개발자 + @

0개의 댓글