튜토리얼: 원격 함수를 사용하여 객체 테이블 분석

이 튜토리얼에서는 꽃 데이터 세트 이미지를 기반으로 객체 테이블을 만들고, Cloud Vision API를 사용하여 이미지를 라벨링하는 원격 함수를 만들고, 원격 함수를 사용해서 객체 테이블에서 이미지를 분석하는 방법을 보여줍니다.

필수 권한

  • 데이터 세트를 만들려면 bigquery.datasets.create 권한이 필요합니다.
  • 연결 리소스를 만들려면 다음 권한이 필요합니다.

    • bigquery.connections.create
    • bigquery.connections.get
  • 연결의 서비스 계정에 권한을 부여하려면 다음 권한이 필요합니다.

    • resourcemanager.projects.setIamPolicy
  • 객체 테이블을 만들려면 다음 권한이 필요합니다.

    • bigquery.tables.create
    • bigquery.tables.update
    • bigquery.connections.delegate
  • 원격 함수를 만들려면 Cloud Functions 개발자 역할과 연결된 권한이 필요합니다.

  • 원격 함수를 호출하려면 Cloud Run 호출자 역할이 필요합니다.

  • 원격 함수로 객체 테이블을 분석하려면 객체 테이블에 대해 bigquery.tables.getData 권한이 필요합니다.

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

  • BigQuery: BigQuery에서 생성한 객체 테이블의 스토리지 비용이 발생합니다.
  • Cloud Functions: 원격 함수 호출과 여기에 사용되는 컴퓨팅 리소스(Cloud Vision API 호출 포함)에는 비용이 발생합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

Cloud Storage 가격에 대한 자세한 내용은 Cloud Storage 가격 책정 페이지를 참조하세요.

BigQuery 스토리지 가격 책정에 대한 자세한 내용은 BigQuery 문서에서 스토리지 가격 책정을 참조하세요.

Cloud Functions 가격 책정에 대한 자세한 내용은 Cloud Functions 가격 책정 페이지를 참조하세요.

Vision API 가격 책정에 대한 자세한 내용은 Vision 문서에서 Cloud Vision 가격 책정을 참조하세요.

시작하기 전에

  1. Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  3. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  4. API BigQuery, BigQuery Connection API, and Cloud Functions 사용 설정

    API 사용 설정

  5. Google Cloud Console의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.

    프로젝트 선택기로 이동

  6. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  7. API BigQuery, BigQuery Connection API, and Cloud Functions 사용 설정

    API 사용 설정

Cloud Functions 함수 만들기

함수를 만들려면 다음 단계를 따르세요.

  1. Cloud Functions 페이지로 이동합니다.

    Cloud Functions로 이동

  2. 함수 만들기를 클릭합니다.

  3. 환경에서 2세대를 선택합니다.

  4. 함수 이름으로 vision-ai를 입력합니다.

  5. 다음을 클릭합니다.

  6. 런타임에 대해 Python 3.9를 선택합니다.

  7. 진입점label_detection을 입력합니다.

  8. main.py를 선택합니다. 다음 코드를 복사하여 붙여넣습니다.

    Python

    import urllib.request
    
    import flask
    import functions_framework
    from google.cloud import vision
    
    @functions_framework.http
    def label_detection(request: flask.Request) -> flask.Response:
        """BigQuery remote function to label input images.
        Args:
            request: HTTP request from BigQuery
            https://cloud.google.com/bigquery/docs/reference/standard-sql/remote-functions#input_format
        Returns:
            HTTP response to BigQuery
            https://cloud.google.com/bigquery/docs/reference/standard-sql/remote-functions#output_format
        """
        try:
            client = vision.ImageAnnotatorClient()
            calls = request.get_json()["calls"]
            replies = []
            for call in calls:
                content = urllib.request.urlopen(call[0]).read()
                results = client.label_detection({"content": content})
                replies.append(vision.AnnotateImageResponse.to_dict(results))
            return flask.make_response(flask.jsonify({"replies": replies}))
        except Exception as e:
            return flask.make_response(flask.jsonify({"errorMessage": str(e)}), 400)
    
    

  9. requirements.txt를 선택합니다. 다음 텍스트를 복사하여 붙여넣습니다.

    Flask==2.2.2
    functions-framework==3.5.0
    google-cloud-vision==3.4.2
    Werkzeug==2.3.7
    

  10. 배포를 클릭합니다.

  11. 함수 배포가 완료되면 트리거 탭을 클릭합니다.

  12. 트리거 URL 값을 복사하여 다른 곳에 저장합니다. 이 정보는 원격 함수를 만들 때 필요합니다.

데이터 세트 만들기

remote_function_test라는 데이터 세트를 만듭니다.

SQL

  1. BigQuery 페이지로 이동합니다.

    BigQuery로 이동

  2. 편집자 창에서 다음 SQL 문을 실행합니다.

    CREATE SCHEMA `PROJECT_ID.remote_function_test`;
    

    PROJECT_ID를 프로젝트 ID로 바꿉니다.

bq

  1. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    Cloud Shell 활성화

  2. bq mk 명령어를 실행하여 데이터 세트를 만듭니다.

      bq mk --dataset --location=us PROJECT_ID:remote_function_test
      

    PROJECT_ID를 프로젝트 ID로 바꿉니다.

연결 만들기

lake-connection이라는 연결을 만듭니다.

콘솔

  1. BigQuery 페이지로 이동합니다.

    BigQuery로 이동

  2. 데이터 추가를 클릭한 다음 외부 데이터 소스를 클릭합니다.

  3. 연결 유형 목록에서 BigLake 및 원격 함수(Cloud 리소스)를 선택합니다.

  4. 연결 ID 필드에 lake-connection을 입력합니다.

  5. 연결 만들기를 클릭합니다.

  6. 연결 정보 창에서 서비스 계정 ID 필드의 값을 복사하여 다른 곳에 저장합니다. 연결의 서비스 계정에 권한을 부여하려면 이 정보가 필요합니다.

bq

  1. Cloud Shell에서 bq mk 명령어를 실행하여 연결을 만듭니다.

    bq mk --connection --location=us --connection_type=CLOUD_RESOURCE \
    lake-connection
    
  2. bq show 명령어를 실행하여 연결에 대한 정보를 검색합니다.

    bq show --connection us.lake-connection
    
  3. properties 열에서 serviceAccountId 속성 값을 복사하여 다른 위치에 저장합니다. 연결의 서비스 계정에 권한을 부여하려면 이 정보가 필요합니다.

Cloud Storage 버킷 만들기

꽃 데이터 세트를 포함할 Cloud Storage 버킷을 만듭니다.

연결의 서비스 계정에 권한 부여

서비스 계정에 이 권한을 부여하려면 다음 단계를 따르세요.

  1. IAM 및 관리자 페이지로 이동합니다.

    IAM 및 관리자로 이동

  2. 액세스 권한 부여를 클릭합니다.

    주 구성원 추가 대화상자가 열립니다.

  3. 새 주 구성원 필드에 앞에서 복사한 서비스 계정 ID를 입력합니다.

  4. 역할 선택 필드에서 Cloud Run을 선택한 후 Cloud Run 호출자를 선택합니다.

  5. 다른 역할 추가를 클릭합니다.

  6. 역할 선택 필드에서 Cloud Storage를 선택한 후 스토리지 객체 뷰어를 선택합니다.

  7. 저장을 클릭합니다.

Cloud Storage에 데이터 세트 업로드

데이터 세트 파일을 가져와 Cloud Storage에서 사용할 수 있도록 만듭니다.

  1. 꽃 데이터 세트를 로컬 머신에 다운로드합니다.
  2. 이전에 만든 버킷에 데이터 세트를 업로드합니다.

객체 테이블 만들기

업로드한 꽃 데이터 세트를 기반으로 sample_images라는 객체 테이블을 만듭니다.

SQL

  1. BigQuery 페이지로 이동합니다.

    BigQuery로 이동

  2. 편집자 창에서 다음 SQL 문을 실행합니다.

    CREATE EXTERNAL TABLE remote_function_test.sample_images
    WITH CONNECTION `us.lake-connection`
    OPTIONS(
      object_metadata = 'SIMPLE',
      uris = ['gs://BUCKET_NAME/*']);
    

    BUCKET_NAME을 이전에 만든 버킷의 이름으로 바꿉니다.

bq

Cloud Shell에서 bq mk 명령어를 실행하여 연결을 만듭니다.

bq mk --table \
--external_table_definition=gs:"//BUCKET_NAME/*@us.lake-connection" \
--object_metadata=SIMPLE \
remote_function_test.sample_images

BUCKET_NAME을 이전에 만든 버킷의 이름으로 바꿉니다.

BigQuery 원격 함수 만들기

label_detection이라는 원격 함수를 만듭니다.

  1. BigQuery 페이지로 이동합니다.

    BigQuery로 이동

  2. 편집자 창에서 다음 SQL 문을 실행합니다.

    CREATE OR REPLACE FUNCTION `remote_function_test.label_detection` (signed_url_ STRING) RETURNS JSON
    REMOTE WITH CONNECTION `us.lake-connection`
    OPTIONS(
    endpoint = 'TRIGGER_URL',
    max_batching_rows = 1
    );
    

    TRIGGER_URL을 이전에 저장한 트리거 URL로 바꿉니다. URL은 https://vision-ai-1abcd2efgh-uc.a.run.app과 비슷하게 표시됩니다.

원격 함수 호출

sample_images 객체 테이블에서 label_detection 원격 함수를 호출합니다.

  1. BigQuery 페이지로 이동합니다.

    BigQuery로 이동

  2. 편집자 창에서 다음 SQL 문을 실행합니다.

    SELECT uri, remote_function_test.label_detection(signed_url)
    FROM EXTERNAL_OBJECT_TRANSFORM(
    TABLE remote_function_test.sample_images,
    ["SIGNED_URL"]
    )
    LIMIT 100;
    

    결과는 다음과 비슷하게 표시됩니다.

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | uri                                                           | f0_                                                                                                            |
    —---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    |  gs://bq_huron_demo/flowers/daisy/100080576_f52e8ee070_n.jpg  |  {"face_annotations":[],"label_annotations":[{"confidence":0.0,"description":"Flower",                         |
    |                                                               |  "locale":"","locations":[],"mid":"/m/0c9ph5","properties":[],"score":0.9785631,"topicality":0.9785631},       |
    |                                                               |  {"confidence":0.0,"description":"Plant","locale":"","locations":[],"mid":"/m/05s2s","properties":[],          |
    |                                                               |  "Score":0.9635679,"topicality":0.9635679},{"confidence":0.0,"description":"camomile","locale":"",             |
    |                                                               |  "locations":[],"mid":"/m/011bc8hg","properties":[],"score":0.9110366,"topicality":0.9110366},                 |
    |                                                               |  {"confidence":0.0,"description":"Petal","locale":"","locations":[],"mid":"/m/016q19","properties":[],         |
    |                                                               |  "score":0.8927441,"topicality":0.8927441},{"confidence":0.0,"description":"Chamaemelum nobile","locale":"",   |
    |                                                               |  "locations":[],"mid":"/m/05cmcg","properties":[],"score":0.8460995,"topicality":0.8460995},                   |
    |                                                               |   {"confidence":0.0,"description":"Flowering plant","locale":"","locations":[],"mid":"/m/04sjm",               |
    |                                                               |  "properties":[],"score":0.7642974,"topicality":0.7642974},{"confidence":0.0,"description":"Annual plant",     |
    |                                                               |  "locale":"","locations":[],"mid":"/m/0jqb","properties":[],"score":0.7478164,                                 |
    |                                                               |  "topicality":0.7478164},{"confidence":0.0,"description":"Close-up","locale":"","locations":[],                |
    |                                                               |  "mid":"/m/02cqfm","properties":[],"score":0.7207553,"topicality":0.7207553},{"confidence":0.0,                |
    |                                                               |  "description":"Oxeye daisy","locale":"","locations":[],"mid":"/m/02qvnf","properties":[],                     |
    |                                                               |  "score":0.71786934,"topicality":0.71786934},{"confidence":0.0,"description":"Daisy family","locale":"",       |
    |                                                               |  "locations":[],"mid":"/m/0l5r","properties":[],"score":0.7164383,"topicality":0.7164383}],                    |
    |                                                               |  "landmark_annotations":[],"localized_object_annotations":[],"logo_annotations":[],"text_annotations":[]}      |
    —---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | gs://bq_huron_demo/flowers/daisy/10140303196_b88d3d6cec.jpg   |  {"face_annotations":[],"label_annotations":[{"confidence":0.0,"description":"Flower","locale":"",             |
    |                                                               |  "locations":[],"mid":"/m/0c9ph5","properties":[],"score":0.9770426,"topicality":0.9770426},                   |
    |                                                               |  {"confidence":0.0,"description":"Plant","locale":"","locations":[],"mid":"/m/05s2s",                          |
    |                                                               |  "Properties":[],"score":0.95798975,"topicality":0.95798975},{"confidence":0.0,                                |
    |                                                               |  "description":"Petal","locale":"","locations":[],"mid":"/m/016q19","properties":[],                           |
    |                                                               |  "score":0.88984144,"topicality":0.88984144},{"confidence":0.0,"description":"Yellow",                         |
    |                                                               |  "locale":"","locations":[],"mid":"/m/088fh","properties":[],"score":0.84456813,                               |
    |                                                               |  "Topicality":0.84456813},{"confidence":0.0,"description":"camomile","locale":"",                              |
    |                                                               |  "locations":[],"mid":"/m/011bc8hg","properties":[],"score":0.7926449, "topicality":0.7926449},                |
    |                                                               |  {"confidence":0.0,"description":"Annual plant","locale":"","locations":[],"mid":"/m/0jqb",                    |
    |                                                               |  "Properties":[],"score":0.75020844, "topicality":0.75020844},{"confidence":0.0,                               |
    |                                                               |  "description":"Flowering plant","locale":"","locations":[],"mid":"/m/04sjm",                                  |
    |                                                               |  "Properties":[],"score":0.7403478,"topicality":0.7403478},{"confidence":0.0,                                  |
    |                                                               |  "description":"Chamaemelum nobile","locale":"","locations":[],"mid":"/m/05cmcg",                              |
    |                                                               |  "Properties":[],"score":0.7264577,"topicality":0.7264577},{"confidence":0.0,                                  |
    |                                                               |  "description":"Close-up","locale":"","locations":[],"mid":"/m/02cqfm","properties":[],                        |
    |                                                               |  "score":0.721242,"topicality":0.721242},{"confidence":0.0,"description":"Daisy family",                       |
    |                                                               |  "locale":"","locations":[],"mid":"/m/0l5r","properties":[],"score":0.7012979,                                 |
    |                                                               |  "Topicality":0.7012979}],"landmark_annotations":[],"localized_object_annotations":[],                         |
    |                                                               |  "logo_annotations":[],"text_annotations":[]}                                                                  |
    —------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------
    
    

삭제

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.