본문 바로가기
Q&A2026년 8월 22일1분 읽기

Drizzle ORM에서 inArray에 빈 배열을 넣으면 전체 행이 다 나오는데 정상인가요?

d
drizzle_minu
조회 296댓글 3

Drizzle로 태그 필터 검색을 만들고 있습니다. 사용자가 고른 태그 ID 배열을 inArray로 거는데, 아무 태그도 선택 안 하면 배열이 빈 배열([])이 됩니다. 이때 결과가 0건이 아니라 테이블 전체가 다 나와버립니다.

const rows = await db.select().from(posts)
  .where(inArray(posts.tagId, selectedIds)) // selectedIds = []

SQL 로그를 찍어보니 where 절이 아예 안 붙거나 이상하게 나가는 것 같습니다. 상식적으로 빈 배열이면 '해당하는 게 없다'니까 0건이어야 하는 거 아닌가요? 아니면 제가 뭔가 잘못 이해하고 있는 걸까요? 하마터면 비공개 글까지 다 노출될 뻔했습니다.

댓글 3

김김영삼2개월 전
잘못 이해한 게 아니라 실제로 위험한 지점을 짚으신 겁니다. 원인부터 말하면, SQL에서 IN () 은 그 자체로 문법 에러라 어떤 쿼리빌더도 빈 IN을 그대로 못 내보냅니다. 그래서 각자 나름대로 특수처리를 하는데, 이 처리 방식이 Drizzle 버전에 따라 달라요.

예전 Drizzle은 inArray([]) 를 만나면 조건을 통째로 흘려버려서 where 절이 사실상 사라지고 전체가 나오는 동작이었습니다. 지금 겪는 게 정확히 그거예요. 논리적으로는 빈 IN이 항상 false(0건)여야 맞는데, 옛 구현이 그렇게 안 돼 있었던 거죠.

버전 의존적인 동작이라 여기 기대면 안 됩니다. 확실한 방법은 애플리케이션에서 빈 배열을 명시적으로 방어하는 거예요. selectedIds가 비면 그 필터를 아예 빼거나(전체 의도라면), 반대로 0건이 의도라면 조건을 강제로 거짓으로 만드세요.

const cond = selectedIds.length ? inArray(posts.tagId, selectedIds) : sql`false`

이렇게 두면 버전이 뭐든 의도대로 0건이 나옵니다. 참고로 쓰고 계신 drizzle-orm 버전이 몇인지 알려주시면 이 버전이 빈 배열을 어떻게 처리하는지 정확히 짚어드릴게요.
ddrizzle_minu(guest)2개월 전
drizzle-orm 0.29.x 쓰고 있습니다. 그럼 버전을 올리면 자동으로 0건이 되게 바뀌는 건가요, 아니면 계속 앱에서 방어해야 하나요? 그리고 반대로 notInArray([]) 는 어떻게 동작하는지도 궁금합니다. 이것도 빈 배열이면 전체가 나오나요?
김김영삼2개월 전
0.30 즈음부터 정리돼서 최신 버전은 inArray([]) 를 항상 false(0건)로, notInArray([]) 를 항상 true(전체)로 처리합니다. 논리적으로 맞는 방향이에요. 'X 중 아무것도 아닌 것'을 뺀 나머지는 곧 전체니까 notInArray([])가 전체를 돌려주는 건 정상 동작입니다.

다만 버전 올린다고 앱 방어를 빼는 건 추천 안 합니다. 이유가 있어요. 팀에 사람이 여럿이면 각자 로컬 lockfile 버전이 미묘하게 섞이고, 라이브러리 하나 동작에 보안 경계를 통째로 맡기면 나중에 누가 다운그레이드하거나 다른 프로젝트로 코드 복사했을 때 조용히 전체 노출로 돌아옵니다. 실제로 이 빈 배열 필터가 프로덕션에서 접근제어를 통째로 무력화한 사고가 드물지 않아요. 방금 '비공개 글까지 다 노출될 뻔했다'고 하셨죠, 그게 딱 그 사고의 전형입니다.

그러니 버전은 올리되, 빈 배열 분기는 코드에 명시적으로 남겨두세요. 라이브러리 동작이 어떻든 내 코드가 의도를 못 박고 있으면 버전이 바뀌어도 안 깨집니다.
Ctrl+Enter로 등록