회사 일을 하는 중 발생한 과정으로 적당한 상황 예시를 들자면
MongoDB Aggregation 파이프라인에서
bar
필드의 값을 foo
라는 새로운 필드로 복사하고, 그걸 기준으로 정렬하려고 했다.
Spring Data MongoDB로는 이렇게 작성했다:
AggregationOperation addFields = addFieldWithValueOf("foo", "bar");
AggregationOperation sort = sort(Direction.DESC, "foo");
단순한 의도였다.
쿼리는 잘 나갔고, 에러도 안 났다.
그런데 결과 정렬이 엉망이었다.
중간에 생성된 쿼리를 확인해보니, 예상했던 쿼리와 달랐다.
{
"$addFields": {
"foo": "$bar"
}
}
{
"$addFields": {
"foo": {
"bar": 1
}
}
}
$bar
가 아니라 { bar: 1 }
이라는 객체가 들어가 있었다.
MongoDB는 이걸 객체로 인식해 foo
필드에 넣은 것이고, 당연히 정렬이 안 되는 게 맞았다.
이 문제가 특히 심각한 이유는 MongoDB가 에러를 안 낸다는 점이다.
문법적으로는 유효한 BSON이기 때문에
에러 없이 실행되지만, 결과는 완전히 잘못된다.
내부 구현 코드를 보면 문제는 이 한 줄에서 비롯됐다:
valueMap.put(field, value instanceof String stringValue ? Fields.fields(stringValue) : value);
여기서 "bar"
는 단일 필드명인데, Fields.fields(...)
로 감싸면서
MongoDB가 객체로 해석하게 만들어버렸다.
해결책은 단순했다 — 단일 필드 참조는 Fields.field(...)
로 감싸야 했다:
- Fields.fields("bar")
+ Fields.field("bar")
그래서 이 문제를 수정한 PR을 올리고자 했고,
실제로 #4933 이슈가 이미 존재해서 이를 바탕으로 PR을 해결하게 됐다.
이 문제는 단순히 정렬뿐 아니라, 다른 파이프라인 연산에서도 발생할 수 있었다.
예를 들어 다음과 같은 연산들도 모두 오작동할 수 있었다:
{
"$match": {
"foo": { "$gt": 100 }
}
}
→ foo
가 {bar: 1}
이라는 객체이면, 숫자 비교 불가
{
"$project": {
"result": { "$add": ["$foo", 5] }
}
}
→ foo
가 숫자일 줄 알았는데 객체면, $add
에서 런타임 에러 발생
이 문제는 단순히 "문자열로 넘긴 필드명이 잘못 해석됨"
같은 사소한 버그처럼 보이지만,
실제로는 MongoDB 파이프라인 전반에 걸쳐 영향을 미치는 치명적인 구조적 버그였다.
이런 과정을 직접 겪고 파고들면서
Spring Data MongoDB에 PR을 올려 메인 컨테이너의 답변까지는 받은 상황이다.
단순히 정렬이 안 되던 작은 의심이,
라이브러리의 오픈소스 기여로 이어졌다.
머지되면 좋겠다......
너무 멋져요