Query에서 if 조건 사용해 처리하기
프로젝트 리펙토링 중에 게시판 댓글 처리에 대해 좀 고민을 하게 되었다.
계층형 구조인데 댓글을 삭제했을 때 어떻게 처리할것인가에 대한 고민이었다.
처음에는 그냥 해당 댓글을 삭제하도록 구현했었고, 고민하다 보니 그것도 구조가 좀 이상하지 않나 싶어 하위 모든 댓글을 삭제 하는것으로 할까 하다가 게시판은 그렇게 처리했으니 다르게 처리하고 싶었다.
그래서 결정한 방법이 많은 사이트에서 볼 수 있는 '삭제된 댓글입니다'를 출력하는 것이었다.
이렇게 처리하기 위해 댓글 상태를 표현하는 필드가 필요했고 그거 추가하는거야 어렵지 않으니 추가해줬다.
default '0', 삭제 요청이 들어오면 데이터를 delete처리하는것이 아닌 1로 update 처리를 하도록 했다.
그럼 이제 여기서 고민이 있었다.
그냥 select * from comment 이렇게 조회해온다면 삭제된 댓글임에도 내용이 그대로 조회될 것이다.
여기서 고민끝에 생각난 방법이 세가지.
1. 프론트로 응답하기 전 서버에서 데이터 리스트를 하나하나 검증해 status가 1이라면 내용을 수정한다.
이 방법은 떠오르자마자 아니다 싶었다.
리스트를 하나하나 보면서 체크하고 해당되는 데이터를 수정한다? 그건 좀 아니다 싶었다.
2. 데이터를 응답받은 프론트에서 파싱하는 과정 중 status가 1인 데이터는 내용을 수정하도록 한다.
괜찮은 방법이라고 생각했다.
어차피 파싱 과정에서 데이터를 차례대로 파싱해 나가야 하고, 그 과정에서 status값 하나를 체크하는 것 뿐이니
처리 시간에 지장을 주지 않고 되지 않겠나 싶었다.
하지만 문득 이 방법으로 처리하면 내용이 노출될 가능성이 있다는 생각이 들었다.
그래서 이 방법은 보류.
3. 쿼리로 조회할 때 부터 수정된 상태로 받으면 이 문제가 다 해결되지 않을까?
그래서 쿼리문에서 조건문을 사용할 수 있는지를 찾아봤다.
그리고 동적쿼리로 if문을 사용할 수 있다는 것을 알아냈다.
문제해결
if 조건문을 통해 처리하는 방법(MySQL)
SELECT commentNo
, IF(commentStatus > 0, '삭제된 댓글입니다', commentContent) AS commentContent
, ...
FROM comment
IF( 조건, true, false) AS 컬럼 표시명
이런 구조로 작성해주면 된다.
그럼 commentStatus는 0, 1두가지로만 구성되어있기 때문에 > 0 을 만족한다는 것은 삭제된 댓글이라는 의미이므로
'삭제된 댓글입니다'를 content로 가져오게 되고 false의 경우 0이므로 삭제된 댓글이 아니기 때문에 원래 내용을 가져오게 된다.
하지만 여기서 문제가 있었다.
JPQL에서는 nativeQuery로 처리하지 않으면 Syntax 오류가 발생한다.
물론 nativeQuery로 처리하면 된다.
하지만 그렇게 되면 클래스 타입의 DTO로 받을 수 없었고, 프로젝트에서는 이 데이터를 또 파싱해야 했어서 무조건 List 타입의 엔티티로 받아야 했기 때문에 다른 방법을 찾아야 했다.
CASE WHEN
SELECT commentNo
, CASE
WHEN (commentStatus > 0) THEN '삭제된 댓글입니다'
ELSE commentContent
END AS commentContent
, ...
FROM comment
다르게 조건문을 사용할 수 있는 CASE WHEN이다.
IF의 경우 단일 조건에 대해서만 처리가 가능하지만 CASE WHEN은 자바에서 switch case 처럼 다양한 조건에 대해 처리가 가능하다.
예를들어
SELECT commentNo
, CASE
WHEN (commentStatus == 0) THEN null
WHEN (commentStatus == 1) THEN '삭제된 댓글입니다'
ELSE commentContent
END AS commentContent
, ...
FROM comment
이런식으로도 사용이 가능하다.
JPQL에 이걸 그대로 적용하게 되면 END뒤의 AS와 매핑할 DTO의 괄호 부분에 빨간 밑줄이 생기긴 한데 처리하는데 문제가 발생하지는 않았다.
아직까지는 JPQL에서 이 동적쿼리를 사용하는데 있어서 문제가 발생하지는 않았지만 빨간 밑줄이 생기는건 좀 찝찝하긴 해서 원인을 좀 찾아보긴 해야할듯 하다.
그리고 이 CASE WHEN의 경우는 Oracle에서도 사용이 가능하다!