자습서: Amazon OpenSearch Service를 사용하여 검색 애플리케이션 생성 - Amazon OpenSearch 서비스

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

자습서: Amazon OpenSearch Service를 사용하여 검색 애플리케이션 생성

Amazon OpenSearch Service로 검색 애플리케이션을 생성하는 일반적인 방법은 웹 양식을 사용해 사용자 쿼리를 서버로 전송하는 것입니다. 그런 다음 서버가 OpenSearch API를 직접 호출하여 OpenSearch Service로 요청을 전송할 수 있도록 권한을 부여하면 됩니다. 하지만 서버에 의존하지 않는 클라이언트 측 코드를 작성하려면 보안 및 성능 위험을 상쇄해야 합니다. OpenSearch API에 대한 무서명 공개 액세스를 허용하는 것은 권장하지 않습니다. 사용자가 보호되지 않은 엔드포인트에 액세스하거나 너무 광범위한 쿼리(또는 너무 많은 쿼리)로 클러스터 성능에 악영향을 미칠 수 있습니다.

이 장에서는 Amazon API Gateway로 사용자를 OpenSearch API 및 AWS Lambda의 하위 집합으로 제한하여 API Gateway에서 OpenSearch Service로 보내는 요청에 서명하도록 하는 솔루션을 소개합니다.

검색 애플리케이션 흐름도.
참고

표준 API Gateway 및 Lambda 요금 정책이 적용되지만, 이 자습서에서는 사용량이 제한적이므로 비용은 무시할만한 수준입니다.

사전 조건

이 자습서의 사전 조건은 OpenSearch Service 도메인입니다. 아직 도메인이 없는 경우 OpenSearch Service 도메인 생성 단계에 따라 도메인을 생성합니다.

1단계: 샘플 데이터 인덱싱

sample-movies.zip을 다운로드하여 압축을 해제한 다음 _bulk API 작업을 사용하여 5,000개 문서를 movies 인덱스에 추가합니다.

POST https://search-my-domain.us-west-1.es.amazonaws.com/_bulk { "index": { "_index": "movies", "_id": "tt1979320" } } {"directors":["Ron Howard"],"release_date":"2013-09-02T00:00:00Z","rating":8.3,"genres":["Action","Biography","Drama","Sport"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg","plot":"A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.","title":"Rush","rank":2,"running_time_secs":7380,"actors":["Daniel Brühl","Chris Hemsworth","Olivia Wilde"],"year":2013,"id":"tt1979320","type":"add"} { "index": { "_index": "movies", "_id": "tt1951264" } } {"directors":["Francis Lawrence"],"release_date":"2013-11-11T00:00:00Z","genres":["Action","Adventure","Sci-Fi","Thriller"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTAyMjQ3OTAxMzNeQTJeQWpwZ15BbWU4MDU0NzA1MzAx._V1_SX400_.jpg","plot":"Katniss Everdeen and Peeta Mellark become targets of the Capitol after their victory in the 74th Hunger Games sparks a rebellion in the Districts of Panem.","title":"The Hunger Games: Catching Fire","rank":4,"running_time_secs":8760,"actors":["Jennifer Lawrence","Josh Hutcherson","Liam Hemsworth"],"year":2013,"id":"tt1951264","type":"add"} ...

위는 사용 가능한 데이터의 하위 세트를 포함하는 예제 명령입니다. _bulk 작업을 수행하려면 sample-movies 파일의 전체 내용을 복사하여 붙여 넣어야 합니다. 자세한 지침은 옵션 2: 여러 문서 업로드을 참조하세요.

또한 다음 curl 명령을 사용하여 동일한 결과를 얻을 수도 있습니다.

curl -XPOST -u 'master-user:master-user-password' 'domain-endpoint/_bulk' --data-binary @bulk_movies.json -H 'Content-Type: application/json'

2단계: Lambda 함수 생성 및 배포

API Gateway에서 API를 생성하기 전에 요청을 전달하는 Lambda 함수를 만듭니다.

Lambda 함수 생성

이 솔루션에서는 API Gateway가 요청을 다음 Lambda 함수로 전달합니다. 그러면 이 함수가 OpenSearch Service를 쿼리하고 결과를 반환합니다. 이 샘플 함수는 외부 라이브러리를 사용하므로 배포 패키지를 생성하고 Lambda에 업로드해야 합니다.

배포 패키지를 만드는 방법
  1. 명령 프롬프트를 열고 my-opensearch-function 프로젝트 디렉터리를 만듭니다. 예를 들어, macOS에서는 다음을 수행합니다.

    mkdir my-opensearch-function
  2. my-sourcecode-function 프로젝트 디렉터리로 이동합니다.

    cd my-opensearch-function
  3. 다음과 같은 샘플 Python 코드의 콘텐츠를 복사하고 이름이 opensearch-lambda.py인 새 파일에 저장합니다. 리전 및 호스트 엔드포인트를 파일에 추가합니다.

    import boto3 import json import requests from requests_aws4auth import AWS4Auth region = '' # For example, us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) host = '' # The OpenSearch domain endpoint with https:// and without a trailing slash index = 'movies' url = host + '/' + index + '/_search' # Lambda execution starts here def lambda_handler(event, context): # Put the user query into the query DSL for more accurate search results. # Note that certain fields are boosted (^). query = { "size": 25, "query": { "multi_match": { "query": event['queryStringParameters']['q'], "fields": ["title^4", "plot^2", "actors", "directors"] } } } # Elasticsearch 6.x requires an explicit Content-Type header headers = { "Content-Type": "application/json" } # Make the signed HTTP request r = requests.get(url, auth=awsauth, headers=headers, data=json.dumps(query)) # Create the response and add some extra content to support CORS response = { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": '*' }, "isBase64Encoded": False } # Add the search results to the response response['body'] = r.text return response
  4. 외부 라이브러리를 새 package 디렉터리에 설치합니다.

    pip3 install --target ./package boto3 pip3 install --target ./package requests pip3 install --target ./package requests_aws4auth
  5. 루트에서 설치된 라이브러리를 포함하는 배포 패키지를 만듭니다. 다음 명령을 실행하면 프로젝트 디렉터리에 my-deployment-package.zip 파일이 생성됩니다.

    cd package zip -r ../my-deployment-package.zip .
  6. zip 파일의 루트에 opensearch-lambda.py 파일을 추가합니다.

    cd .. zip my-deployment-package.zip opensearch-lambda.py

Lambda 함수 및 배포 패키지를 만드는 방법에 대한 자세한 내용은 AWS Lambda 개발자 안내서zip 파일 아카이브를 사용하여 Python Lambda 함수 배포 및 본 가이드의 Lambda 배포 패키지 생성를 참조하세요.

Lambda 콘솔을 사용하여 함수를 만들려면

  1. https://console.aws.amazon.com/lambda/home에서 Lambda 콘솔로 이동합니다. 왼쪽 탐색 창에서 함수를 선택합니다.

  2. 함수 생성을 선택합니다.

  3. 다음 필드를 구성합니다.

    • 함수 이름: opensearch-function

    • 런타임 – Python 3.9

    • 아키텍처: x86_64

    다른 모든 기본 옵션은 그대로 두고 함수 생성을 선택합니다.

  4. 함수 요약 페이지의 코드 소스 섹션에서 드롭다운에서 업로드를 선택하고 .zip 파일을 선택합니다. 생성한 my-deployment-package.zip 파일을 찾아 저장을 선택합니다.

  5. 핸들러는 이벤트를 처리하는 함수 코드의 메서드입니다. 런타임 설정에서 편집을 선택하고 Lambda 함수가 있는 배포 패키지의 파일 이름에 따라 핸들러 이름을 변경합니다. 파일 이름이 opensearch-lambda.py이므로 핸들러 이름을 opensearch-lambda.lambda_handler로 변경합니다. 자세한 내용은 Python의 Lambda 함수 핸들러를 참조하세요.

3단계: API Gateway에서 API 생성

API Gateway를 사용하면 보다 제한된 API를 생성하고 OpenSearch _search API와의 상호 작용을 간소화할 수 있습니다. API Gateway를 사용하면 Amazon Cognito 인증 및 요청 조절 같은 보안 기능을 활성화할 수도 있습니다. API를 생성하고 배포하려면 다음 단계를 수행합니다.

API 생성 및 구성

API Gateway 콘솔을 사용하여 API를 생성하려면

  1. https://console.aws.amazon.com/apigateway/home에서 API Gateway 콘솔로 이동합니다. 왼쪽 탐색 창에서 API를 선택합니다.

  2. REST API(비공개 아님)를 찾고 빌드(Build)를 선택합니다.

  3. 다음 페이지에서 새 API 생성 섹션을 찾아 새 API가 선택되어 있는지 확인합니다.

  4. 다음 필드를 구성합니다.

    • API 이름: OpenSearch-api

    • 설명: Amazon OpenSearch Service 도메인을 검색하기 위한 퍼블릭 API

    • 엔드포인트 유형: 리전별

  5. API 생성(Create API)을 선택합니다.

  6. 작업(Actions)메서드 생성(Create Method)을 선택합니다.

  7. 드롭다운에서 GET을 선택하고 확인 표시를 클릭하여 확인합니다.

  8. 다음 설정을 구성한 다음 저장(Save)을 선택합니다.

설정
통합 유형 Lambda 함수
Lambda 프록시 통합 사용
Lambda 리전 us-west-1
Lambda 함수 opensearch-lambda
기본 제한 시간 사용

메서드 요청 구성

메서드 요청(Method Request)을 선택하고 다음 설정을 구성합니다.

설정
권한 부여 NONE
요청 검사기

쿼리 문자열 파라미터 및 헤더 검사

필수 API 키 false

URL 쿼리 문자열 파라미터에서 쿼리 문자열 추가를 선택하고 다음 파라미터를 구성합니다.

설정
명칭 q
필수

API 배포 및 단계 구성

API Gateway 콘솔에서 배포를 생성하고 새 단계 또는 기존 단계에 연결하여 API를 배포할 수 있습니다.

  1. 작업(Actions)API 배포(Deploy API)를 선택합니다.

  2. 배포 단계(Deployment stage)에서 새 단계(New Stage)를 클릭하고 단계 이름을 opensearch-api-test로 지정합니다.

  3. 배포(Deploy)를 선택합니다.

  4. 단계 편집기에서 다음 설정을 구성한 다음 변경 내용 저장(Save Changes)을 선택합니다.

설정
조절 활성화
Rate

1000

버스트 500

이러한 설정은 엔드포인트 루트에 대한 GET 요청(https://some-id.execute-api.us-west-1.amazonaws.com/search-es-api-test) 메서드 하나뿐인 API를 구성합니다. 이 요청에는 파라미터 하나(q), 즉 검색할 쿼리 문자열이 필요합니다. 메서드를 호출하면 요청이 Lambda로 전송되어 opensearch-lambda 함수가 실행됩니다. 자세한 내용은 Amazon API Gateway에서 API 생성Amazon API Gateway에서 REST API 배포를 참조하세요.

4단계: (선택 사항) 도메인 액세스 정책 수정

OpenSearch Service 도메인에서 Lambda 함수가 movies 인덱스에 GET 요청을 수행할 수 있도록 허용해야 합니다. 도메인에 세분화된 액세스 제어가 활성화된 오픈 액세스 정책이 있는 경우 그대로 둘 수 있습니다.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "es:*", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name/*" } ] }

또는 도메인 액세스 정책을 보다 세분화하도록 선택할 수 있습니다. 예를 들어 다음 최소 정책은 opensearch-lambda-role(Lambda를 통해 생성됨)에 movies 인덱스에 대한 읽기 액세스를 제공합니다. Lambda가 자동으로 생성하는 역할의 정확한 이름을 얻으려면 AWS Identity and Access Management(IAM) 콘솔로 이동하여 역할(Roles)을 클릭하고 “lambda”를 검색합니다.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/service-role/opensearch-lambda-role-1abcdefg" }, "Action": "es:ESHttpGet", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name/movies/_search" } ] }
중요

도메인에 대해 세분화된 액세스 제어를 활성화한 경우 OpenSearch 대시보드에서 역할을 사용자에게 매핑해야 합니다. 그러지 않으면 권한 오류가 표시됩니다.

액세스 정책에 대한 자세한 내용은 액세스 정책 구성 섹션을 참조하세요.

Lambda 역할 매핑(세분화된 액세스 제어를 사용하는 경우)

세분화된 액세스 제어를 사용하면 애플리케이션을 테스트하기 전에 추가 단계가 안내됩니다. 다른 모든 목적으로 HTTP 기본 인증을 사용하더라도 Lambda 역할을 사용자에게 매핑해야 합니다. 그러지 않으면 권한 오류가 표시됩니다.

  1. 도메인에 대한 OpenSearch 대시보드 URL로 이동합니다.

  2. 기본 메뉴에서 보안, 역할을 선택한 후 Lambda 역할을 매핑해야 할 역할인 all_access에 대한 링크를 선택합니다.

  3. 매핑된 사용자(Mapped users), 매핑 관리(Manage mapping)를 차례로 선택합니다.

  4. Backend roles(백엔드 역할)에서 Lambda 역할의 Amazon 리소스 이름(ARN)을 추가합니다. ARN은 arn:aws:iam::123456789123:role/service-role/opensearch-lambda-role-1abcdefg 형식을 취해야 합니다.

  5. Map(맵)을 선택하고 Mapped users(매핑된 사용자)에 사용자 또는 역할이 나타나는지 확인합니다.

5단계: 웹 애플리케이션 테스트

웹 애플리케이션을 테스트하려면
  1. sample-site.zip을 다운로드하고 압축을 해제하여 자주 사용하는 텍스트 편집기에서 scripts/search.js를 엽니다.

  2. apigatewayendpoint 변수를 업데이트하여 API Gateway 엔드포인트를 가리키도록 하고 지정된 경로의 끝에 백슬래시를 추가합니다. 단계(Stages)를 선택하고 API의 이름을 선택하여 API Gateway에서 엔드포인트를 빠르게 찾을 수 있습니다. apigatewayendpoint 변수는 https://some-id.execute-api.us-west-1.amazonaws.com/opensearch-api-test/의 형식을 취해야 합니다.

  3. index.html을 열고 thor, house 등 몇 가지 단어를 검색해 봅니다.

    thor에 대한 샘플 검색입니다.

CORS 오류 문제 해결

Lambda 함수가 CORS를 지원하기 위해 응답에 콘텐츠를 포함하더라도 다음과 같은 오류가 계속 표시될 수 있습니다.

Access to XMLHttpRequest at '<api-gateway-endpoint>' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present in the requested resource.

이러한 상황이 발생하면 다음 작업을 시도합니다.

  1. GET 리소스에서 CORS를 활성화합니다. 고급(Advanced)에서 Access-Control-Allow-Credentials'true'로 설정합니다.

  2. API Gateway에서 API를 재배포합니다(작업(Actions), API 배포(Deploy API)).

  3. Lambda 함수 트리거를 삭제하고 다시 추가합니다. 다시 추가하려면 트리거 추가를 선택하고 함수를 호출하는 HTTP 엔드포인트를 생성합니다. 트리거 구성은 다음과 같아야 합니다.

    트리거 API 배포 단계 보안
    API Gateway OpenSearch-api OpenSearch-api-test 열기

다음 단계

이 장은 개념을 설명하기 위한 출발점에 불과합니다. 다음과 같은 수정을 고려할 수 있습니다.

  • OpenSearch Service 도메인에 사용자의 데이터를 추가합니다.

  • 사용자의 API에 메서드를 추가합니다.

  • Lambda 함수에서 검색 쿼리를 수정하거나 다른 필드를 부스트합니다.

  • 결과 스타일을 다르게 지정하거나 search.js를 수정하여 사용자에게 다른 필드를 표시합니다.