kakasoo

Repository 패턴에서 조인 대상이 Null인 경우에 대한 체크 본문

프로그래밍/NestJS

Repository 패턴에서 조인 대상이 Null인 경우에 대한 체크

카카수(kakasoo) 2022. 9. 12. 16:50
반응형

 

원래 Repository에서 조인 대상에 대해 IsNull로 체크하는 것은 자잘한 버그들이 있었습니다.

IsNull로 할 경우, 사용자가 기대하던 방식대로 동작하지 않았는데, 이게 버그인지 의도인지는 알 수 없었습니다.

그래서 이런 경우는, 차라리 쿼리빌더에서 InnerJoin을 하는 것이 낫다는 판단이었습니다.

어떤 식으로 동작할지 명확한 것이 차라리 낫다는 판단이었습니다.

그러고 나서 몇 달의 시간이 지나니 새로운 업데이트가 나왔습니다.

새 업데이트 내용을 보니, 기존의 코드가 의도된 게 아니라 버그였음을 확인할 수 있겠네요.

 

이 내용은 issue number #8890에 있는 코드를 그대로 옮겨, 해석을 달은 것입니다.

일단 기존에 코드가 어떤 문제가 있었는지, 예제 코드를 통해 이해해보겠습니다.

 

const box = await AppDataSource.getRepository(BoxModel).find({
	  relations: {
	    pallet: true,
	  },
	  where: {
	    pallet: IsNull(),
	  },
});

 

Repository에서 조인한 대상이 Null인 경우를 조회하려고 합니다.

아마 대부분의 사용자는 아래의 쿼리처럼 변환되기를 희망했을 겁니다.

 

Expected Behavior

SELECT
	*
FROM
	"boxes" "BoxModel"
	LEFT JOIN "pallets" "BoxModelBoxModel_pallet" ON "BoxModelBoxModel_pallet"."id" = "BoxModel"."pallet_id"
		AND("BoxModel_BoxModel_pallet"."deleted_at" IS NULL)
WHERE
	"BoxModel"."deleted_at" IS NULL
	AND "BoxModel"."pallet_id" IS NULL;

 

내용이 이해가 되실까요?

간단히 설명하면, 조인할 대상이 없는 박스를 가져오라는 쿼리문이라고 해석할 수 있습니다.

하지만 실제 동작은 이렇지 않았습니다.

 

Actual Behavior

SELECT
	*
FROM
	"boxes" "BoxModel"
	LEFT JOIN "pallets" "BoxModelBoxModel_pallet" ON "BoxModelBoxModel_pallet"."id"=" BoxModel"."pallet_id" 
		AND ("BoxModel_BoxModel_pallet"."deleted_at" IS NULL)
WHERE " BoxModel "." deleted_at IS NULL;

 

조인까지는 똑같았지만, WHERE 문에서 pallets가 없을 것을 요구하는 내용이 생략되어 있습니다.

즉, 조인 대상에서는 IsNull() 함수가 사용될 수 없었던 모양입니다.

다행히 이런 문제는 해결되었습니다.

이제 0.3.8 버전에서는 우리가 의도한 대로 정상동작하기 때문에 이 문제는 무시하셔도 될 것 같습니다.

반응형