객체지향, 관계형 데이터베이스 패러다임의 불일치로 인해 우리는 추가적인 작업을 해야한다. 객체를 관계형 데이터베이스에 저장하고 꺼내오기 위해서는 객체를 테이블로, 테이블을 객체로 매핑하는 작업이다. 이런 매핑 작업은 크게 의미있지도 않고, 시간도 오래 걸리고, 지루하다. 또한 테이블 구조가 변경되면, 코드의 모든 SQL문을 변경된 테이블 구조에 맞게 수정해야한다.. 100개의 테이블이 존재한다면, 100개의 CRUD 코드가 필요할 것 이다.
SQL 중심으로 코드를 작성하면, 객체의 구조를 테이블에 맞춰야 한다.
객체는 자유롭게 객체 그래프를 탐색해야하지만, 테이블 행의 ID를 통한 간접 참조는 이를 불가능하게 한다. 물론 Join 쿼리등을 사용하여 객체가 객체를 참조하는 모양으로 객체를 생성할수는 있겠으나, 쉽지 않다. 즉, 객체간 참조를 통한 연관관계 설정이 어렵다
객체의 연관관계가 많아질수록 DAO의 쿼리문 또한 계속해서 비대해질 것 이고, 유지보수가 어려워질 것 이다. 또한 성능상으로도 손해일 것 이다. 따라서 필요한 데이터만 조회하는 메서드를 만들어야하는데, 이 또한 유지보수성이 좋지 않다.
실제 객체간의 연관관계와 상관없이, 쿼리문에 따라 객체 그래프의 탐색 범위가 제한된다. 실제 객체 그래프와 관련 없이, 실제 쿼리문이 어떤 테이블을 가져오느냐에 따라 탐색할 수 있는 범위는 제한
된다. 이런 문제는 아래의 문제를 낳는다. 코드를 살펴보자.
User user = userDao.find(userId);
user.getOrder(); // 어떤 값일까?
user.getAddress().getZipCode(); // NPE가 발생하진 않을까?
위 코드를 안전하게 사용하려면, getAddress
를 호출하는 개발자가 userDao.find()
가 내부적으로 Address
테이블과 Join 하여 쿼리를 하는지 확인해야한다. Address
테이블과 Join 하지 않는다면, user.getAddress()
의 반환값은 null
일 것 이다. 즉, 엔티티를 신뢰할 수 없는 문제가 발생한다.
레이어드 아키텍처에서는 다른 레이어가 정상적으로 동작한다는 신뢰가 있어야 한다. 하지만, 위와 같이 신뢰가 깨져버린 상황에서는 비즈니스 레이어에서 영속 레이어의 내부 구현을 알고있어야 한다. 따라서 진정한 의미의 계층 분할이 어렵다.
객체답게 모델링 할수록 매핑 작업만 늘어난다. 객체를 자바 컬렉션에 저장 하듯이 DB에 저장하고 관리할 수 는 없을까? 객체지향과 관계형 데이터베이스간의 패러다임 불일치를 해결하고, SQL 중심적인 개발에서 벗어나 객체 중심으로 개발하기 위해 ORM (Object Relational Mapping) 이라는 기술이 등장하였다. 그리고 자바 진영에서는 JPA 라는 ORM 기술 표준이 존재한다.
참고 : SQL 중심적인 개발의 문제점