상황
날짜와 테마를 고르면, 예약 시간을 선택할 수 있다.
이때 이미 예약된 시간대는 예약할 수 없어야 하는 요구사항이 있다.
SELECT
t.id,
t.start_at,
CASE
WHEN r.id IS NOT NULL THEN TRUE
ELSE FALSE
END AS is_booked
FROM reservation_time t
LEFT JOIN reservation r
ON t.id = r.time_id
AND r.date = ?
AND r.theme_id = ?
이 쿼리는 특정 날짜와 테마에 대해 예약 가능한 시간대를 조회하고,
각 시간대가 이미 예약되었는지 여부를 is_booked 컬럼으로 함께 반환한다.
단 한 번의 쿼리(한방 쿼리)로 요구사항을 만족할 수 있다.
리뷰어:
"예약이 존재하는지를 CASE 를 통해 함께 확인하고 있는데요. sql 문에 비즈니스 로직을 넣다보면 유지보수가 어려워지는 문제가 있습니다."
왜 어려워질까? (추측)
어떻게 보면 #1 와도 연관된 문제일 수 있다.
관련 글을 찾아볼수록 요즘은 단순한 데이터 저장소 개념으로 사용하는 것이 선호되는 것 같다.
SQL에 비즈니스 로직이 있다는 것이 도메인 로직의 분산이다.
- CASE 문 같은 조건 로직은, 사실
예약되었는지 여부 라는 도메인 개념에 해당한다.
- 하지만 이 로직이 SQL에 들어가면, 예약이 되었는지를 판단하는 핵심 기준이 자바가 아니라 SQL 내부에 숨겨진다.
- 이렇게 되면 비즈니스 로직이 코드와 쿼리로 나뉘게 되어 도메인 흐름을 전체적으로 이해하기 어려워질 것이다.
SQL은 정적이고 리팩토링이 어렵다
- 자바 코드는 IDE의 도움을 받아 리팩터링 하기 쉽지만, 문자열로 작성하는 SQL은 어렵다.
- 나아가 컴파일 예외가 발생하지 않는다.
테스트하기 어렵다.
- SQL은 테스트가 어렵다. SQL만 따로 테스트하려면 DB를 붙여야 한다.
- 반면 자바 코드로 예약 여부 판단을 나누면, 단위 테스트를 작성할 수 있다.
SQL이 더 익숙하지 않다.
- 대부분 자바 개발자라면, SQL 보다는 자바 코드가 더 읽기 쉽지 않을까?
읽어보면 좋을 글
상황
이 쿼리는 특정 날짜와 테마에 대해 예약 가능한 시간대를 조회하고,
각 시간대가 이미 예약되었는지 여부를 is_booked 컬럼으로 함께 반환한다.
단 한 번의 쿼리(한방 쿼리)로 요구사항을 만족할 수 있다.
왜 어려워질까? (추측)
어떻게 보면 #1 와도 연관된 문제일 수 있다.
관련 글을 찾아볼수록 요즘은 단순한 데이터 저장소 개념으로 사용하는 것이 선호되는 것 같다.
SQL에 비즈니스 로직이 있다는 것이 도메인 로직의 분산이다.
예약되었는지 여부라는 도메인 개념에 해당한다.SQL은 정적이고 리팩토링이 어렵다
테스트하기 어렵다.
SQL이 더 익숙하지 않다.
읽어보면 좋을 글