다음을 통해 공유


자습서: Azure Static Web Apps에서 Azure Cosmos DB 데이터베이스 연결 추가(미리 보기)

이 자습서에서는 Azure Cosmos DB for NoSQL 데이터베이스를 정적 웹앱에 연결하는 방법을 알아봅니다. 구성되면 백 엔드 코드를 작성하지 않고도 데이터를 조작하기 위해 기본 제공 /data-api 엔드포인트에 GraphQL 요청을 수행할 수 있습니다.

간단히 설명하기 위해 이 자습서에서는 로컬 개발 목적으로 Azure 데이터베이스를 사용하는 방법을 보여 주지만, 로컬 개발 요구 사항에 따라 로컬 데이터베이스 서버를 사용할 수도 있습니다.

참고 항목

이 자습서에서는 Azure Cosmos DB for NoSQL를 사용하는 방법을 보여 줍니다. 다른 데이터베이스를 사용하려면 Azure SQL, MySQL 또는 PostgreSQL 자습서를 참조하세요.

개발자 도구 콘솔 창에서 Cosmos DB의 결과를 보여 주는 웹 브라우저입니다.

이 자습서에서는 다음을 알아봅니다.

  • Azure Cosmos DB for NoSQL 데이터베이스를 정적 웹앱에 연결
  • 데이터의 만들기, 읽기, 업데이트 및 삭제

필수 조건

이 자습서를 완료하려면 기존 Azure Cosmos DB for NoSQL 데이터베이스 및 정적 웹앱이 있어야 합니다.

리소스 설명
Azure Cosmos DB for NoSQL 데이터베이스 아직 없는 경우 Azure Cosmos DB 데이터베이스 만들기 가이드의 단계를 수행합니다.
기존 정적 웹앱 아직 없는 경우 시작 가이드의 단계에 따라 프레임워크 없음 정적 웹앱을 만듭니다.

먼저 Azure Static Web Apps 데이터베이스 연결 기능을 사용하도록 데이터베이스를 구성합니다.

데이터베이스 연결 구성

데이터베이스 연결이 작동하려면 Azure Static Web Apps에 데이터베이스에 대한 네트워크 액세스 권한이 있어야 합니다. 또한 로컬 개발에 Azure 데이터베이스를 사용하려면 자체 IP 주소의 요청을 허용하도록 데이터베이스를 구성해야 합니다.

  1. Azure Portal에서 Azure Cosmos DB for NoSQL 계정으로 이동합니다.

  2. 설정 섹션에서 네트워킹을 선택합니다.

  3. 공용 액세스 섹션에서 모든 네트워크를 선택합니다. 이 작업을 통해 로컬 개발에 클라우드 데이터베이스를 사용하고, 배포된 Static Web Apps 리소스가 데이터베이스에 액세스할 수 있고, 포털에서 데이터베이스를 쿼리할 수 있습니다.

  4. 저장을 선택합니다.

로컬 개발을 위한 데이터베이스 연결 문자열 가져오기

로컬 개발에 Azure 데이터베이스를 사용하려면 데이터베이스의 연결 문자열을 검색해야 합니다. 개발 목적으로 로컬 데이터베이스를 사용하려는 경우 이 단계를 건너뛸 수 있습니다.

  1. Azure Portal에서 Azure Cosmos DB for NoSQL 계정으로 이동합니다.

  2. 설정 섹션에서 를 선택합니다.

  3. 기본 연결 문자열 상자에서 연결 문자열을 복사하고 텍스트 편집기에서 따로 설정합니다.

샘플 데이터 만들기

샘플 테이블을 만들고 자습서와 일치하도록 샘플 데이터로 시드합니다.

  1. 왼쪽 탐색 창에서 Data Explorer를 선택합니다.

  2. 새 컨테이너를 선택합니다. 데이터베이스 ID를 Create new로 입력하고 값을 MyTestPersonDatabase로 입력합니다.

  3. MyTestPersonContainer의 컨테이너 ID를 입력합니다.

  4. id의 파티션 키를 입력합니다(이 값에는 / 접두사가 있음).

  5. 확인을 선택합니다.

  6. MyTestPersonContainer 컨테이너를 선택합니다.

  7. 해당 항목을 선택합니다.

  8. 새 항목을 선택하고 다음 값을 입력합니다.

    {
        "id": "1",
        "Name": "Sunny"
    }
    

정적 웹앱 구성

이 자습서의 나머지 부분에서는 데이터베이스 연결을 로컬로 사용하도록 정적 웹앱의 소스 코드를 편집하는 데 중점을 둡니다.

Important

다음 단계에서는 시작 가이드에서 만든 정적 웹앱으로 작업하고 있다고 가정합니다. 다른 프로젝트를 사용하는 경우 분기 이름과 일치하도록 다음 git 명령을 조정해야 합니다.

  1. main 분기로 전환합니다.

    git checkout main
    
  2. git pull을 사용하여 로컬 버전을 GitHub의 버전과 동기화합니다.

    git pull origin main
    

데이터베이스 구성 파일 만들기

다음으로, 정적 웹앱이 데이터베이스와 인터페이스하는 데 사용하는 구성 파일을 만듭니다.

  1. 터미널을 열고 연결 문자열을 저장할 새 변수를 만듭니다. 특정 구문은 사용 중인 셸 유형에 따라 달라질 수 있습니다.

    export DATABASE_CONNECTION_STRING='<YOUR_CONNECTION_STRING>'
    

    <YOUR_CONNECTION_STRING>을 텍스트 편집기에서 따로 설정한 연결 문자열 값으로 바꿔야 합니다.

  2. npm을 사용하여 Static Web Apps CLI를 설치하거나 업데이트합니다. 상황에 가장 적합한 명령을 선택합니다.

    설치하려면 npm install을 사용합니다.

    npm install -g @azure/static-web-apps-cli
    

    업데이트하려면 npm update를 사용합니다.

    npm update
    
  3. swa db init 명령을 사용하여 데이터베이스 구성 파일을 생성합니다.

    swa db init --database-type cosmosdb_nosql --cosmosdb_nosql-database MyTestPersonDatabase
    

    init 명령은 swa-db-connections 폴더에 staticwebapp.database.config.json 파일을 생성합니다.

  4. 이 샘플 스키마를 생성한 staticwebapp.database.schema.gql 파일에 붙여넣습니다.

    Cosmos DB for NoSQL은 스키마에 구애받지 않는 데이터베이스이므로 Azure Static Web Apps 데이터베이스 연결은 데이터베이스의 스키마를 추출할 수 없습니다. staticwebapp.database.schema.gql 파일을 사용하면 Static Web Apps를 위한 Cosmos DB for NoSQL 데이터베이스의 스키마를 지정할 수 있습니다.

    type Person @model {
      id: ID
      Name: String
    }
    
  5. 이 샘플 구성을 생성한 파일 staticwebapp.database.config.json에 붙여넣습니다. Cosmos DB for NoSQL에는 데이터베이스의 스키마를 이해하기 위해 데이터베이스 연결에 필요한 Cosmos DB 데이터베이스 및 스키마 파일을 나타내는 더 많은 옵션이 data-source 개체에 있습니다.

{
  "$schema": "https://github.com/Azure/data-api-builder/releases/latest/download/dab.draft.schema.json",
  "data-source": {
    "database-type": "cosmosdb_nosql",
    "options": {
      "database": "MyTestPersonDatabase",
      "schema": "staticwebapp.database.schema.gql"
    },
    "connection-string": "@env('DATABASE_CONNECTION_STRING')"
  },
  "runtime": {
    "graphql": {
      "allow-introspection": true,
      "enabled": true,
      "path": "/graphql"
    },
    "host": {
      "mode": "production",
      "cors": {
        "origins": ["http://localhost:4280"],
        "allow-credentials": false
      },
      "authentication": {
        "provider": "StaticWebApps"
      }
    }
  },
  "entities": {
    "Person": {
      "source": "MyTestPersonContainer",
      "permissions": [
        {
          "actions": ["*"],
          "role": "anonymous"
        }
      ]
    }
  }
}

다음 단계로 이동하기 전에 구성 파일의 다양한 측면을 설명하는 다음 표를 검토합니다. 항목 수준 보안에 대한 관계와 정책과 같은 기능 및 구성 파일에 대한 전체 설명서는 데이터 API 작성기 설명서를 참조하세요.

기능 설명
데이터베이스 연결 개발 시 런타임은 구성 파일의 연결 문자열 값에서 연결 문자열을 읽습니다. 구성 파일에서 직접 연결 문자열을 지정할 수 있지만 연결 문자열을 로컬 환경 변수에 저장하는 것이 가장 좋습니다. @env('DATABASE_CONNECTION_STRING') 표기법을 통해 구성 파일에서 환경 변수 값을 참조할 수 있습니다. 데이터베이스를 연결할 때 수집된 정보로 배포된 사이트의 Static Web Apps에서 연결 문자열 값을 덮어씁니다.
API 엔드포인트 GraphQL 엔드포인트는 이 구성 파일에 구성된 대로 /data-api/graphql를 통해 사용할 수 있습니다. GraphQL 경로를 구성할 수 있지만 /data-api 접두사는 구성할 수 없습니다.
API 보안 runtime.host.cors 설정을 사용하면 API에 요청할 수 있는 허용된 원본을 정의할 수 있습니다. 이 경우 구성은 개발 환경을 반영하고 http://localhost:4280 위치를 허용 목록에 추가합니다.
엔터티 모델 경로를 통해 노출되는 엔터티를 GraphQL 스키마의 유형으로 정의합니다. 이 경우 Person이라는 이름은 엔드포인트에 노출되는 이름이고 entities.<NAME>.source은 데이터베이스 스키마 및 테이블 매핑입니다. API 엔드포인트 이름이 테이블 이름과 동일할 필요는 없습니다.
엔터티 보안 entity.<NAME>.permissions 배열에 나열된 권한 규칙은 엔터티에 대한 권한 부여 설정을 제어합니다. 역할을 사용하여 경로를 보호하는 것과 동일한 방식으로 역할을 사용하여 엔터티를 보호할 수 있습니다.

참고 항목

구성 파일의 connection-string, host.mode, graphql.allow-introspection 속성은 사이트를 배포할 때 덮어씁니다. 데이터베이스를 Static Web Apps 리소스에 연결할 때 수집된 인증 세부 정보로 연결 문자열을 덮어씁니다. host.mode 속성은 production으로 설정되고, graphql.allow-introspectionfalse로 설정됩니다. 이러한 재정의는 개발 및 프로덕션 워크로드에서 구성 파일의 일관성을 제공하는 동시에 데이터베이스 연결을 사용하도록 설정된 Static Web Apps 리소스가 안전하고 프로덕션 준비가 되도록 보장합니다.

이제 데이터베이스에 연결하도록 구성된 정적 웹앱을 사용하여 연결을 확인할 수 있습니다.

홈페이지 업데이트

index.html 파일에서 body 태그 사이의 마크업을 다음 HTML로 바꿉니다.

<h1>Static Web Apps Database Connections</h1>
<blockquote>
    Open the console in the browser developer tools to see the API responses.
</blockquote>
<div>
    <button id="list" onclick="list()">List</button>
    <button id="get" onclick="get()">Get</button>
    <button id="update" onclick="update()">Update</button>
    <button id="create" onclick="create()">Create</button>
    <button id="delete" onclick="del()">Delete</button>
</div>
<script>
    // add JavaScript here
</script>

로컬로 애플리케이션 시작

이제 웹 사이트를 실행하고 데이터베이스의 데이터를 직접 조작할 수 있습니다.

Important

Static Web Apps CLI에서 배포 보안을 강화하기 위해 2025년 1월 15일까지 Static Web Apps CLI의 최신 버전(2.0.2)으로 업그레이드해야 하는 호환성이 손상되는 변경이 도입되었습니다.

  1. npm을 사용하여 Static Web Apps CLI를 설치하거나 업데이트합니다. 상황에 가장 적합한 명령을 선택합니다.

    설치하려면 npm install을 사용합니다.

    npm install -g @azure/static-web-apps-cli
    

    업데이트하려면 npm update를 사용합니다.

    npm update
    
  2. 데이터베이스 구성을 사용하여 정적 웹앱을 시작합니다.

    swa start ./src --data-api-location swa-db-connections
    

이제 CLI가 시작되었으므로 staticwebapp.database.config.json 파일에 정의된 대로 엔드포인트를 통해 데이터베이스에 액세스할 수 있습니다.

http://localhost:4280/data-api/graphql 엔드포인트는 GraphQL 쿼리 및 변형을 허용합니다.

데이터 조작

다음 프레임워크에 구애받지 않는 명령은 데이터베이스에서 전체 CRUD 작업을 수행하는 방법을 보여 줍니다.

각 함수의 출력이 브라우저의 콘솔 창에 표시됩니다.

CMD/CTRL + SHIFT + I를 눌러 개발자 도구를 열고 콘솔 탭을 선택합니다.

모든 항목 나열

index.htmlscript 태그 사이에 다음 코드를 추가합니다.

async function list() {

  const query = `
      {
        people {
          items {
            id
            Name
          }
        }
      }`;
      
  const endpoint = "/data-api/graphql";
  const response = await fetch(endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ query: query })
  });
  const result = await response.json();
  console.table(result.data.people.items);
}

이 예에서는 다음이 적용됩니다.

  • GraphQL 쿼리는 데이터베이스에서 IdName 필드를 선택합니다.
  • 서버에 전달된 요청에는 query 속성에 쿼리 정의가 있는 페이로드가 필요합니다.
  • 응답 페이로드의 데이터는 data.people.items 속성에 있습니다.

페이지를 새로 고치고 목록 단추를 선택합니다.

이제 브라우저의 콘솔 창에 데이터베이스의 레코드가 모두 나열된 테이블이 표시됩니다.

id 속성
1 맑음
2 Dheeraj

브라우저에 어떻게 표시되는지 보여주는 스크린샷은 다음과 같습니다.

개발자 도구 콘솔 창에서 데이터베이스 선택 결과를 보여 주는 웹 브라우저입니다.

ID로 가져오기

index.htmlscript 태그 사이에 다음 코드를 추가합니다.

async function get() {

  const id = '1';

  const gql = `
    query getById($id: ID!) {
      person_by_pk(id: $id) {
        id
        Name
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id,
    },
  };

  const endpoint = "/data-api/graphql";
  const response = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query),
  });
  const result = await response.json();
  console.table(result.data.person_by_pk);
}

이 예에서는 다음이 적용됩니다.

  • GraphQL 쿼리는 데이터베이스에서 idName 필드를 선택합니다.
  • 서버에 전달된 요청에는 query 속성에 쿼리 정의가 있는 페이로드가 필요합니다.
  • 응답 페이로드의 데이터는 data.person_by_pk 속성에 있습니다.

페이지를 새로 고치고 가져오기 단추를 선택합니다.

이제 브라우저의 콘솔 창에 데이터베이스에서 요청한 단일 레코드가 나열된 테이블이 표시됩니다.

id 속성
1 맑음

엽데이트

index.htmlscript 태그 사이에 다음 코드를 추가합니다.

async function update() {

  const id = '1';
  const data = {
    id: id,
    Name: "Molly"
  };

  const gql = `
    mutation update($id: ID!, $_partitionKeyValue: String!, $item: UpdatePersonInput!) {
      updatePerson(id: $id, _partitionKeyValue: $_partitionKeyValue, item: $item) {
        id
        Name
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id,
      _partitionKeyValue: id,
      item: data
    } 
  };

  const endpoint = "/data-api/graphql";
  const res = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query)
  });

  const result = await res.json();
  console.table(result.data.updatePerson);
}

이 예에서는 다음이 적용됩니다.

  • GraphQL 쿼리는 데이터베이스에서 idName 필드를 선택합니다.
  • query 개체는 query 속성에 GraphQL 쿼리를 포함합니다.
  • GraphQL 함수에 대한 인수 값은 query.variables 속성을 통해 전달됩니다.
  • 서버에 전달된 요청에는 query 속성에 쿼리 정의가 있는 페이로드가 필요합니다.
  • 응답 페이로드의 데이터는 data.updatePerson 속성에 있습니다.

페이지를 새로 고치고 업데이트 단추를 선택합니다.

이제 브라우저의 콘솔 창에 업데이트된 데이터를 보여주는 테이블이 표시됩니다.

id 속성
1 Molly

만들기

index.htmlscript 태그 사이에 다음 코드를 추가합니다.

async function create() {

  const data = {
    id: "3",
    Name: "Pedro"
  };

  const gql = `
    mutation create($item: CreatePersonInput!) {
      createPerson(item: $item) {
        id
        Name
      }
    }`;
  
  const query = {
    query: gql,
    variables: {
      item: data
    } 
  };
  
  const endpoint = "/data-api/graphql";
  const result = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query)
  });

  const response = await result.json();
  console.table(response.data.createPerson);
}

이 예에서는 다음이 적용됩니다.

  • GraphQL 쿼리는 데이터베이스에서 idName 필드를 선택합니다.
  • query 개체는 query 속성에 GraphQL 쿼리를 포함합니다.
  • GraphQL 함수에 대한 인수 값은 query.variables 속성을 통해 전달됩니다.
  • 서버에 전달된 요청에는 query 속성에 쿼리 정의가 있는 페이로드가 필요합니다.
  • 응답 페이로드의 데이터는 data.updatePerson 속성에 있습니다.

페이지를 새로 고치고 만들기 단추를 선택합니다.

이제 브라우저의 콘솔 창에 데이터베이스의 새 레코드를 보여주는 테이블이 표시됩니다.

id 이름
3 Pedro

삭제

index.htmlscript 태그 사이에 다음 코드를 추가합니다.

async function del() {

  const id = '3';

  const gql = `
    mutation del($id: ID!, $_partitionKeyValue: String!) {
      deletePerson(id: $id, _partitionKeyValue: $_partitionKeyValue) {
        id
      }
    }`;

  const query = {
    query: gql,
    variables: {
      id: id,
    _partitionKeyValue: id
    }
  };

  const endpoint = "/data-api/graphql";
  const response = await fetch(endpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(query)
  });

  const result = await response.json();
  console.log(`Record deleted: ${ JSON.stringify(result.data) }`);
}

이 예에서는 다음이 적용됩니다.

  • GraphQL 쿼리는 데이터베이스에서 Id 필드를 선택합니다.
  • query 개체는 query 속성에 GraphQL 쿼리를 포함합니다.
  • GraphQL 함수에 대한 인수 값은 query.variables 속성을 통해 전달됩니다.
  • 서버에 전달된 요청에는 query 속성에 쿼리 정의가 있는 페이로드가 필요합니다.
  • 응답 페이로드의 데이터는 data.deletePerson 속성에 있습니다.

페이지를 새로 고치고 삭제 단추를 선택합니다.

이제 브라우저의 콘솔 창에 삭제 요청의 응답을 보여주는 테이블이 표시됩니다.

삭제된 레코드: 2

로컬에서 사이트 작업을 완료했으므로 이제 Azure에 배포할 수 있습니다.

사이트 배포

이 사이트를 프로덕션에 배포하려면 구성 파일을 커밋하고 변경 내용을 서버에 푸시하기만 하면 됩니다.

  1. 구성 변경 내용을 커밋합니다.

    git commit -am "Add database configuration"
    
  2. 서버에 변경 내용을 푸시합니다.

    git push origin main
    
  3. 웹앱이 빌드될 때까지 기다립니다.

  4. 브라우저에서 정적 웹앱으로 이동합니다.

  5. 목록 단추를 선택하여 모든 항목을 나열합니다.

    출력은 이 스크린샷에 표시된 것과 유사해야 합니다.

    개발자 도구 콘솔 창에 데이터베이스의 레코드를 나열한 결과를 보여 주는 웹 브라우저입니다.

데이터베이스를 정적 웹앱에 연결

다음 단계를 사용하여 사이트의 Static Web Apps 인스턴스와 데이터베이스 간에 연결을 만듭니다.

  1. Azure Portal의 Static Web App을 엽니다.

  2. 설정 섹션에서 데이터베이스 연결을 선택합니다.

  3. 프로덕션 섹션에서 기존 데이터베이스 연결 링크를 선택합니다.

  4. 기존 데이터베이스 연결 창에서 다음 값을 입력합니다.

    속성
    데이터베이스 유형 드롭다운 목록에서 데이터베이스 유형을 선택합니다.
    구독 드롭다운 목록에서 Azure 구독을 선택합니다.
    데이터베이스 이름 정적 웹앱에 연결할 데이터베이스의 이름을 선택합니다.
    인증 유형 연결 문자열을 선택합니다.
  5. 확인을 선택합니다.

데이터베이스가 Static Web Apps 리소스에 연결되어 있는지 확인

데이터베이스를 정적 웹앱에 연결하고 사이트 빌드가 완료되면 다음 단계를 사용하여 데이터베이스 연결을 확인합니다.

  1. Azure Portal의 Static Web App을 엽니다.

  2. Essentials 섹션에서 Static Web Apps 리소스의 URL을 선택하여 정적 웹앱으로 이동합니다.

  3. 목록 단추를 선택하여 모든 항목을 나열합니다.

    출력은 이 스크린샷에 표시된 것과 유사해야 합니다.

    개발자 도구 콘솔 창에 데이터베이스의 레코드를 나열한 결과를 보여 주는 웹 브라우저입니다.

리소스 정리

이 자습서에서 만든 리소스를 제거하려면 데이터베이스 연결을 해제하고 샘플 데이터를 제거해야 합니다.

  1. 데이터베이스 연결 해제: Azure Portal에서 정적 웹앱을 엽니다. 설정 섹션에서 데이터베이스 연결을 선택합니다. 연결된 데이터베이스 옆에 있는 세부 정보 보기를 선택합니다. 데이터베이스 연결 세부 정보 창에서 연결 해제 단추를 선택합니다.

  2. 샘플 데이터 제거: 데이터베이스에서 MyTestPersonContainer라는 테이블을 삭제합니다.

다음 단계