문서 메뉴
문서 홈
/
MongoDB 매뉴얼
/ / / / /

필드 암호화 및 쿼리 가능성

이 페이지의 내용

  • 개요
  • 쿼리 사용 시 고려 사항
  • 암호화할 필드 지정
  • 예제
  • 쿼리를 위한 필드 구성
  • 예제
  • 경합
  • 경합 요인 조정
  • 쿼리 유형
  • 클라이언트 및 서버 스키마
  • Queryable Encryption 활성화

다음 Queryable Encryption 주제에 대해 알아보세요.

  • 암호화된 필드에서 쿼리를 사용하도록 설정할 때 고려할 사항입니다.

  • 암호화할 필드를 지정하는 방법입니다.

  • 쿼리할 수 있도록 암호화된 필드를 구성하는 방법입니다.

  • 쿼리 유형 및 암호화된 필드에 사용할 수 있는 쿼리 유형입니다.

  • 암호화된 필드에서 쿼리 성능을 최적화하는 방법입니다.

Queryable Encryption을 사용하면 암호화된 필드를 쿼리 가능하게 만들지 여부를 선택할 수 있습니다. 암호화된 필드를 쿼리해야 하는 CRUD 작업을 수행할 필요가 없는 경우에는 해당 필드에서 쿼리를 사용하도록 설정하지 않아도 됩니다. 쿼리 가능하거나 암호화되지 않은 다른 필드를 쿼리하여 전체 문서를 조회할 수 있습니다.

암호화된 필드를 쿼리 가능하게 설정하면 Queryable Encryption은 암호화된 각 필드에 대한 인덱스를 생성하므로 해당 필드에 대한 쓰기 작업이 더 오래 걸릴 수 있습니다. 쓰기 작업이 인덱싱된 필드를 업데이트하면 MongoDB도 관련 인덱스를 업데이트합니다.

암호화된 컬렉션을 만들면 MongoDB는 두 개의 메타데이터 컬렉션을 생성하므로 스토리지 요구 사항이 증가합니다.

Queryable Encryption을 사용하면 JSON 암호화 스키마를 사용하여 MongoDB 문서에서 자동으로 암호화할 필드를 지정할 수 있습니다. 암호화 스키마는 암호화되는 필드와 해당 필드에 사용할 수 있는 쿼리를 정의합니다.

중요

_id 필드를 제외한 모든 필드를 암호화하도록 지정할 수 있습니다.

암호화 및 쿼리를 위한 필드를 지정하려면 다음 속성을 포함하는 암호화 스키마를 생성하세요.

키 이름
유형
필수 사항
path
문자열
필수 사항
bsonType
문자열
필수 사항
keyId
바이너리

필수입니다. 각 필드에 대한 키 값을 지정합니다.

참고

createEncryptedCollection() 를 호출하고 keyId: null 설정하면 MongoDB 드라이버가 자동으로 데이터 키를 생성합니다. 그런 다음 createEncryptedCollection 는 새 keyId 값을 사용하여 새 암호화 스키마를 반환합니다.

queries
개체
선택 사항입니다. 필드를 쿼리 가능하게 만들려면 포함합니다.

이 예는 암호화 스키마를 만드는 방법을 보여줍니다.

개인 식별 정보(PII), 신용 카드 정보 및 민감한 의료 정보가 포함된 다음 문서를 고려해 보세요.

{
"firstName": "Jon",
"lastName": "Snow",
"patientId": 12345187,
"address": "123 Cherry Ave",
"medications": [
"Adderall",
"Lipitor"
],
"patientInfo": {
"ssn": "921-12-1234",
"billing": {
"type": "visa",
"number": "1234-1234-1234-1234"
}
}
}

PII와 민감한 의료 정보를 안전하게 보호하려면 암호화 스키마를 생성하고 해당 필드를 자동 암호화하도록 구성합니다. 암호화된 각 필드에 대해 고유한 키를 미리 생성해야 합니다. 예를 들면 다음과 같습니다.

const encryptedFieldsObject = {
fields: [
{
path: "patientId",
keyId: "<unique data encryption key>",
bsonType: "int"
},
{
path: "patientInfo.ssn",
keyId: "<unique data encryption key>",
bsonType: "string"
},
{
path: "medications",
keyId: "<unique data encryption key>",
bsonType: "array"
},
{
path: "patientInfo.billing",
keyId: "<unique data encryption key>",
bsonType: "object"
}
]
}

클라이언트에서 AutoEncryptionSettings 를 구성한 다음 createEncryptedCollection() 헬퍼 메서드를 사용하여 컬렉션을 만듭니다.

필드를 쿼리할 수 있도록 설정하려면 필드에 queries 속성을 포함하세요. 이렇게 하면 권한이 부여된 클라이언트가 해당 필드에 대해 읽기 및 쓰기 쿼리를 실행할 수 있습니다. queries 속성을 생략하면 클라이언트가 필드를 쿼리할 수 없습니다.

이전 예시 스키마에 queries 속성을 추가하여 patientIdpatientInfo.ssn 필드를 쿼리 가능하게 만듭니다.

const encryptedFieldsObject = {
fields: [
{
path: "patientId",
bsonType: "int",
queries: { queryType: "equality" }
},
{
path: "patientInfo.ssn",
bsonType: "string",
queries: { queryType: "equality" }
},
{
path: "medications",
bsonType: "array"
},
{
path: "patientInfo.billing",
bsonType: "object"
},
]
}

동일한 필드/값 쌍을 여러 문서에 연속적으로 삽입하는 등의 동시 쓰기 작업은 경합(충돌로 인해 작업이 지연되는 현상)을 일으킬 수 있습니다.

Queryable Encryption을 사용하면 MongoDB는 내부 카운터를 사용하여 암호화된 컬렉션의 각 필드/값 쌍의 발생을 추적합니다. 경합 요인은 배열과 유사하게 이 카운터를 분할합니다. 이렇게 하면 insert, update 또는 findAndModify 를 사용하여 동일한 필드/값 쌍이 있는 암호화된 필드를 연속해서 추가하거나 수정할 때 카운터 증분과 관련된 문제를 최소화합니다. contention = 0 은 인덱스 0 에 하나의 요소가 있는 배열을 만듭니다. contention = 4 는 인덱스 0-4 에 5 요소가 있는 배열을 만듭니다. MongoDB는 삽입 중에 임의의 배열 요소를 증가시킵니다.

설정하지 않으면 contention 기본값은 8 으로, 대부분의 워크로드에 고성능을 제공합니다. 경합이 높으면 카디널리티가 낮은 필드에서 삽입 및 업데이트 작업의 성능이 향상되지만 찾기 성능이 저하됩니다.

쿼리 가능 필드에 선택적으로 contention 속성을 포함하여 경합 요소를 기본값인 8에서 변경할 수 있습니다. 경합 요소를 수정하기 전에 다음 점을 고려하세요.

필드에 동시 쓰기 작업이 자주 있는 경우에만 contention을 기본값인 8보다 높게 늘리는 것이 좋습니다. 경합 값이 크면 삽입 및 업데이트 작업에 유리하게 찾기 성능이 저하되므로, 거의 업데이트되지 않는 필드의 경우 값이 큰 경합 요인의 이점이 단점보다 클 가능성은 거의 없습니다.

필드가 자주 쿼리되지만 작성되는 경우는 거의 없는 경우 contention 를 줄이는 것이 좋습니다. 이 경우 쓰기 및 업데이트 성능보다 찾기 성능을 사용하는 것이 좋습니다.

다음과 같은 경우 수식을 사용하여 필드에 대한 경합 요인을 계산할 수 있습니다.

  • ω 는 짧은 시간 동안 필드에서 수행된 동시 쓰기 작업의 수입니다(예: 30ms). 알 수 없는 경우 서버의 가상 코어 수를 사용할 수 있습니다.

  • valinserts 마지막으로 메타데이터 압축을 수행한 이후 삽입된 고유 필드/값 쌍의 수입니다.

  • ω*ω/valinserts 가장 가까운 정수로 반올림됩니다. 최근 값이 1000 개인 100 작업의 워크로드의 경우, 100/1000 = 0.1 이며, 이는 1 로 반올림됩니다.

합리적인 경합 요인 cf 은 다음 공식의 결과를 가장 가까운 양의 정수로 반올림한 것입니다.

· (ω − 1)) / 0.2

예를 들어, 30ms 동안 필드에 100개의 동시 쓰기 작업이 있는 경우 ω = 100이 됩니다. 해당 필드에 최근 고유 값이 50개이면 ω*= 100/50 = 2가 됩니다. 그 결과 cf = (2·1)/0.2 = 10가 됩니다.

경고

필드/값 쌍의 빈도(카디널리티)와 같은 데이터 자체의 속성에 대해서는 경합 요인을 설정하지 마세요. 워크로드에 따라 경합 요인만 설정하세요.

ω = 100valinserts = 1000ω* = 100/1000 = 0.1 ≈ 1cf = (1·0)/0.2 = 0 ≈ 1 가 되는 경우를 생각해 보겠습니다. 20 값이 매우 자주 표시되므로 대신 contention = 3 를 설정합니다. 여러 데이터베이스 스냅샷에 액세스할 수 있는 공격자는 높은 설정이 필드/값 쌍이 빈번하다는 것을 의미한다고 추론할 수 있습니다. 이 경우 contention 을 설정하지 않은 상태로 두어 기본값을 8 로 설정하면 공격자가 해당 정보를 얻는 것을 방지할 수 있습니다.

경합과 그 암호화에 대한 자세한 내용은 MongoDB의 Queryable Encryption 기술 백서의 "섹션 9: 가이드라인"을 참조하세요.

쿼리 유형을 암호화된 필드 객체의 queries 옵션에 전달하면 필드에 허용되는 쿼리 유형이 설정됩니다. 암호화되지 않은 필드 또는 지원되는 쿼리 유형으로 암호화된 필드를 쿼리하면 암호화된 데이터가 반환되고 클라이언트에서 해독됩니다.

Queryable Encryption은 현재 noneequality 쿼리 유형을 지원합니다. 쿼리 유형이 지정되지 않은 경우, 기본값은 none입니다. 쿼리 유형이 none인 경우, 필드는 암호화되지만 클라이언트가 쿼리할 수 없습니다.

equality 쿼리 유형은 다음 표현식을 지원합니다.

참고

암호화된 필드를 null 또는 정규 표현식과 비교하는 쿼리는 지원되는 쿼리 연산자를 사용해도 오류가 발생합니다.

Queryable Encryption equality 쿼리는 암호화된 필드를 다음 BSON 유형 중 하나와 비교하는 작업에서 필드에 대한 읽기 또는 쓰기 작업을 지원하지 않습니다.

  • double

  • decimal128

  • object

  • array

MongoDB는 스키마 유효성 검사를 사용하여 컬렉션의 특정 필드에 암호화를 시행하는 기능을 지원합니다. 자동 Queryable Encryption을 사용하는 클라이언트는 데이터베이스 연결 구성에 따라 특정 동작을 수행합니다.

  • 연결 encryptedFieldsMap 객체에 지정된 컬렉션에 대한 키가 포함되어 있으면 클라이언트는 원격 스키마를 사용하는 대신 해당 객체를 사용하여 자동 Queryable Encryption을 수행합니다. 최소한 로컬 규칙은 원격 스키마가 암호화가 필요하다고 표시하는 필드를 암호화해야 합니다.

  • 연결 encryptedFieldsMap 객체에 지정된 컬렉션의 키가 포함되어 있지 않은 경우 클라이언트는 컬렉션에 대한 서버측 원격 스키마를 다운로드하고 이를 사용하여 자동 Queryable Encryption을 수행합니다.

    중요

    동작 고려 사항

    클라이언트에 지정된 컬렉션에 대한 암호화 스키마가 없으면 다음과 같은 상황이 발생합니다.

    • 클라이언트는 자동 Queryable Encryption과 관련하여 서버에 유효한 스키마가 있음을 신뢰합니다.

    • 클라이언트는 원격 스키마를 사용하여 자동 Queryable Encryption만 수행합니다. 클라이언트는 스키마에 지정된 다른 유효성 검사 규칙을 적용하지 않습니다.

자동 Queryable Encryption에 대해 자세히 알아보려면 다음 리소스를 참조하세요.

컬렉션 생성 전에 Queryable Encryption을 사용하도록 설정합니다. 컬렉션을 생성한 후 Queryable Encryption을 활성화해도 해당 컬렉션에 이미 있던 문서의 필드는 암호화되지 않습니다. 다음 두 가지 방법 중 하나로 필드에서 Queryable Encryption을 사용하도록 설정할 수 있습니다.

  • 애플리케이션이 컬렉션을 만드는 데 사용하는 클라이언트에 encryptedFieldsObject 상수로 표시되는 암호화 스키마를 전달합니다.

const client = new MongoClient(uri, {
autoEncryption: {
keyVaultNameSpace: "<your keyvault namespace>",
kmsProviders: "<your kms provider>",
extraOptions: {
cryptSharedLibPath: "<path to Automatic Encryption Shared Library>"
},
encryptedFieldsMap: {
"<databaseName.collectionName>": { encryptedFieldsObject }
}
}
...
await client.db("<database name>").createCollection("<collection name>");
}

autoEncryption 구성 옵션에 대한 자세한 내용은 Queryable Encryption용 MongoClient 옵션 섹션을 참조하세요.

  • 암호화된 필드 객체를 createCollection()에 전달하여 새 컬렉션을 생성합니다.

await encryptedDB.createCollection("<collection name>", {
encryptedFields: encryptedFieldsObject
});

컬렉션을 생성할 때와 컬렉션에 액세스하기 위해 클라이언트를 생성할 때 암호화된 필드를 지정합니다. 이렇게 하면 서버의 보안이 손상되더라도 정보는 클라이언트를 통해 계속 암호화됩니다.

중요

삽입 작업을 통해 암시적으로 컬렉션을 생성하는 대신 명시적으로 컬렉션을 생성합니다. createCollection()을 사용하여 컬렉션을 생성하면 MongoDB는 암호화된 필드에 인덱스을 생성합니다. 이 인덱스가 없으면 암호화된 필드에 대한 쿼리가 느리게 실행될 수 있습니다.

← 기본 사항