SQL Mapper와 ORM

Violet_Evgadn·2023년 4월 23일
0

DB연동

목록 보기
3/22
post-custom-banner

SQL Mapper 장단점

장점

불필요한 코드들을 줄일 수 있음

이는 SQL Mapper 뿐만이 아닌 ORM의 장점이기도 하다.

Persistence Framework의 장점이기 때문에 별다른 설명 없이 넘어가겠다.

SQL Query를 그대로 활용하기 때문에 복잡한 JOIN, 튜닝 등을 수월하게 할 수 있음

이 부분이 SQL Mapper가 가진 가장 큰 장점이다.

이전에 말했듯 ORM은 객체와 Table을 연결하는 기술로써, SQL 구문을 입력하지 않고서도 편한 DB 활용을 할 수 있다는 게 장점이었다.(물론 직접 SQL 구문을 입력하여 활용할 수도 있긴 하다)

하지만 이는 곧 단점이 될수 있는데 복잡한 JOIN문을 활용하는 상황에서는 자동으로 SQL 구문을 형성하는 ORM은 더욱 복잡한 Query문을 통해 결과문을 받아올 수도 있다.

예를 들어 나는 A Table에 접속하고 싶을 때 SQL을 통해서는 B 이후 바로 A에 접속 가능하지만 ORM 측에서는 B에서 C를 찾고 C 이후에 A를 찾는 과정으로 A Table에 접근하는 쿼리문을 만들 수도 있게 되는 것이다.

이런 면에서 SQL Mapper는 직접 SQL Query를 입력하기 때문에 튜닝과 복잡한 JOIN이 필요한 로직에 대해 매우 큰 장점을 가지고 있다.

동적 Query 생성에 유리

동적 쿼리란 상황에 따라 분기 처리를 통해 SQL을 동적으로 만드는 표기법이다.

예를 들어 A = True일 경우 SELECT * FROM A를 실행하고 A = False일 경우 SELECT * FROM B를 실행하는 등으로 분기 처리를 하는 것이다.

ORM은 이런 부분에 대한 메서드를 제공하지 않아 직접 if문을 Service Class 등 Java Code 쪽에 넣어줌으로써 동적 Query와 유사한 효과를 내지만 SQL Mapper 측에서는 , 등을 활용해 Query문에 조건문을 추가할 수 있다.

물론 현재로서는 동적 Query를 굳이 사용하지 않아도 된다고 생각해서 나중에 동적 Query의 장단점과 왜 사용하는가에 대해 한 번 정리할 필요가 있어 보인다.

단점

특정 DB에 종속적임

MyBatis를 활용한 프로젝트의 디렉터리 구조를 보자

위 디렉터리를 보면 mysql과 oracle 디렉터리가 따로 존재함을 알 수 있다.

MySQL과 Oracle의 Query 문법은 서로 다르고 SQL Mapper는 결국 "객체와 Query를 연결"하는 기술이기 때문에 Query가 다를 경우 각각의 DB 고유의 Query문을 형성해줘야 하는 것이다.

따라서 위 예시처럼 mysql과 oracle 디렉터리를 나눠 DB에 맞는 Query문을 작성하게 되는 것이다.

MySQL과 Oracle이 가장 대표적인 DBMS이기 때문에 2개만 형성했지만, 만약 훗날 새롭게 인기를 끄는 DBMS가 나온다면? 혹은 현재 잘 활용되지 않는 DBMS를 활용해야 하는 상황이 생긴다면?

그때마다 우리는 DBMS에 맞는 Query문을 형성해줘야 하는 불편함이 생길 것이다.

이런 단점은 개발이 DBMS에 의존적이라는 단점으로도 이어지게 된다.

DB 스키마 변경 시 수정할 부분이 너무 많아짐

Query문이라는 것은 결국 Table의 관계도에 비롯해서 생성되게 된다.

내가 A Table과 B Table을 Join으로 묶기 위해서는 먼저 A Table이나 B Table에 Foreign Key가 존재해야 할 것이다.

그런데 만약 상황이 변경되어 A Table과 B Table 사이의 직접적 연결이 없어지고, A Table과 C Table이 연결되고 C Table과 B Table이 연결되는 형식으로 구조가 바뀌었다고 가정하자.

이 경우 SQL Mapper에서 활용하는 Query문 자체도 모두 변경되어야 하기 때문에 DB 스키마가 변경될 경우 매우 많은 부분이 수정되어야 한다.


ORM 장단점

장점

개발자가 객체 모델만 활용하며 프로그래밍을 할 수 있음

ORM은 객체와 Table을 자동으로 연결해준다.

즉 ORM을 활용할 경우 SQL 구문이 아닌 클래스의 메서드를 통해 DB를 조작할 수 있게 되며 정해진 키워드를 활용하면 SQL 구문 없이도 데이터에 대한 처리가 가능해진다.

즉, 개발자는 최소한의 지식(키워드, 사용 방법)을 가지고서도 복잡한 Query문을 형성할 수 있게 되며 이에 따라 개발자는 Query문에 대한 고민 없이 오로지 애플리케이션 개발에만 집중할 수 있게 되는 것이다

DB에 종속적이지 않음

ORM은 Query문을 자동으로 생성해준다.

이때 ORM은 "내가 지정한 DB"에 따라 Query문을 자동으로 형성해준다.

즉, MySQL을 활용할 경우 MySQL Query 문법에 맞는 Query문을, Oracle을 활용할 때는 Oracle Query 문법에 맞는 Query문을 자동으로 생성해주는 것이다.

따라서 ORM을 활용할 때는 DB에 관계없이 오로지 "애플리케이션이 수행할 로직"에만 집중해 개발을 수행하면 되고, DB에 종속적인 개발이 이뤄지지 않는 것이다.

스키마가 변경되었을 경우의 처리 자동 수행

위에서 말했듯 SQL Mapper에서는 스키마가 변경될 경우 Query문이 변경되기 때문에 당연히 수정할 부분이 다수 생기게 된다.

하지만 ORM에서는 Query문을 ORM 측에서 자동으로 생성하기 때문에 스키마가 변경된다고 하더라도 이를 ORM 입장에서 인지하고 알아서 변경된 스키마에 적용할 수 있는 쿼리문으로 변동되게 된다.

즉, 스키마가 변동되더라도 수정할 부분이 거의 없다는 장점이 존재하는 것이다.

단점

러닝 커브의 존재

ORM을 활용하기 위해서는 알아야 할 것이 많다. 그런데 이게 참 신기한 부분이다.

ORM을 활용하는 이유는 DB를 몰라도 DB를 활용할 수 있다는 이유일 텐데, ORM을 제대로 활용하기 위해서는 DB를 누구보다도 잘 알고 있어야 한다. 약간 모순적인 상황이 되는 것이다.

즉, "학습 초기"에는 이렇게 쉬운 툴이 없는데 "중간 단계"에서는 이렇게 어려운 툴이 없는 것이다.

추가적으로 ORM은 "객체 지향적"인 프로젝트에 적절한 기술인데 예전에 만들어진 애플리케이션이 객체 지향적이라는 것을 보장할 수 없다. 만약 프로그램이 객체 지향적이지 않다면 프로그램 자체를 먼저 뜯어고쳐야 ORM을 활용할 수 있게 되며 이는 배보다 배꼽이 큰 상황을 가지고 올 것이다.

특히 Procedure가 많은 시스템의 경우 이를 객체로 바꿔줘야 하는데, 이는 생선성 저하를 가지고 오며 로직이 원하지 않는 방향으로 변경되는 리스크를 가져오기도 한다.

성능 및 세밀함이 떨어짐

ORM은 자동으로 Query문을 형성해주는데 이렇게 생성된 Query문이 꼭 최선의 선택이라고는 할 수 없다.

ORM이 짠 코드보다 DB 전문가가 직접 짠 Query문이 더욱 좋은 성능을 나타낼 수 있게 되는 것이다.

물론 ORM에서도 직접 Query문을 입력할 수 있는 기능이 존재하지만, MyBatis보다는 이런 기능이 덜 쓰이는 것이 사실이다.(직접 Query문을 만들지 않아도 된다는 편리함과 재사용성이 ORM을 활용하는 이유이기 때문)

즉, 최고의 성능을 낼 수 있도록 최단 거리를 통해 데이터를 찾는 Query문을 활용하는 데에 있어 ORM보다는 DB 전문가가 직접 짠 Query문을 활용하는 게 더 유리할 수 있다는 것이다.

N+1 Problem

N+1 Problem은 ORM(특히 JPA)를 활용하다 보면 꼭 따라오는 문제로, 1번의 쿼리를 날렸는데 추가로 N번의 쿼리문을 날려야 최종적인 결과를 얻을 수 있는 문제를 N번 + 1번의 쿼리문이 나와야 된다는 의미에서 "N+1 Problem"이라고 한다.

조금 어려울 수 있는데, 쉽게 말하자면 "1개 Query가 수행될 것이라고 생각했는데 생각지도 않게 N개의 Query문이 추가적으로 발생하는 경우" N+1 Problem이 발생했다고 말할 수 있다.

예를 들어보자.

가수는 여러 개의 노래를 부를 것이다. 이를 DB로 표현하면 Singer Table 1개당 여러 개의 Sing Table이 연결되어 있는 1:N의 관계를 가지게 될 것이다.

나는 여기에서 아이유에 대한 정보를 검색하고 싶다. 따라서 아무 생각 없이 Singer Table에서 아이유를 검색했다.

그런데 Singer Table은 Sing Table에도 연결되어 있으므로 Sing Table에서 아이유와 연결된 모든 노래 데이터를 검색하게 될 것이다.

즉, 나는 "아이유의 생일" 정보를 알고 싶어서 검색했기 때문에 1번의 Query문이 실행될 것이라고 예상되었지만 DB 측에서는 "아이유의 정보 + 아이유가 부른 노래"를 모두 검색하기 때문에 아이유의 정보(1번의 Query) + 아이유가 부른 노래(N번의 Query)가 발생하여 총 N+1번의 Query문이 실행된 것이다.

이 N+1 Problem에 대해서도 나중에 한 번 제대로 다뤄봐야겠다.


SQL Mapper와 ORM 둘 다 활용해야 하는 이유

소규모 프로젝트의 경우 ORM만 활용하는 Case도 많지만, 대규모 프로젝트가 진행될 때는 SQL Mapper와 ORM을 같이 활용하여 프로젝트를 진행하는 경우가 많다.

그렇다면 왜 두 영속성 프레임워크를 동시에 활용할까? 한 개만 활용하면 어떨까?

먼저 ORM만 활용하는 것에 대한 한계는 명확하다. "성능"

ORM은 내가 원하는 대로 Query문이 실행될지 안될지 예상할 수 없으므로 성능 예측이 힘들며, DB 전문가의 최적 Query보다는 떨어진 성능의 Query문이 실행될 가능성이 꽤 있다는 점에서 ORM만 활용한다는 것은 말이 안 되는 일이다.

SQL Mapper의 SQL을 직접 짤 수 있어 복잡한 JOIN문에 대한 강점이 있다는 것, 그리고 동적 Query를 만들 수 있다는 장점은 DB Schema가 방대하고 복잡한 대규모 프로젝트에서는 필수 불가결하다고 말할 수 있다.

그럼 ORM이 아닌 SQL Mapper만 활용해서 프로젝트를 짜는 것은 어떨까?

이 부분에 대해선 "실제로 SQL Mapper만 활용하는 것이 좋다"라고 생각하는 사람들도 있는 것 같다.

나는 이런 논쟁에 참여하기엔 너무나 멍청한 개발자이겠지만, 개인적인 생각으로는 ORM의 장점도 무시할 수 없다고 생각한다. 특히 "DB에 종속적이지 않다"라는 장점과 "스키마의 변경에 강하다"라는 장점은 생각보다 괜찮은 장점이라고 생각한다.

예를 들어 INSERT문을 실행하는 명령일 때 Null 값을 확인해야 한다고 가정하자. 이 때 Oracle은 NVL을 써야하고 MySQL은 IFNULL 명령어를 활용한다. 나는 그냥 INSERT 구문에서 Null값을 확인하고 싶을 뿐인데 2개의 구문 차이가 존재하므로 똑같은 INSERT문을 2개 만들어야 하는 것이다. 이는 SQL Mapper 측에서 동적 Query를 활용해 중복되는 Query 부분을 겨우 줄여놨는데, 다시 INSERT문이라는 간단한 Query 때문에 쿼리 사이즈가 방대해지게 되는 것이다.

또한 개발 초기 단계에는 Schema가 변경될 일이 많을 텐데, 이때 SQL Mapper만 활용한다면 계속해서 SQL Query를 바꿔줘야 할 것이다. 따라서 처음에는 ORM을 활용해서 동작 여부 및 로직에만 집중하다가 나중에 실제 서비스를 제공할 만큼 DB Table이 커지고 안정적이 되었을 때 그때부터 SQL Mapper를 활용해 SELECT문이나 복잡한 JOIN문을 SQL Mapper로 대체함으로써 성능을 점차 올리는 방식으로도 활용할 수 있을 것 같다.

그래서 SELECT 관련 Query에는 SQL Mapper를, 그리고 복잡한 Query문이 필요하지 않은 INSERT, DELETE, UPDATE 관련 Query는 ORM을 활용해 프로젝트를 진행한다면 상당히 유연하고 재활용성이 높은 프로젝트를 만들 수 있다고 생각한다.

이 SQL Mapper와 ORM을 동시에 활용하는 이유에 대해서는 상당히 많은 뇌피셜이 포함되어 있다. 이 부분에 대해서는 신봉하지 말고 SQL Mapper와 ORM을 찾아보고 직접 활용해보며 둘을 동시에 활용하는 것이 좋을까에 대해 깊이 고민해보는 시간을 가지면 좋을 것 같다.

(참고로 나는 웹 개발을 공부하기 시작했을 때 ORM만 활용해서 ORM만 있으면 충분하다고 생각했다가 SQL Mapper를 활용한 이후 2개를 모두 활용해야 좋은 애플리케이션을 만들 수 있겠다고 생각이 바뀐 사람이다)

아래 사이트는 ORM에 대한 논쟁 글이다. 상당히 재밌는 글이어서 한번 보는 것을 추천한다

https://okky.kr/article/286812

profile
혹시 틀린 내용이 있다면 언제든 말씀해주세요!
post-custom-banner

0개의 댓글