본문으로 건너뛰기

고급 사용자 검색

Management API를 직접 사용하여 고급 사용자 검색 조건을 활용하세요.

검색 요청 수행하기​

사용자 검색을 위해 GET /api/users를 사용하세요. 이 API는 다른 Management API와 마찬가지로 인증이 필요합니다. 상호작용 방법은 Management API와 상호작용하기를 참고하세요.

샘플​

요청

curl \
--location \
--request GET \
'http://<your-logto-endpoint>/api/users?search=%25alice%25'

응답

User 엔티티의 배열입니다.

[
{
"id": "MgUzzDsyX0iB",
"username": "alice_123",
"primaryEmail": "alice@some.email.domain",
"primaryPhone": null,
"name": null,
"avatar": null
// ...
}
]

파라미터​

검색 요청은 다음 파라미터 키로 구성됩니다:

  • 검색 키워드: search, search.*
  • 필드별 검색 모드: mode, mode.* (기본값 'like', 사용 가능 값 ['exact', 'like', 'similar_to', 'posix'])
  • 조인 모드: joint 또는 jointMode (기본값 'or', 사용 가능 값 ['or', 'and'])
  • 대소문자 구분 여부: isCaseSensitive (기본값 false)

이 API는 페이지네이션이 활성화되어 있습니다.

몇 가지 예시를 통해 살펴보겠습니다. 모든 검색 파라미터는 URLSearchParams 생성자 형식으로 작성됩니다.

경고:

검색 모드는 기본적으로 like로 설정되어 있으며, 근사 문자열 매칭 ("퍼지 검색")을 사용합니다.

노트:

모든 퍼지 검색 모드는 필드당 하나의 값만 매칭할 수 있습니다. 하나의 필드에 여러 값을 매칭하려면 "exact" 모드를 사용해야 합니다. 자세한 내용은 정확한 일치 및 대소문자 구분을 참고하세요.

모든 사용 가능한 필드에서 퍼지 검색을 하고 싶다면, search 키에 값을 제공하면 됩니다. 내부적으로 the like 연산자를 사용합니다:

new URLSearchParams([['search', '%foo%']]);

이 검색은 사용자 검색에서 사용 가능한 모든 필드, 즉 id, primaryEmail, primaryPhone, username, name을 순회합니다.

필드 지정하기​

name 필드에서만 검색을 제한하고 싶다면? 이름에 foo가 포함된 사용자를 찾으려면, . 기호로 필드를 지정하세요:

new URLSearchParams([['search.name', '%foo%']]);

중첩 필드는 지원되지 않으니 주의하세요. 예를 들어, search.name.first는 오류가 발생합니다.

여러 필드를 동시에 지정할 수도 있습니다:

new URLSearchParams([
['search.name', '%foo%'],
['search.primaryEmail', '%@gmail.com'],
]);

즉, 이름에 foo가 포함되어 있거나 OR 이메일이 @gmail.com으로 끝나는 사용자를 검색합니다.

조인 모드 변경하기​

모든 조건을 만족하는 결과만 반환받고 싶다면, 조인 모드를 and로 설정하세요:

new URLSearchParams([
['search.name', '%foo%'],
['search.primaryEmail', '%@gmail.com'],
['joint', 'and'],
]);

즉, 이름에 foo가 포함되어 있고 AND 이메일이 @gmail.com으로 끝나는 사용자를 검색합니다.

정확한 일치 및 대소문자 구분​

이름이 정확히 "Alice"인 사용자를 검색하고 싶다면, mode.name을 exact로 설정하세요.

new URLSearchParams([
['search.name', 'Alice'],
['mode.name', 'exact'],
]);

기본값인 like 모드와 exact를 지정했을 때 동일한 효과를 볼 수 있지만, 차이점은 exact 모드는 비교에 =를 사용하고, like는 like 또는 ilike를 사용한다는 점입니다. 이론적으로 =가 더 나은 성능을 보입니다.

또한, exact 모드에서는 여러 값을 전달할 수 있으며, 이 값들은 or로 연결됩니다:

new URLSearchParams([
['search.name', 'Alice'],
['search.name', 'Bob'],
['mode.name', 'exact'],
]);

즉, 이름이 "Alice" OR "Bob"인 사용자를 매칭합니다.

기본적으로 검색은 대소문자를 구분하지 않습니다. 더 정확하게 검색하려면, 대소문자 구분을 활성화하세요:

new URLSearchParams([
['search.name', 'Alice'],
['search.name', 'Bob'],
['mode.name', 'exact'],
['isCaseSensitive', 'true'],
]);

isCaseSensitive는 전역 설정입니다. 따라서 모든 필드에 적용됩니다.

정규 표현식 (RegEx)​

PostgreSQL은 두 가지 유형의 정규 표현식을 지원합니다: similar to와 posix. 정규 표현식으로 검색하려면 mode를 similar_to 또는 posix로 설정하세요:

new URLSearchParams([
['search', '^T.?m Scot+$'],
['mode', 'posix'],
]);

참고: similar_to 모드는 대소문자 구분 검색에서만 동작합니다.

매치 모드 오버라이드​

기본적으로 모든 키워드는 일반 검색의 매치 모드를 상속받습니다:

new URLSearchParams([
['search', '^T.?m Scot+$'],
['mode', 'posix'],
['search.primaryEmail', 'tom%'], // Posix 모드
['joint', 'and'],
]);

특정 필드에 대해 오버라이드하려면:

new URLSearchParams([
['search', '^T.?m Scot+$'],
['mode', 'posix'],
['search.primaryEmail', 'tom%'], // Like 모드
['mode.primaryEmail', 'like'],
['search.phone', '0{3,}'], // Posix 모드
['joint', 'and'],
]);

외부 아이덴티티로 조회하기​

소셜 또는 엔터프라이즈 SSO 아이덴티티에 연결된 사용자를 찾으려면, 다음 세 가지 쿼리 파라미터를 함께 전달하여 정확히 조회하세요:

  • identityType: 소셜 커넥터 아이덴티티는 social, 엔터프라이즈 SSO 아이덴티티는 sso.
  • identityProvider: 소셜 아이덴티티의 커넥터 대상(예: dingtalk), 또는 엔터프라이즈 SSO 아이덴티티의 발급자.
  • identityId: 외부 아이덴티티 제공자가 발급한 사용자 식별자.
// DingTalk 소셜 아이덴티티에 연결된 사용자 찾기
new URLSearchParams([
['identityType', 'social'],
['identityProvider', 'dingtalk'],
['identityId', 'dingtalk-open-id'],
]);
// 엔터프라이즈 SSO 아이덴티티에 연결된 사용자 찾기
new URLSearchParams([
['identityType', 'sso'],
['identityProvider', 'https://example.com/issuer'],
['identityId', 'enterprise-user-id'],
]);

아이덴티티 필터는 다른 검색 필터와 AND 논리로 결합됩니다. 예를 들어, 키워드 검색과 함께 아이덴티티 조회를 더 좁힐 수 있습니다:

new URLSearchParams([
['identityType', 'social'],
['identityProvider', 'dingtalk'],
['identityId', 'dingtalk-open-id'],
['search', '%foo%'],
]);

커스텀 데이터로 조회하기​

커스텀 데이터에 저장된 정확한 값으로 사용자를 찾으려면, 하나 이상의 customData 쿼리 파라미터를 GET /api/users에 전달하세요. 각 값은 URL 인코딩된 JSON 객체여야 합니다:

curl \
--get \
--data-urlencode 'customData={"qq":114514}' \
'http://<your-logto-endpoint>/api/users'

--data-urlencode는 JSON 객체를 자동으로 인코딩합니다. 동등한 요청 URL은 GET /api/users?customData=%7B%22qq%22%3A114514%7D입니다.

노트:

테넌트에 사용자가 많을 경우 커스텀 데이터 조회가 느릴 수 있습니다. customData를 search 또는 아이덴티티 조회 등 다른 선택적 필터와 결합하여 쿼리 범위를 좁히세요.

Logto는 JSONB 포함을 사용하여 사용자의 custom_data와 값을 매칭합니다. 값에 포함된 키만 일치하면 되며, 사용자의 커스텀 데이터 내 다른 키는 무시됩니다.

  • 타입은 엄격합니다: 숫자 114514는 문자열 "114514"와 일치하지 않습니다.
  • 문자열은 대소문자를 구분합니다.
  • null은 명시적 JSON null과만 일치하며, 키가 없는 경우에는 일치하지 않습니다.
  • 중첩 객체는 재귀적으로 매칭됩니다.
  • 배열은 순서나 중복과 상관없이 요소별로 매칭됩니다.

하나의 JSON 객체 내 모든 키는 AND로 매칭됩니다. customData를 여러 번 전달하면, 객체 중 하나라도 일치하면 사용자가 매칭됩니다 (OR):

curl \
--get \
--data-urlencode 'customData={"qq":114514}' \
--data-urlencode 'customData={"wechat":"logto"}' \
'http://<your-logto-endpoint>/api/users'

커스텀 데이터 필터는 항상 search, 아이덴티티 조회(identityType, identityProvider, identityId), excludeRoleId, excludeOrganizationId 등 다른 필터와 AND로 결합됩니다. 예를 들어, 다음 요청은 qq가 114514이고, 사용자 이름에 alice가 포함된 사용자를 반환합니다:

curl \
--get \
--data-urlencode 'customData={"qq":114514}' \
--data-urlencode 'search.username=%alice%' \
'http://<your-logto-endpoint>/api/users'

mode, joint, isCaseSensitive 파라미터는 키워드 검색에만 영향을 주며, customData에는 영향을 주지 않습니다.

customData 값이 유효한 JSON 객체가 아니거나(예: [] 또는 114514), 빈 객체 {}이거나, 어떤 레벨에서든 빈 객체 또는 배열을 포함하는 경우(예: {"profile":{}} 또는 {"tags":[]}), 또는 customData.qq, customData[qq], mode.customData와 같은 중첩 파라미터 이름을 사용할 경우 API는 항상 400 Bad Request를 반환합니다.