2025년 10월 08일·6분 읽기

권한 인식 글로벌 검색 설계 — 데이터 유출 없이

빠른 인덱싱과 엄격한 행별 접근 검사를 통해 권한 인식 글로벌 검색을 설계하는 방법을 배우고, 사용자가 빠른 결과를 얻는 동시에 데이터 유출을 방지하세요.

권한 인식 글로벌 검색 설계 — 데이터 유출 없이

글로벌 검색이 어떻게 데이터 유출을 일으키는가

글로벌 검색은 보통 앱 전체를 훑는 한 개의 검색 상자를 의미합니다: 고객, 티켓, 청구서, 문서, 사용자, 그리고 사람들이 사용하는 다른 모든 것들. 자동완성이나 빠른 결과 페이지를 제공해 사용자가 곧장 레코드로 이동하게 합니다.

유출은 사용자가 볼 수 없어야 할 항목을 검색이 반환할 때 발생합니다. 사용자가 레코드를 열 수 없더라도 제목 한 줄, 사람 이름, 태그, 하이라이트된 스니펫 하나로 민감한 정보가 드러날 수 있습니다.

검색은 "읽기 전용"처럼 느껴지기 때문에 팀들이 과소평가합니다. 하지만 결과 제목과 미리보기, 자동완성 제안, 결과 총계, "고객 (5)" 같은 패싯, 심지어 속도 차이(어떤 검색어는 빠르고 다른 것은 느림)를 통해 데이터가 노출될 수 있습니다.

이 문제는 보통 초기에 드러나지 않습니다. 초반에는 역할이 하나뿐이거나 테스트 데이터베이스에서 모두가 모든 것을 볼 수 있을 때 검색 기능을 먼저 내놓습니다. 제품이 성장하며 역할(지원 vs 영업, 매니저 vs 상담원)과 공유 인박스, 비공개 메모, 접근 제한 고객, "내 계정만" 같은 기능이 추가되면 이전 가정에 의존하던 검색은 교차 팀이나 고객에 대한 단서를 반환하기 시작합니다.

일반적인 실패 모드는 속도를 위해 "모든 것을" 인덱싱한 뒤 앱에서 결과를 필터링하려는 접근입니다. 그건 이미 늦습니다. 검색 엔진은 무엇이 매치되는지를 이미 결정했고, 제안, 카운트 혹은 부분 필드로 제한된 레코드를 노출할 수 있습니다.

예를 들어, 특정 고객의 티켓만 봐야 하는 지원 상담원이 "Acme"를 입력했을 때 자동완성이 "Acme - 법무 이슈" 또는 "Acme 침해 통지"를 보여준다면, 클릭해서 "권한 없음" 에러가 뜨더라도 제목만으로 정보 유출입니다.

권한 인식 글로벌 검색의 목표는 말로는 단순하지만 구현은 어렵습니다: 빠르고 관련성 높은 결과를 반환하면서 레코드를 열 때 적용하는 것과 동일한 접근 규칙을 엄격히 적용하는 것. 모든 쿼리는 사용자가 자신의 데이터 조각만 볼 수 있는 것처럼 동작해야 하고, UI는 그 밖의 단서(카운트 같은)를 누설하지 않아야 합니다.

인덱싱 대상과 보호해야 할 항목

사용자가 단어를 입력하고 답을 기대하기 때문에 글로벌 검색은 단순해 보입니다. 하지만 내부적으로는 데이터 노출을 위한 새로운 표면을 만듭니다. 인덱스나 데이터베이스 기능을 선택하기 전에 명확히 해야 할 두 가지는: 검색할 객체(엔티티)와 그 객체의 어떤 부분이 민감한지입니다.

엔티티는 누군가 빠르게 찾고자 할 수 있는 모든 레코드입니다. 대부분의 비즈니스 앱에서는 고객, 지원 티켓, 청구서, 주문, 파일(또는 파일 메타데이터)이 포함됩니다. 사람 레코드(사용자, 상담원), 내부 메모, 통합이나 API 키 같은 시스템 객체도 포함될 수 있습니다. 이름, ID, 상태 같은 검색될 가능성이 있는 항목은 대개 글로벌 검색에 들어갑니다.

행별 규칙 vs 테이블별 규칙

테이블별 규칙은 거칠게 적용됩니다: 테이블 전체에 접근할 수 있거나 없거나. 예: 재무팀만 청구서 페이지를 열 수 있다. 이는 이해하기 쉽지만 같은 테이블 내에서 사람마다 다른 행을 보아야 할 때는 실패합니다.

행별 규칙은 행 단위로 가시성을 결정합니다. 예: 지원 상담원은 자신에게 할당된 고객의 티켓만 볼 수 있고, 매니저는 자신의 지역 내 모든 티켓을 볼 수 있습니다. 멀티테넌트 앱에서는 흔히 customer_id = their_customer_id 같은 소유자 규칙이 있습니다.

검색은 대개 이 행별 규칙에서 유출됩니다. 인덱스가 접근 확인 전에 히트를 반환하면 무언가가 존재한다는 사실을 이미 드러낸 것입니다.

실제로 "볼 수 있다"는 의미

"볼 수 있다"는 단순한 예/아니오 스위치가 아닙니다. 일반적으로는 소유(내가 생성한, 내게 할당된), 멤버십(내 팀, 내 부서, 내 역할), 범위(내 지역, 사업부, 프로젝트), 레코드 상태(게시됨, 비보관), 특수 케이스(VIP 고객, 법적 보류, 제한된 태그) 등이 결합됩니다.

이 규칙들을 먼저 평이한 언어로 적으세요. 나중에 이를 데이터 모델과 서버 측 검사로 전환할 것입니다.

결과 미리보기에 안전하게 보여줄 항목 결정하기

검색 결과에는 종종 미리보기 스니펫이 포함되며, 스니펫은 사용자가 레코드를 열 수 없어도 민감한 정보를 유출할 수 있습니다.

안전한 기본값은 접근 확인이 끝날 때까지 최소한의 비민감 필드만 보여주는 것입니다: 표시 이름이나 제목(때로는 마스킹), 짧은 식별자(주문 번호 등), 높은 수준의 상태(열림, 결제됨, 발송됨), 날짜(생성 또는 업데이트), 일반 엔티티 라벨(티켓, 청구서) 정도입니다.

구체적 예: 누군가가 "Acme merger"를 검색했는데 제한된 티켓이 있다면 "Ticket: Acme merger draft - Legal"을 반환하는 것은 이미 유출입니다. 더 안전한 결과는 "Ticket: Restricted"처럼 스니펫 없이 표시하거나 정책에 따라 아예 결과를 보여주지 않는 것입니다.

이 정의들을 초기에 잘 해두면 이후의 결정(무엇을 인덱싱할지, 어떻게 필터링할지, 무엇을 공개할지)이 단순해집니다.

안전하고 빠른 검색을 위한 기본 요구사항

사람들은 급할 때 글로벌 검색을 사용합니다. 1초 이상 걸리면 신뢰를 잃고 수동 필터링으로 돌아갑니다. 하지만 속도는 절반에 불과합니다. 빠른 검색이라도 기록 제목, 고객 이름, 티켓 주제를 한 건이라도 유출하면 검색이 없는 편이 낫습니다.

핵심 규칙은 협상불가입니다: 권한은 UI에서만 숨기지 말고 쿼리 시점에 강제해야 합니다. 데이터를 가져온 뒤에 숨기는 것은 이미 늦습니다. 시스템은 이미 반환해서는 안 되는 데이터를 건드린 것입니다.

이것은 최종 결과 목록뿐 아니라 제안, 상단 히트, 카운트, "결과 없음" 동작 등 검색 주위의 모든 것에 적용됩니다. 자동완성이 접근할 수 없는 사람에게 "Acme Renewal Contract"를 보여주면 유출입니다. 사용자가 볼 수 있는 것보다 더 많은 것을 드러내는 패싯의 "12건 일치"도 유출입니다. 심지어 접근 제한된 매치 때문에 쿼리가 느려지는 것도 타이밍을 통해 정보를 주게 됩니다.

안전한 글로벌 검색은 네 가지가 필요합니다:

  • 정확성: 반환되는 모든 항목은 지금 이 사용자, 이 테넌트에서 허용된 항목이어야 합니다.
  • 속도: 결과, 제안, 카운트가 대규모에서도 일관되게 빠르게 유지되어야 합니다.
  • 일관성: 접근이 변경되면(역할 업데이트, 티켓 재할당), 검색 동작이 빠르고 예측 가능하게 바뀌어야 합니다.
  • 감사성: 어떤 항목이 왜 반환되었는지 설명할 수 있어야 하며, 조사용으로 검색 활동을 로깅할 수 있어야 합니다.

유용한 사고 전환: 검색을 UI 기능이 아니라 또 다른 데이터 API로 취급하세요. 즉, 리스트 페이지에 적용하는 동일한 접근 규칙을 인덱스 빌드, 쿼리 실행, 연관된 모든 엔드포인트(자동완성, 최근 검색, 인기 쿼리)에도 적용해야 합니다.

세 가지 일반적인 설계 패턴(언제 사용할지)

검색 상자는 만들기 쉽습니다. 권한 인식 글로벌 검색은 인덱스는 즉시 결과를 반환하고 싶어하는 반면 앱은 사용자가 접근할 수 없는 레코드를 절대 노출해서는 안 되기 때문에 더 어렵습니다.

아래는 팀들이 자주 쓰는 세 가지 패턴입니다. 적절한 선택은 접근 규칙의 복잡성과 수용 가능한 리스크에 달려 있습니다.

Approach A: "안전한" 필드만 인덱스하고 클릭 시 권한 확인 후 전체 레코드 가져오기.

인덱스에는 ID와 누구에게나 보여도 안전한 비민감 라벨 같은 최소 문서를 저장합니다. 사용자가 결과를 클릭하면 앱이 기본 데이터베이스에서 전체 레코드를 로드하고 실제 권한 규칙을 적용합니다.

이 방식은 유출 위험을 줄이지만 결과가 빈약하게 느껴질 수 있습니다. 또한 "안전한" 라벨이 실수로 비밀을 드러내지 않도록 UI 문구에 주의가 필요합니다.

Approach B: 권한 속성을 인덱스에 저장하고 그곳에서 필터링하기.

각 인덱스 문서에 tenant_id, team_id, owner_id, 역할 플래그, project_id 같은 필드를 포함합니다. 모든 쿼리는 현재 사용자의 범위에 맞는 필터를 추가합니다.

이 방식은 빠르고 풍부한 결과와 좋은 자동완성을 제공하지만, 권한이 필터로 표현될 수 있을 때만 동작합니다. 권한이 복잡한 논리(예: "할당되어 있거나 이번 주 온콜이거나 사고에 포함된 경우")에 따라 달라지면 올바르게 유지하기 어렵습니다.

Approach C: 하이브리드. 인덱스에서 거친 필터링을 하고, 최종 검증은 DB에서 수행.

인덱스에서는 테넌트, 워크스페이스, 고객 같은 안정적이고 넓은 속성으로 필터링한 뒤, 후보 ID 소수에 대해 기본 데이터베이스에서 권한을 재검사합니다.

실제 앱에서는 이 방식이 종종 가장 안전합니다: 인덱스는 빠르고 데이터베이스가 진실의 원천 역할을 합니다.

패턴 선택하기

간단한 설정을 원하고 얇은 스니펫으로 괜찮다면 A를 선택하세요. 명확하고 대부분 정적 범위(멀티테넌트, 팀 기반 접근)가 있고 매우 빠른 자동완성이 필요하면 B를 선택하세요. 역할이 많고 예외가 많거나 레코드별 규칙이 자주 바뀌면 C를 선택하세요. HR, 재무, 의료 같은 고위험 데이터에는 거의 정확하지 않은 솔루션은 용납되지 않으므로 C를 선호하세요.

접근 규칙을 준수하는 인덱스 설계 단계별 가이드

One permission check everywhere
Create a single search flow that powers results, suggestions, and exports safely.
Build Now

먼저 새 팀원에게 설명하듯 접근 규칙을 적으세요. "관리자는 모든 것을 본다"라고만 쓰지 마세요. 대신 이유를 명시하세요: "지원 상담원은 자신의 테넌트의 티켓을 볼 수 있다. 팀 리드는 조직 단위의 티켓도 볼 수 있다. 비공개 메모는 티켓 소유자와 할당된 상담원만 볼 수 있다." 누가 왜 레코드를 볼 수 있는지 말할 수 없다면 안전하게 인코딩하기 어렵습니다.

다음으로 안정적 식별자를 선택하고 최소 검색 문서를 정의하세요. 인덱스는 데이터베이스 행의 전체 복사본이 되어선 안 됩니다. 제목, 상태, 짧은 비민감 스니펫 같은 검색 및 결과 표시를 위해 필요한 것만 보관하세요. 민감한 필드는 권한 확인 후 별도 조회로 두세요.

그다음 빠르게 필터링할 수 있는 권한 신호를 결정하세요. 이는 각 인덱스 문서에 저장할 수 있는 접근을 제한하는 속성(tenant_id, org_unit_id, visibility_level 등)입니다. 목표는 모든 쿼리가 자동완성을 포함해 결과를 반환하기 전에 필터를 적용할 수 있게 하는 것입니다.

실용적 워크플로우는 다음과 같습니다:

  1. 엔티티별(티켓, 고객, 청구서) 가시성 규칙을 평이한 언어로 정의합니다.
  2. record_id와 안전한 검색 가능 필드만 포함한 검색 문서 스키마를 만듭니다.
  3. 모든 문서에 필터 가능한 권한 필드(tenant_id, org_unit_id, visibility_level)를 추가합니다.
  4. 예외는 명시적 허용 목록으로 처리하세요: shared 아이템은 허용 사용자 ID 목록이나 그룹 ID를 저장합니다.

공유된 항목과 예외가 설계를 망치는 지점입니다. 티켓이 팀 간 공유될 수 있다면 "단순 불리언"으로 처리하지 마세요. 필터로 검사 가능한 명시적 허용 목록을 사용하세요. 허용 목록이 크면 개별 사용자보다 그룹 기반 허용을 선호하세요.

인덱스를 동기화 상태로 유지하는 방법

Turn access rules into data
Model tenants, teams, and record scopes in Data Designer, then enforce them in one place.
Try AppMaster

안전한 검색 경험은 지루하지만 잘 해낸 한 가지에서 옵니다: 인덱스는 현실을 반영해야 합니다. 레코드가 생성, 변경, 삭제되거나 권한이 바뀌면 검색 결과도 빠르고 예측 가능하게 따라와야 합니다.

생성, 업데이트, 삭제를 따라가기

인덱싱을 데이터 수명 주기의 일부로 취급하세요. 유용한 사고 모델은: 진실의 원천이 변경될 때마다 이벤트를 방출하고 인덱서가 반응한다는 것입니다.

일반적 접근으로는 DB 트리거, 애플리케이션 이벤트, 잡 큐가 있습니다. 가장 중요한 것은 이벤트가 손실되지 않는 것입니다. 앱이 레코드를 저장하고 인덱싱에 실패하면 "존재함을 알지만 검색에서 찾을 수 없음" 같은 혼란스러운 동작이 발생합니다.

권한 변경도 인덱스 변경이다

많은 유출은 컨텐츠는 업데이트 되었지만 접근 메타데이터가 업데이트되지 않을 때 발생합니다. 권한 변경은 역할 업데이트, 팀 이동, 소유권 이전, 고객 재할당, 티켓 병합 등에서 옵니다.

권한 변경을 일급 이벤트로 만드세요. 권한 인식 검색이 tenant 또는 team 필터에 의존한다면 인덱스 문서에 이를 적용할 수 있는 필드(tenant_id, team_id, owner_id, allowed_role_ids)를 포함하고, 해당 필드가 바뀌면 재인덱스하세요.

문제는 폭발 범위입니다. 역할 변경은 수천 건의 레코드에 영향을 줄 수 있습니다. 진행 상태, 재시도, 일시 정지 기능이 있는 대규모 재인덱스 경로를 계획하세요.

결국 일관성 있는 지연을 계획하라

좋은 이벤트 시스템을 갖추더라도 검색이 뒤처지는 창이 생깁니다. 변경 직후 몇 초 동안 사용자가 무엇을 보게 할지 결정하세요.

두 가지 규칙이 도움이 됩니다:

  • 지연에 대해 일관되게 하세요. 인덱싱이 보통 2–5초 안에 끝난다면 중요한 경우 그 기대치를 알려주세요.
  • 누락되는 편이 유출되는 것보다 낫습니다. 새로 권한이 부여된 레코드가 약간 늦게 나타나는 것이 새로 권한이 철회되었음에도 계속 표시되는 것보다 안전합니다.

인덱스가 오래된 경우 안전한 폴백 추가

검색은 발견을 위한 도구이지만 상세 보기에서 유출이 발생합니다. 민감한 필드를 보여주기 전에 읽기 시점에 두 번째 권한 검사를 하세요. 인덱스가 오래되어 결과가 누락되거나 슬립스루됐더라도 상세 페이지가 접근을 차단해야 합니다.

좋은 패턴은: 검색에서는 최소 스니펫만 보여주고 사용자가 레코드를 열거나 미리보기를 확장할 때 권한을 다시 확인합니다. 검사가 실패하면 명확한 메시지를 보여주고 다음 새로고침에서 해당 항목을 결과 집합에서 제거하세요.

데이터 유출을 일으키는 흔한 실수들

검색은 "레코드 열기" 페이지가 잠겨 있어도 데이터를 유출할 수 있습니다. 사용자는 결과를 클릭하지 않아도 이름, 고객 ID, 숨겨진 프로젝트의 규모를 알 수 있습니다. 권한 인식 글로벌 검색은 문서뿐 아니라 문서에 대한 힌트도 보호해야 합니다.

자동완성은 자주 발생하는 유출원입니다. 제안은 종종 전체 권한 검사를 건너뛰는 빠른 접두사 조회로 구동됩니다. UI는 무해해 보이지만 한 글자만 입력해도 고객 이름이나 직원 이메일을 드러낼 수 있습니다. 자동완성은 전체 검색과 같은 접근 필터를 실행하거나(또는) 미리 필터된 제안 세트(예: 테넌트 및 역할별)에서 빌드되어야 합니다.

패싯 카운트와 "약 1,243건의 결과" 배너도 은밀한 유출입니다. 카운트는 레코드를 숨기더라도 존재를 확인시켜 줄 수 있습니다. 동일한 접근 규칙하에 카운트를 안전하게 계산할 수 없다면 세부 정보를 줄이거나 카운트를 생략하세요.

캐싱도 흔한 원인입니다. 사용자, 역할, 테넌트 간에 공유된 캐시는 다른 사용자가 생성한 결과를 보여주는 "결과 유령"을 만들 수 있습니다. 엣지 캐시, 애플리케이션 레벨 캐시, 검색 서비스 내부의 인메모리 캐시에서 발생할 수 있습니다.

초기에 점검할 유출 트랩:

  • 자동완성과 최근 검색이 전체 검색과 동일한 규칙으로 필터링되는가.
  • 패싯 카운트와 총계가 권한 적용 후에 계산되는가.
  • 캐시 키에 tenant ID와 권한 서명(역할, 팀, 사용자 ID)이 포함되는가.
  • 로그와 분석에 제한된 데이터의 원문 쿼리나 스니펫을 저장하지 않는가.

마지막으로 너무 광범위한 필터를 조심하세요. "테넌트로만 필터링"은 고전적인 멀티테넌트 실수이지만 한 테넌트 내부에서도 발생합니다: "부서로 필터링"할 때 실제로는 레코드별 규칙이 필요한 경우입니다. 예: 상담원이 "환불"을 검색했는데 테넌트 내 모든 고객의 결과(상위 VIP 계정 포함)를 받는 경우. 해결책은 원리적으로 단순합니다: 검색, 자동완성, 패싯, 내보내기 등 모든 쿼리 경로에서 행 수준 규칙을 강제하세요.

사람들이 잊는 개인정보 및 보안 세부사항

Build role-based apps fast
Design internal tools with real roles and row-level rules from day one.
Create App

많은 설계가 "누가 무엇을 볼 수 있는가"에 집중하지만, 빈 상태, 타이밍, UI의 작은 힌트 같은 가장자리를 통해서도 유출이 발생합니다. 권한 인식 검색은 아무것도 반환하지 않을 때조차 안전해야 합니다.

한 가지 쉬운 유출은 부재에 의한 확인입니다. 권한이 없는 사용자가 특정 고객 이름, 티켓 ID, 이메일을 검색하고 "접근 불가" 또는 "권한 없음"과 같은 특별한 메시지를 받으면 레코드가 존재한다는 사실을 확인한 것입니다. "존재하지 않음"과 "접근 불가"에 대해 기본 결과를 동일한 "결과 없음"으로 처리하세요. 응답 시간과 문구를 일관되게 유지해 속도로 추측할 수 없게 하세요.

민감한 부분 일치

자동완성과 입력 중 검색에서 개인정보가 새는 경우가 많습니다. 이메일, 전화번호, 정부 발급 ID나 고객 ID 같은 필드의 부분 일치는 의도치 않게 더 많은 정보를 드러낼 수 있습니다. 이러한 필드의 동작 방식을 미리 결정하세요.

실용적 규칙:

  • 이메일, 전화번호, ID 같은 고위험 필드는 정확 일치만 허용합니다.
  • 숨겨진 텍스트를 드러내는 하이라이트 스니펫은 피합니다.
  • 민감한 필드에 대해서는 자동완성을 비활성화하는 것도 고려하세요.

한 글자라도 노출되면 데이터 추측에 도움이 된다면 그 필드는 민감하다고 취급하세요.

새로운 리스크를 만들지 않는 남용 방지

검색 엔드포인트는 열거 공격에 이상적입니다: 많은 쿼리를 시도해 무엇이 존재하는지 맵핑하려는 시도입니다. 속도 제한과 이상 탐지를 추가하되 저장하는 내용에 주의하세요. 원문 쿼리를 포함한 로그는 두 번째 데이터 유출 소가 될 수 있습니다.

간단하게 유지하세요: 사용자별, IP별, 테넌트별로 속도 제한을 적용하고, 원문 쿼리가 아닌 카운트·타이밍·대략적 패턴을 로깅하며, 반복되는 "근접 실패" 쿼리(연속 ID 등)에 경보를 설정하고 반복 실패 후 차단하거나 추가 인증을 요구하세요.

에러 메시지는 지루하게 만드세요. "결과 없음", "권한 없음", "잘못된 필터"에 대해 동일한 메시지와 빈 상태를 사용하세요. 검색 UI가 덜 말할수록 우연히 드러낼 수 있는 게 줄어듭니다.

예시: 지원팀의 고객별 티켓 검색

Design for multi-tenant safety
Build a multi-tenant app where every query behaves like the user’s exact data slice.
Get Started

지원 상담원 마야(Maya)는 세 개의 고객 계정을 처리하는 팀에서 일합니다. 앱 헤더에는 하나의 검색 상자가 있습니다. 제품은 티켓, 연락처, 회사에 대한 글로벌 인덱스를 가지고 있지만 모든 결과는 접근 규칙을 따라야 합니다.

마야가 발신자가 "Alice"라고 했기에 "Alic"을 입력합니다. 자동완성이 몇 가지 제안을 빠르게 보여주고, 그녀는 "Alice Nguyen - Ticket: Password reset"을 클릭합니다. 레코드를 열기 전에 앱은 해당 레코드에 대한 접근을 다시 확인합니다. 그 티켓이 여전히 그녀의 팀에 할당되어 있고 그녀의 역할이 허용하면 상세 페이지로 들어갑니다.

마야가 각 단계에서 보는 것:

  • 검색창: 제안은 빠르게 표시되지만 지금 그녀가 접근할 수 있는 레코드만 표시됩니다.
  • 결과 목록: 티켓 제목, 고객 이름, 마지막 업데이트 시간만 표시됩니다. "접근 권한 없음" 자리표시는 없습니다.
  • 티켓 상세: 전체 뷰는 서버 측 권한 재검사 후에만 로드됩니다. 접근이 변경되면 앱은 "티켓을 찾을 수 없음"이라고 표시합니다("금지"라고 하지 않음).

훈련 중인 새로운 상담원 레오(Leo)는 역할상 "지원에 공개"로 표시된 티켓과 한 고객에 한정된 권한만 있습니다. 같은 "Alic" 검색어를 입력해도 더 적은 제안만 보고 누락된 항목에 대한 단서도 보지 못합니다. 다른 매치가 존재한다는 것을 알리는 "5건" 같은 카운트도 없습니다. UI는 단지 그가 열 수 있는 것만 보여줍니다.

나중에 매니저가 "Alice Nguyen - Password reset"을 마야의 팀에서 전문 에스컬레이션 팀으로 재할당합니다. 짧은 시간 내(사용하는 동기화 방식에 따라 보통 수초에서 몇 분) 마야의 검색은 그 티켓을 반환하지 않습니다. 만약 상세 페이지를 열어둔 상태라면 새로고침 시 권한을 재검사하고 티켓이 사라질 것입니다.

이것이 원하는 동작입니다: 입력과 결과는 빠르게 나오되, 카운트, 스니펫, 오래된 인덱스 항목을 통해 데이터의 흔적이 남지 않도록 합니다.

안전하게 구현하기 위한 체크리스트와 다음 단계

권한 인식 글로벌 검색은 지루한 가장자리가 안전할 때만 "완료"입니다. 많은 유출은 무해해 보이는 장소에서 발생합니다: 자동완성, 결과 카운트, 내보내기 등.

빠른 안전 점검

배포 전에 실제 데이터를 사용해 다음 점검을 하세요:

  • 자동완성: 사용자가 열 수 없는 제목, 이름, ID를 제안하지 않는가.
  • 카운트와 패싯: 총계나 그룹별 카운트를 보여준다면 권한 적용 후 계산하는가(또는 카운트를 생략하는가).
  • 내보내기와 대량 작업: "현재 검색"을 내보낼 때는 내보내기 시점에 행별로 접근을 다시 확인하는가.
  • 정렬과 하이라이트: 사용자가 볼 수 없는 필드를 기준으로 정렬하거나 하이라이트하지 않는가.
  • "찾을 수 없음" vs "금지": 민감한 엔티티에 대해 존재를 확인시켜 주지 않도록 같은 응답 형태를 고려하세요.

실행할 수 있는 테스트 계획

작은 역할 매트릭스(역할 x 엔티티)와 다음과 같은 까다로운 사례를 포함한 데이터셋을 만드세요: 공유 레코드, 최근에 권한이 철회된 레코드, 테넌트 간 유사 레코드.

세 번에 걸쳐 테스트하세요: (1) 역할 매트릭스 테스트 — 거부된 레코드가 절대 결과, 제안, 카운트, 내보내기에 나타나지 않는지 확인; (2) "깨뜨려 보기" 테스트 — ID 붙여넣기, 이메일/전화로 검색, 부분 일치로 아무것도 반환하면 안 되는 경우 시도; (3) 타이밍 및 캐시 테스트 — 권한을 변경하고 결과가 빠르게 업데이트되어 오래된 제안이 남지 않는지 확인.

운영적으로는 검색 결과가 "이상해 보이는" 날을 대비하세요. 쿼리 컨텍스트(사용자, 역할, 테넌트)와 적용된 권한 필터를 로깅하되 민감한 원문 쿼리나 스니펫은 저장하지 마세요. 안전한 디버깅을 위해 관리자 전용 도구를 만들어 왜 레코드가 매치되었는지, 왜 허용되었는지 설명할 수 있게 하세요.

제품이 AppMaster (appmaster.io) 위에 구축된다면, 실제적인 접근법은 검색을 서버사이드 흐름으로 유지하는 것입니다: Data Designer에서 엔티티와 관계를 모델링하고 Business Processes에서 접근 규칙을 강제하며 같은 권한 검사를 자동완성, 결과 목록, 내보내기에 재사용해 한 곳에서만 올바르게 구현되도록 하세요.

쉬운 시작
멋진만들기

무료 요금제로 AppMaster를 사용해 보세요.
준비가 되면 적절한 구독을 선택할 수 있습니다.

시작하다