ORM? 난 직접 짤래
처음에는 해결하고자 하는 범위가 작기 때문에 ORM이 필요없다고 생각했다.
쿼리는 직접 짜면 되고, 오히려 환경 구축의 복잡성이 더 높다고 생각했다.
그래서 JdbcTemplate
, SimpleJdbcInsert
클래스등으로 DAO를 만들어 사용했다.
처음에는 분명 합리적이었다.
진짜? 화이팅!! ㅋ.ㅋ
반복되는 코드
JdbcTemplate
을 이용하는 코드는 거의 비슷하다. 읽기, 쓰기, 가끔 좀 복잡한 읽기 등…
주로 변하는 것은 대상이 되는 객체 그리고 테이블이다.
하지만 생략할 수 없는 반복 작업이 존재한다.
생략할 수 없는 테스트 코드
쿼리를 직접 짜다보니, 여러 상황에서 실제로 동작하는지 믿기가 어려웠다.
쿼리는 문자열로 관리되므로 휴먼 에러가 발생하기 십상이었기 때문이다.
그래서 쿼리 작성 후에는 이 쿼리가 어플리케이션과 잘 어우러지는지 확인하기 위해 각종 테스트를 작성했다.
그렇지 않으면 프로덕션 환경에서 장애가 생길 수 있기 때문이다. (실제로 그랬던 적도 있다)
테스트와 프로덕션 개발의 주객전도
이렇게 열심히 작성한 DAO 테스트 코드들은 요구사항이 바뀌면 깨지기 십상이다.
또 다시 오류 상황들을 고려하고, 엣지 케이스를 고려해서 테스트를 짜야 했다.
뭔가 모순되는 느낌이 들었다.
실제 어플리케이션을 개발하는 시간보다 쿼리 및 DAO 객체 테스트를 작성하는 시간이 훨씬 길었다.
게다가, 요구사항 반영을 위해 쿼리를 수정해야 했기 때문에 대부분의 비즈니스가 영속화 계층까지 내려가있다는 것을 알아챌 수 있었다.
객체 비교
스낵게임 웹 어플리케이션은 Java로 작성한 객체지향 프로그램이다.
따라서 영속화의 대상은 객체이며, RDB에 객체를 저장하고 있다.
HTTP 프로토콜의 무상태성과 메모리의 휘발성 때문이다.
그런데 DB에 담궜다 뺀 객체들을 어떻게 비교할 수 있을까? 동일성은 어떻게 보장할 수 있을까?
물론 Equals & HashCode를 재정의하고, Id 속성을 비교할 수도 있다.
하지만 모든 객체들을 Id 속성으로 비교할 수는 없다.
Id 속성 유무,
JPA는 1차 캐시를 가진다.
복잡한 객체의 영속화
복잡한 객체를 DB에서 뽑으려면 여러 DAO를 조합해야 한다.
이걸 조합하는 방법을 정의하는 것도 보통 일이 아니다.
여러 DAO 객체를 조합하고, 객체를 매핑하는 방법도 복잡하게 정의해야 한다.
물론 가능하지만, 이곳에 쏟는 시간이 아깝다고 느꼈다.
이대로는 안된다
DAO 작성과 테스트가 너무 귀찮고 오래걸리고 힘들다.
이걸 사용하는 서비스 계층의 테스트도 만만찮다.
이런 소모적인 환경은 휴먼 에러들을 야기할 것이다.
“아 이건 당연히 잘 되겠지…”
“테스트 작성 끝난 것 같은데 왤캐 찝찝하지?” (← 실제로 테스트 케이스 빠뜨렸음)
“아 요구사항 바뀌었네.. 이 부분 테스트 다시 짜야겠네”
이렇게 미처 테스트하지 못한 케이스가 하나씩 쌓여 큰 결함이 생길 수도 있다.
그래서 이런 악순환을 끊고자 ORM을 도입하기로 했다.
결과
기존에 작성했던 단순 저장/조회 DAO들과 그 테스트를 제거하고, 일부만 남았다.
앞으로 어플리케이션 코드 작성과 그 테스트에 더 집중할 수 있을거란 희망이 솟았다.
동시에, 도메인 객체들에는 영향이 없었다.
사실 JPA 어노테이션이 붙어 의존성이 생기긴 했지만, 유연성이 희생되지는 않았다고 생각했다.
JPA 컨텍스트 없이도 해당 객체들을 사용하는 데 아무 문제가 없기 때문이다.
잘 도입했다는 생각이 들었지만, 안심할 수는 없다.
JPA를 아주 빠삭하게 알지는 못하기 때문에 항상 부작용을 경계하고, 기능들을 보수적으로 사용해야 하겠다.