서버리스 API를 사용하여 정적 웹앱 만들기

로컬로 실행한 다음 서버리스 API를 사용하여 정적 웹앱을 Azure에 배포하는 방법을 알아봅니다. 이 자습서에서는 최신 Azure Functions Node.js 프로그래밍 모델의 미리 보기 버전을 사용합니다. 이 문서에서는 Azure Functions의 미리 보기 버전을 사용하므로 정적 웹앱과 별도의 앱으로 배포됩니다.

다음의 방법을 알아보세요.

  • Azure Function 앱을 사용하여 SWA(정적 웹앱 ) 로컬 실행
  • SWA CLI를 사용하여 로컬 백 엔드 API에 대한 로컬 프록시 프런트 엔드 요청입니다.
  • 동일한 코드를 원격으로 배포하고 실행합니다.

정적 웹앱 CLI에서 제공하는 프런트 엔드와 백 엔드 엔드 간의 프록시는 다음을 제공합니다.

  • React /api/todo의 URL은 API의 서버 또는 포트 번호를 지정하지 않습니다. SWA CLI에서 프록시를 자동으로 관리하므로 이 URL을 사용하는 요청은 로컬에서 성공합니다.
  • /.auth/login/<provider>에 액세스할 때 로컬 인증 에뮬레이터
  • 경로 관리 및 권한 부여

이 샘플의 인증

이 샘플의 인증은 Azure Static Web Apps 서비스의 프런트 엔드 사용자를 위해 제공됩니다.

  • 로그인/로그아웃
  • 퍼블릭 및 프라이빗 콘텐츠

이 샘플의 소스 코드

이 샘플의 소스 코드는 서버리스 API를 사용하여 정적 웹앱을 빌드하고 배포하는 방법을 알아보기 위한 것입니다. 코드는 프로덕션용이 아닙니다.

코드에서 모범 보안 사례를 따르지 않는 여러 위치를 찾을 수 있습니다. 예를 들어 코드는 브라우저 콘솔에 쓰는 데 사용합니다 console.log .

프로덕션 환경으로 이동하면 조직의 보안 모범 사례를 위반하는 코드를 검토하고 제거해야 합니다.

1. 개발 환경 준비

다음 계정을 만듭니다.

로컬 개발 컴퓨터에 다음을 설치합니다.

2. GitHub에서 샘플 리포지토리 포크

GitHub에서 배포를 완료하려면 샘플 리포지토리의 고유한 포크가 있어야 합니다. 포크 프로세스 중에 분기를 복사 main 하기만 하면 됩니다.

샘플 리포지토리를 포크합니다https://github.com/Azure-Samples/azure-typescript-e2e-apps. .

3. 포크된 샘플 리포지토리 복제

  1. bash 터미널에서 포크된 리포지토리를 로컬 컴퓨터에 복제합니다. 원래 샘플 리포지토리를 복제하지 마세요. URL의 예는 다음과 같습니다. https://github.com/YOUR-ACCOUNT-NAME/azure-typescript-e2e-apps

    git clone YOUR-FORKED-REPO-URL
    
  2. 로컬 프런트 엔드 앱에 대한 종속성을 설치합니다.

    cd app-react-vite && npm install 
    
  3. 로컬 백 엔드 앱에 대한 종속성을 설치합니다.

    cd ../api-inmemory && npm install && cd ..
    

4. 선택 사항, 로컬 앱 빌드 및 실행

샘플 리포지토리에는 프런트 엔드 및 백 엔드 앱의 여러 버전이 있습니다. 다음 단계에서는 프런트 엔드의 React 18(Vite) 버전과 API 경로가 있는 백 엔드의 Node.js 버전과 함께 Azure Function v4를 /status/todo 사용합니다.

  1. 샘플 앱의 루트에서 파일과 함께 SWA CLI를 ./swa-cli.config.json 사용하여 프런트 엔드 및 백 엔드 앱을 빌드합니다.

    swa build
    

    다양한 패키지의 버전 및 환경에 따라 발생할 수 있는 오류가 발생하는 경우 계속하기 전에 오류를 수정합니다. Azure Static Web Apps로 배포하기 전에 프로젝트가 로컬로 성공적으로 빌드된다는 것을 알아야 합니다.

  2. 샘플 앱의 루트에서 SWA CLI를 사용하여 프록시로 앱을 시작합니다.

    swa start
    
  3. bash 터미널에 다음 줄이 표시되면 프로젝트가 성공적으로 시작되었습니다.

    [swa] Serving static content:
    [swa]   /workspaces/azure-typescript-e2e-apps/app-react-vite/dist
    [swa] 
    [swa] Serving API:
    [swa]   /workspaces/azure-typescript-e2e-apps/api-inmemory
    [swa] 
    [swa] Azure Static Web Apps emulator started at http://0.0.0.0:4280. Press CTRL+C to exit.
    
  4. 프록시된 URL http://localhost:4280에 대한 웹 브라우저를 엽니다. 다음 페이지가 표시됩니다.

    Screenshot of local React app prior to authentication.

  5. SWA CLI에서 제공하는 인증을 사용하여 로그인할 수 있습니다. 이 프로세스는 클라우드 기반 Azure Static 웹앱에서 인증을 모의합니다. 프런트 엔드 코드는 엔드포인트를 /.auth/me 사용하여 사용자의 ID를 가져옵니다. 가짜 사용자 이름을 입력하고 나머지 필드를 변경하지 마세요.

    Screenshot of local React app's mock authentication form.

  6. 사용자가 인증되면 프런트 엔드는 API의 환경 변수와 같은 개인 정보를 표시합니다.

    Screenshot of local React app with authentication complete.

    이 API에 대한 Azure Function v4 앱 소스 코드는 다음과 같습니다.

    import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
    
    import { name, version } from '../../package.json';
    function isObject(v) {
        return '[object Object]' === Object.prototype.toString.call(v);
    };
    function sortJson(o){
        if (Array.isArray(o)) {
            return o.sort().map(sortJson);
        } else if (isObject(o)) {
            return Object
                .keys(o)
            .sort()
                .reduce(function(a, k) {
                    a[k] = sortJson(o[k]);
    
                    return a;
                }, {});
        }
        return o;
    }
    
    export async function status(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
        context.log(`Http function processed request for url "${request.url}"`);
    
        const sortedEnv = sortJson(process.env);
    
        return { jsonBody: {
            name,
            version,
            env: sortedEnv,
            requestHeaders: request.headers 
        }};
    };
    
    app.http('status', {
        route: "status",
        methods: ['GET'],
        authLevel: 'anonymous',
        handler: status
    });
    
  7. 공용 및 프라이빗 섹션을 확장하여 API의 콘텐츠가 표시되는지 확인합니다.

5. 새 Azure Functions 앱 만들기

API를 사용하여 정적 웹앱을 실행하는 이전 섹션은 선택 사항이었습니다. Azure 클라우드에 앱 및 API를 배포하려면 문서의 재기본 섹션이 필요합니다.

Azure Functions v4 런타임의 미리 보기 버전을 사용하려면 새 Azure Functions 앱을 만들어야 합니다. 또한 프록시되고 관리되는 API를 사용하는 대신 API에 대한 Fetch 요청에서 Azure Functions 앱 URI를 사용하도록 정적 웹앱을 다시 빌드하고 다시 배포해야 합니다.

  1. 웹 브라우저에서 Azure Portal을 열어 새 Azure Functions 앱 만들기: 새 앱 만들기

  2. 다음 정보를 사용하여 함수 앱을 만듭니다.

    탭:설정
    기본 사항: 구독 사용할 구독을 선택합니다.
    기본 사항: 리소스 그룹 와 같은 새 리소스 그룹을 만듭니다 first-static-web-app-with-api. 이름은 앱의 공용 URL에서 사용되지 않습니다. 리소스 그룹은 관련 Azure 리소스를 그룹화하고 관리하는 데 도움이 됩니다.
    기본 사항: 인스턴스 세부 정보: 함수 앱 이름 끝에 3개의 임의 문자가 추가되는 것과 같이 swa-api 전역적으로 고유한 이름을 입력합니다(예: swa-api-123.).
    기본 사항: 인스턴스 세부 정보: 코드 또는 컨테이너 Code를 선택합니다.
    기본 사항: 인스턴스 세부 정보: 런타임 스택 Node.js를 선택합니다.
    기본 사항: 인스턴스 세부 정보: 런타임 스택 18LTS를 선택합니다.
    기본 사항: 운영 체제 Linux를 선택합니다.
    기본 사항: 호스팅 Consumption를 선택합니다.
    스토리지: 스토리지 계정 이 필드는 변경하지 마십시오. 함수 이벤트를 돕기 위해 새 Azure Storage 계정이 만들어집니다.
    네트워킹 아무것도 변경하지 마십시오.
    모니터링: Application Insights: Application Insights 사용 Yes를 선택합니다. 제공된 기본 이름을 변경하지 마세요.
    배포: GitHub Actions 설정: 지속적인 배포 Enable를 선택합니다.
    배포: GitHub 계정 GitHub 계정을 선택합니다.
    배포: 조직 샘플 리포지토리를 포크할 때 사용한 GitHub 계정을 선택합니다.
    배포: 리포지토리 포크된 리포지토리 이름을 azure-typescript-e2e-apps선택합니다.
    배포: 분기 main를 선택합니다.
    태그 아무것도 변경하지 마십시오.
    검토 + 만들기 Create를 선택합니다.

    이 단계에서는 포크된 리포지토리에 GitHub yaml 워크플로 파일을 추가합니다.

  3. 리소스를 만들 때 단추를 선택합니다 Go to resource .

  4. 설정 선택 - 구성은 이름 AzureWebJobsFeatureFlags 및 값을 사용하여 Azure Function Node.js v4 런타임에 대한 구성 설정을 추가합니다EnableWorkerIndexing.>

  5. 저장을 선택하여 설정을 저장합니다.

  6. bash 터미널에서 git을 사용하여 GitHub 포크된 리포지토리에서 로컬 컴퓨터로 새 yaml 워크플로 파일을 끌어옵니다.

    git pull origin main
    
  7. Visual Studio Code에서 에 있는 ./.github/workflows/새 yaml 워크플로 파일을 엽니다.

  8. 사용자가 제공한 기본 워크플로 파일은 함수 소스 코드가 리포지토리의 루트에 있으며 리포지토리의 유일한 앱이라고 가정하지만 이 샘플에서는 그렇지 않습니다. 이 문제를 해결하려면 파일을 편집합니다. 편집할 줄은 다음 yaml 블록에서 강조 표시되며 아래에 설명되어 있습니다.

    # Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action
    # More GitHub Actions for Azure: https://github.com/Azure/actions
    
    # Deploy Azure Functions Node.js v4 runtime
    # with api-inmemory subdir
    
    name: Azure Function App - api-inmemory
    
    on:
      push:
        branches:
          - main
        paths:
          - 'api-inmemory/**'
      workflow_dispatch:
    
    env:
      AZURE_FUNCTIONAPP_PACKAGE_PATH: 'api-inmemory' # set this to the path to your web app project, defaults to the repository root
      NODE_VERSION: '18.x' # Azure Functions v4 runtime requires 18
      VERBOSE: true # For debugging
    
    jobs:
      build-and-deploy:
        runs-on: ubuntu-latest
        steps:
          - name: 'Checkout GitHub Action'
            uses: actions/checkout@v2
    
          - name: Setup Node ${{ env.NODE_VERSION }} Environment
            uses: actions/setup-node@v1
            with:
              node-version: ${{ env.NODE_VERSION }}
    
          - name: 'Resolve Project Dependencies Using Npm'
            shell: bash
            run: |
              pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}'
              npm install
              npm run build --if-present
              npm run test --if-present
              popd
          - name: 'Upload artifact for deployment job' # For debugging
            uses: actions/upload-artifact@v3
            with:
              name: azure-function-v4-app
              path: |
                ${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}
                !${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}/node_modules
                !${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}/dist          
          - name: 'Run Azure Functions Action'
            uses: Azure/functions-action@v1
            id: fa
            with:
              app-name: 'swa-api' # change this to your Azure Function app name
              slot-name: 'Production'
              package: ${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}
              publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_123 }}
              scm-do-build-during-deployment: false
              enable-oryx-build: false
    
    속성 변경 목적
    name 포크의 GitHub 작업 목록에서 쉽게 찾을 수 있도록 이름을 줄입니다.
    paths Azure Functions API 코드가 변경되는 경우에만 배포가 실행되도록 제한하는 경로 섹션을 추가합니다. 워크플로 파일을 편집할 때 배포를 수동으로 트리거할 수 있습니다.
    AZURE_FUNCTIONAPP_PACKAGE_PATH 소스 코드에 하위 디렉터리를 사용하는 경우 해당 하위 디렉터리 경로 및 이름이어야 합니다.
    VERBOSE 이 설정은 빌드 및 배포 프로세스를 디버깅하는 데 유용합니다.
    명명된 단계 Upload artifact for deployment job 이 단계에서는 다운로드 가능한 아티팩트를 만듭니다. 이는 Azure Function에 배포된 파일을 정확히 디버깅할 때 유용합니다.

    선택 Upload artifact for deployment job 사항입니다. Azure Functions에 배포되는 파일을 이해하고 디버그하거나 별도의 환경에서 해당 파일을 사용하는 데 사용됩니다.

  9. 파일을 저장한 다음 git을 사용하여 GitHub에 파일을 추가하고, 커밋하고, 다시 푸시합니다.

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  10. 브라우저에서 포크의 작업 영역에서 GitHub의 워크플로를 다시 실행합니다.

    Screenshot of GitHub forked repository, showing how to rerun a GitHub action.

  11. 계속하기 전에 작업이 성공적으로 완료되기를 기다립니다.

  12. 웹 브라우저에서 함수 앱의 외부 API 엔드포인트를 사용하여 앱이 성공적으로 배포되었는지 확인합니다.

    https://YOUR-FUNCTION-APP-NAME.azurewebsites.net/api/todo
    

    메모리 내 데이터에 대해 반환된 JSON 결과는 다음과 같습니다.

    {
        "1": "Say hello"
    }
    
  13. 함수의 URL을 기록해 둡다. 다음 섹션에서 필요합니다.

  14. Azure Function 앱이 클라우드에서 작동하고 있다는 것을 알고 있습니다. 이제 API를 사용하기 위해 클라우드에서 정적 웹앱을 만들어야 합니다.

6. 새 Azure Static 웹앱 만들기

이 만들기 프로세스는 동일한 분기된 GitHub 샘플 리포지토리를 Azure에 배포합니다. 프런트 엔드 앱만 사용하도록 배포를 구성합니다.

  1. Azure Portal을 열고 Azure 계정인 Azure Portal로 로그인합니다.

  2. 다음 정보를 사용하여 만들기 단계를 완료합니다.

    프롬프트 설정
    구독 사용할 구독을 선택합니다.
    리소스 그룹 리소스 그룹에 대한 새 리소스를 선택하고 Create new 입력합니다(예: first-static-web-app.). 이름은 앱의 공용 URL에서 사용되지 않습니다. 리소스 그룹을 사용하면 단일 프로젝트에 사용되는 리소스를 그룹화할 수 있습니다.
    호스팅 계획 유형 Free 선택
    Azure Functions 및 준비 정보 기본값을 변경하지 마세요. 정적 웹앱 내에서 함수 API를 배포하지 않습니다.
    배포 세부 정보 - 원본 GitHub 선택
    배포 세부 정보 - GitHub 필요한 경우 GitHub에 로그인합니다.
    배포 세부 정보 - 조직 GitHub 계정을 선택합니다.
    배포 세부 정보 - 리포지토리 이름이 azure-typescript-e2e-apps포크된 리포지토리를 선택합니다.
    배포 세부 정보 - 분기 분기를 main 선택합니다.
    빌드 세부 정보 - 빌드 프레젠테이션 Custom를 선택합니다.
    빌드 세부 정보 - 앱 위치 /app-react-vite를 입력합니다.
    빌드 세부 정보 - API 위치 비워 둡니다.
    빌드 세부 정보 - 출력 위치 프런트 엔드 출력 디렉터리의 위치를 입력합니다 dist.
  3. 검토 + 생성를 선택한 다음, 생성를 선택합니다.

  4. 리소스를 만들 때 단추를 선택합니다 Go to resource .

  5. 개요 페이지에서 정적 웹앱의 URL을 기록해 둡다. Azure Function의 CORS 설정을 설정할 때 다음 섹션에서 필요합니다.

  6. 만들기 프로세스는 포크된 GitHub 리포지토리에 GitHub yaml 워크플로 파일을 만듭니다. 다음 명령을 사용하여 변경 내용 아래로 끌어오기:

    git pull origin main
    
  7. 발견된 ./.github/workflows/azure-static-web-apps-*.yml GitHub 작업은 프런트 엔드 앱을 빌드하고 배포하는 작업을 담당합니다. 파일을 편집하여 클라우드 기반 백 엔드 API URL에 대한 환경 변수를 추가합니다. 편집할 줄은 다음 yaml 블록에서 강조 표시되고 yaml 블록 아래에 설명되어 있습니다.

    name: Azure Static Web Apps CI/CD
    
    on:
      push:
        branches:
          - main
        paths:
          - 'app-react-vite/**'
      pull_request:
        types: [opened, synchronize, reopened, closed]
        branches:
          - main
        paths:
          - 'app-react-vite/**'      
      workflow_dispatch:
    
    jobs:
      build_and_deploy_job:
        if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.action != 'closed')
        runs-on: ubuntu-latest
        name: Build and Deploy Job
        steps:
          - uses: actions/checkout@v2
            with:
              submodules: true
          - name: Build And Deploy
            id: builddeploy
            uses: Azure/static-web-apps-deploy@v1
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ORANGE_DUNE_123 }}
              repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
              action: "upload"
              ###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
              # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
              app_location: "/app-react-vite" # App source code path
              api_location: "" # Api source code path - optional
              output_location: "dist" # Built app content directory - optional
              ###### End of Repository/Build Configurations ######
            env: 
              VITE_BACKEND_URI: https://swa-api-123.azurewebsites.net
              VITE_CLOUD_ENV: production
    
      close_pull_request_job:
        if: github.event_name == 'pull_request' && github.event.action == 'closed'
        runs-on: ubuntu-latest
        name: Close Pull Request Job
        steps:
          - name: Close Pull Request
            id: closepullrequest
            uses: Azure/static-web-apps-deploy@v1
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ORANGE_DUNE_123 }}
              action: "close"
    
    속성 변경 목적
    paths Azure Functions API 코드가 변경되는 경우에만 배포가 실행되도록 제한하는 경로 섹션을 추가합니다. 워크플로 파일을 편집할 때 배포를 수동으로 트리거할 수 있습니다.
    workflow_dispatch 배포 프로세스를 학습하고 Vite 빌드의 문제를 디버깅하는 동안에만 추가workflow_dispatch합니다. 이 문서 이후에도 이 소스 코드를 계속 진행하면 이 줄을 제거합니다.
    if ... || github.event_name == 'workflow_dispatch' workflow_dispatch 배포 프로세스를 학습하고 Vite 빌드에서 문제를 디버깅하는 동안에만 빌드를 생성하도록 허용된 이벤트를 포함합니다.
    env Vite를 사용하여 정적 빌드에 Azure Function API의 URL을 포함하는 데 필요한 환경 변수를 추가합니다. VITE_BACKEND_URL Azure Function 앱의 URL입니다. VITE_CLOUD_ENV VITE_BACKEND_URL URL을 사용하는 시기를 나타내는 매개 변수입니다. 의도하지 않은 측면 영향이 있으므로 이 샘플에 NODE_ENV 사용하지 마세요.
  8. 파일을 저장한 다음 git을 사용하여 GitHub에 파일을 추가하고, 커밋하고, 다시 푸시합니다.

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  9. 브라우저에서 정적 웹앱에 대한 포크의 작업 영역에서 GitHub의 워크플로를 다시 실행합니다.

  10. 프런트 엔드 앱이 Azure에 배포됩니다. 이제 정적 웹앱의 CORS 요청을 허용하도록 Azure Function 앱을 구성해야 합니다.

7. Azure Function 앱에 대한 CORS 구성

관리되는 함수 앱 대신 별도의 Azure Function 앱을 사용하는 경우 정적 웹앱의 요청을 허용하도록 CORS를 구성해야 합니다.

  1. Azure Portal에서 Azure Function 앱을 엽니다.
  2. API -> CORS 섹션에서 정적 웹앱의 URL을 허용된 원본 목록에 추가합니다.

8. 정적 웹앱 테스트

  1. 브라우저에서 정적 웹앱을 엽니다.
  2. 앱과 상호 작용하여 로그인하고, 공용 및 개인 정보를 보고, 다시 로그아웃합니다.

9. 이 문서 시리즈에서 사용되는 모든 리소스 정리

이 문서 시리즈에서 만든 모든 리소스를 정리합니다.

  1. Azure Portal에서 정적 웹앱 및 함수 앱을 삭제하는 리소스 그룹을 삭제합니다.
  2. GitHub 포털에서 포크된 리포지토리를 삭제합니다.

문제 해결

이 샘플에서는 알려진 문제 및 해결 방법 목록을 유지합니다. 문제가 나열되지 않으면 문제를 열어 주세요.

정적 웹앱 및 함수 앱 공용 URL

Azure Portal의 각 리소스 개요 페이지에서 항상 정적 웹앱의 URL과 함수 앱의 URL을 찾을 수 있습니다. 이러한 URL은 기본적으로 공용입니다.

다음 단계