MongoDB $redact란 무엇인가?
$redact는 문서 자체에 저장된 정보를 기준으로 문서의 내용을 제한(필터링)할 수 있는 강력한 집계 연산자입니다. 일반적인 $match가 쿼리 조건에 따라 문서 전체를 걸러내는 것과 달리, $redact는 문서 내부의 필드 값을 실시간으로 평가하여 해당 문서나 하위 문서를 유지하거나 제거할 수 있습니다.
$redact는 보통 $cond 연산자와 함께 사용되며, 조건이 참이면 문서를 유지하고 거짓이면 제거하는 방식으로 동작합니다.
$redact의 핵심 시스템 변수
- $$KEEP — 현재 문서(및 하위 문서)를 그대로 유지합니다.
- $$PRUNE — 현재 문서(및 하위 문서)를 결과에서 제외합니다.
- $$DESCEND — 현재 문서 수준은 유지하되, 포함된 하위 문서들을 계속 검사합니다.
예제 컬렉션 생성하기
$redact의 동작을 확인하기 위해 먼저 데모 컬렉션을 만들고 문서를 삽입해 보겠습니다.
> db.demo546.insertOne({"Value1":10,"Value2":20});{
"acknowledged" : true, "insertedId" : ObjectId("5e8e263f9e5f92834d7f05d7")
}
> db.demo546.insertOne({"Value1":40,"Value2":30,Value3:50});{
"acknowledged" : true, "insertedId" : ObjectId("5e8e26549e5f92834d7f05d8")
}
> db.demo546.insertOne({"Value1":100,"Value2":200,Value3:null});{
"acknowledged" : true, "insertedId" : ObjectId("5e8e26619e5f92834d7f05d9")
}
> db.demo546.insertOne({"Value1":400,"Value2":1000,Value3:null});{
"acknowledged" : true, "insertedId" : ObjectId("5e8e26e09e5f92834d7f05da")
}
> db.demo546.insertOne({"Value1":400,"Value2":200,Value3:null});{
"acknowledged" : true, "insertedId" : ObjectId("5e8e26f59e5f92834d7f05db")
}
> db.demo546.insertOne({"Value1":400,"Value2":1000,Value3:60});{
"acknowledged" : true, "insertedId" : ObjectId("5e8e27159e5f92834d7f05dc")
}find() 메서드로 전체 문서 조회하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 확인할 수 있습니다.
> db.demo546.find();
위 명령은 다음과 같은 출력을 생성합니다.
{ "_id" : ObjectId("5e8e263f9e5f92834d7f05d7"), "Value1" : 10, "Value2" : 20 }
{ "_id" : ObjectId("5e8e26549e5f92834d7f05d8"), "Value1" : 40, "Value2" : 30, "Value3" : 50 }
{ "_id" : ObjectId("5e8e26619e5f92834d7f05d9"), "Value1" : 100, "Value2" : 200, "Value3" : null }
{ "_id" : ObjectId("5e8e26e09e5f92834d7f05da"), "Value1" : 400, "Value2" : 1000, "Value3" : null }
{ "_id" : ObjectId("5e8e26f59e5f92834d7f05db"), "Value1" : 400, "Value2" : 200, "Value3" : null }
{ "_id" : ObjectId("5e8e27159e5f92834d7f05dc"), "Value1" : 400, "Value2" : 1000, "Value3" : 60 }$redact와 $cond를 결합한 집계 쿼리 작성하기
이제 $exists 개념과 유사하게 Value3 필드의 존재 여부를 판단하면서, 동시에 Value1이 Value2보다 작은지를 평가하는 $redact 집계 쿼리를 살펴보겠습니다. 여기서는 $ifNull을 활용해 Value3 필드가 null이거나 없는 경우를 처리합니다.
> db.demo546.aggregate( { "$redact": { "$cond": { "if": { "$and": [ {
"$lt": [ "$Value1", "$Value2" ] }, { "$ifNull": [ "$Value3", false ] } ] },
"then": "$$KEEP", "else": "$$PRUNE" } }
} );위 쿼리의 조건은 다음 두 가지입니다.
- $lt: Value1의 값이 Value2보다 작아야 합니다.
- $ifNull: Value3 필드가 null 또는 존재하지 않으면 false로 평가되어 조건을 통과하지 못합니다.
두 조건을 모두 만족하는 문서만 $$KEEP으로 유지되며, 나머지는 $$PRUNE으로 제거됩니다. 실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e8e27159e5f92834d7f05dc"), "Value1" : 400, "Value2" : 1000, "Value3" : 60 }정리
$redact는 단일 파이프라인 단계에서 복잡한 조건 로직을 적용해 문서를 필터링할 수 있어, 특히 계층 구조를 가진 문서에서 권한 기반 데이터 마스킹이나 조건부 필드 제어에 유용합니다. $cond, $and, $lt, $ifNull 등의 연산자와 조합하면 문서 내부 값에 따른 세밀한 제어가 가능합니다.