Blazor 앱 배포와 호스팅 — Azure·IIS·Docker 완전 가이드

배포와 호스팅
📚 핵심 정리

배포와 호스팅

Blazor 앱을 Azure, IIS, Docker에 배포하는 방법과 배포 환경 설정을 학습합니다.
Blazor 앱 배포와 호스팅 완전 가이드
Azure App Service · IIS · Docker를 활용한 실무 배포 전략 완전 정복

📌 학습 목표

  • Blazor WebAssembly와 Blazor Server의 배포 방식 차이를 명확하게 설명할 수 있습니다.
  • Azure App Service에 Blazor 앱을 배포하고 환경 변수를 설정할 수 있습니다.
  • IIS에 Blazor 앱을 호스팅하고 필요한 설정(.NET 호스팅 번들, MIME 타입 등)을 적용할 수 있습니다.
  • Dockerfile 멀티 스테이지 빌드를 작성하고 Docker로 Blazor 앱을 컨테이너화할 수 있습니다.
  • 환경별 appsettings.json을 분리하여 개발·운영 환경을 안전하게 관리할 수 있습니다.
구분Blazor WebAssemblyBlazor Server
실행 위치브라우저 (클라이언트)서버 (SignalR 연결)
배포 형태정적 파일 (.html/.js/.wasm)ASP.NET Core 앱
Azure 배포Static Web Apps / App ServiceApp Service
IIS 배포정적 사이트 또는 역방향 프록시역방향 프록시 필수
DockerNginx + 정적 파일ASP.NET Core 런타임 이미지
서버 부하낮음 (클라이언트에서 처리)높음 (서버에서 UI 처리)

📝 개념 설명

1. 배포 전 준비 — dotnet publish

Blazor 앱을 어느 환경에 배포하든 공통적으로 dotnet publish 명령을 먼저 실행합니다. 이 명령은 소스 코드를 릴리스 모드로 컴파일하고, 의존 파일·정적 파일을 하나의 폴더에 모아 배포 패키지를 생성합니다.

# 릴리스 모드로 발행 (가장 기본적인 형태)
dotnet publish -c Release -o ./publish

# Self-contained 배포 — .NET 런타임을 함께 패키징 (서버에 .NET 불필요)
dotnet publish -c Release -o ./publish --self-contained true -r win-x64

# Framework-dependent 배포 — 서버에 .NET 런타임이 별도 설치되어야 함
dotnet publish -c Release -o ./publish --self-contained false

발행이 완료된 ./publish 폴더에는 배포에 필요한 모든 파일이 들어 있습니다. 이 폴더가 실제로 서버에 올라가는 배포 단위입니다.

2. 환경별 설정 분리 — appsettings.json

.NET 앱은 ASPNETCORE_ENVIRONMENT 환경 변수 값에 따라 설정 파일을 자동으로 계층화하여 로드합니다. 기본 appsettings.json 위에 환경별 파일의 값이 덮어씌워지는 방식입니다.

// appsettings.json — 모든 환경 공통 기본값
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

// appsettings.Production.json — 운영 환경 전용 (기본값 덮어씌움)
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=prod-db;Database=MyApp;Integrated Security=True"
  },
  "AllowedHosts": "mydomain.com;www.mydomain.com"
}

// appsettings.Development.json — 개발 환경 전용
{
  "DetailedErrors": true,
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyAppDev"
  }
}
  • Development — 로컬 개발 환경. 오류 상세 정보 표시 활성화
  • Staging — QA·스테이징 환경. 운영과 유사하되 테스트 가능
  • Production — 운영 환경. ASPNETCORE_ENVIRONMENT 미설정 시 기본값
🔒 비밀 정보는 설정 파일에 하드코딩 금지
연결 문자열, API 키, 비밀번호 등 민감한 값을 appsettings.json에 직접 넣으면 Git 리포지토리를 통해 유출될 수 있습니다. 개발 환경에서는 dotnet user-secrets를, 운영 환경에서는 Azure Key Vault 또는 환경 변수(Environment Variables)를 활용하세요.

3. 설정 우선순위 이해

.NET 설정 계층은 낮은 곳에서 높은 곳으로 덮어씌워집니다. 우선순위가 높을수록 나중에 로드되어 이전 값을 재정의합니다.

 

 

⚙️ .NET 설정 우선순위 (낮음 → 높음)

 

appsettings
.json
(최저)
appsettings
.{환경명}
.json
user-secrets
(개발 전용)
환경 변수
(Environment
Variables)
명령줄 인수
(최우선)

💡 예제 & 실습

실습 1 — Azure App Service 배포

Azure App Service는 서버 관리 없이 Blazor 앱을 클라우드에 호스팅할 수 있는 PaaS(Platform as a Service) 서비스입니다. Blazor Server와 Blazor WebAssembly(Hosted) 모두 지원합니다.

# 1. Azure 로그인
az login

# 2. 리소스 그룹 생성
az group create --name MyBlazorRG --location koreacentral

# 3. App Service 플랜 생성 (Free 티어)
az appservice plan create --name MyBlazorPlan --resource-group MyBlazorRG --sku FREE

# 4. Web App 생성 (.NET 8 런타임)
az webapp create --name my-blazor-app --resource-group MyBlazorRG --plan MyBlazorPlan --runtime "DOTNETCORE:8.0"

# 5. 환경 변수 설정
az webapp config appsettings set --name my-blazor-app --resource-group MyBlazorRG --settings ASPNETCORE_ENVIRONMENT=Production

# 6. 앱 발행 후 ZIP 배포 (PowerShell)
dotnet publish -c Release -o ./publish
Compress-Archive -Path ./publish/* -DestinationPath myapp.zip -Force
az webapp deploy --name my-blazor-app --resource-group MyBlazorRG --src-path myapp.zip

배포 후 Azure 포털에서 App Service → 구성(Configuration) → 애플리케이션 설정에서 환경 변수를 추가하거나 수정할 수 있습니다. 이 값들은 appsettings.json보다 우선순위가 높아 코드 수정 없이 설정을 변경할 수 있습니다.

💡 Blazor WebAssembly 전용 — Azure Static Web Apps
Blazor WebAssembly는 정적 파일만으로 실행되므로 Azure Static Web Apps를 사용하면 더 저렴하고 빠릅니다. GitHub 리포지토리와 자동 연동되어 main 브랜치에 Push 시 자동 빌드·배포(CI/CD)가 구성됩니다. Free 티어에서도 HTTPS, 커스텀 도메인, CDN 가속이 제공됩니다.

실습 2 — IIS(인터넷 정보 서비스) 배포

사내 Windows 서버나 온프레미스 환경에 배포할 때 IIS를 사용합니다. IIS에서 .NET 앱을 실행하려면 반드시 .NET 호스팅 번들(Hosting Bundle)을 먼저 설치해야 합니다. 이 번들에는 ASP.NET Core 모듈(ANCM)이 포함되어 있습니다.

IIS 배포 단계:
  1. .NET 호스팅 번들 설치 — Microsoft 공식 다운로드 센터에서 설치 후 IIS를 재시작합니다.
  2. IIS에서 새 사이트 추가 — IIS 관리자 → 사이트 → 웹 사이트 추가. 실제 경로를 발행 폴더(./publish)로 지정합니다.
  3. 애플리케이션 풀 설정 — .NET CLR 버전을 반드시 “관리 코드 없음(No Managed Code)”으로 설정합니다.
  4. 폴더 권한 부여 — IIS_IUSRS 계정에 발행 폴더의 읽기·실행 권한을 부여합니다.
  5. 바인딩 및 HTTPS 구성 — SSL 인증서를 바인딩하여 HTTPS를 활성화합니다.

dotnet publish 시 자동으로 생성되는 web.config 파일이 IIS와 ASP.NET Core 모듈 간의 연동을 담당합니다:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <location path="." inheritInChildApplications="false">
    <system.webServer>
      <handlers>
        <add name="aspNetCore" path="*" verb="*"
             modules="AspNetCoreModuleV2"
             resourceType="Unspecified" />
      </handlers>
      <aspNetCore processPath="dotnet"
                  arguments="./MyBlazorApp.dll"
                  stdoutLogEnabled="false"
                  stdoutLogFile="./logs/stdout"
                  hostingModel="inprocess">
        <environmentVariables>
          <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
        </environmentVariables>
      </aspNetCore>

      <!-- Blazor WebAssembly 전용: .wasm MIME 타입 등록 (미등록 시 404 오류) -->
      <staticContent>
        <mimeMap fileExtension=".wasm" mimeType="application/wasm" />
      </staticContent>
    </system.webServer>
  </location>
</configuration>

실습 3 — Docker 컨테이너 배포

Docker는 애플리케이션과 모든 의존성을 컨테이너에 패키징하여 어느 환경에서나 동일하게 실행할 수 있게 합니다. 멀티 스테이지 빌드(Multi-stage Build)를 사용하면 최종 이미지에 빌드 도구(SDK)가 포함되지 않아 이미지 크기를 크게 줄일 수 있습니다.

Blazor Server용 Dockerfile (멀티 스테이지 빌드):
# ── Stage 1: SDK 이미지로 빌드·발행 ──────────────────────
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# 프로젝트 파일 먼저 복사 → 의존성 복원 (Docker 레이어 캐시 활용)
COPY ["MyBlazorApp/MyBlazorApp.csproj", "MyBlazorApp/"]
RUN dotnet restore "MyBlazorApp/MyBlazorApp.csproj"

# 전체 소스 복사 → 릴리스 발행
COPY . .
WORKDIR "/src/MyBlazorApp"
RUN dotnet publish -c Release -o /app/publish

# ── Stage 2: 런타임 이미지 (SDK 제외 → 이미지 경량화) ────
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
WORKDIR /app
COPY --from=build /app/publish .

# .NET 8 기본 HTTP 포트 = 8080
ENV ASPNETCORE_ENVIRONMENT=Production
ENV ASPNETCORE_URLS=http://+:8080
EXPOSE 8080

ENTRYPOINT ["dotnet", "MyBlazorApp.dll"]
Blazor WebAssembly용 Dockerfile (Nginx 정적 서버):
# Stage 1: WebAssembly 발행
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app/publish

# Stage 2: Nginx로 정적 파일 서빙 (SDK 완전 제외)
FROM nginx:alpine AS final
COPY --from=build /app/publish/wwwroot /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
nginx.conf — Blazor WebAssembly SPA 라우팅 폴백 설정:
events {}
http {
  include mime.types;
  types {
    application/wasm wasm;  # .wasm MIME 타입 등록
  }

  server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html;

    # SPA 라우팅: 존재하지 않는 경로는 index.html로 폴백
    location / {
      try_files $uri $uri/ /index.html;
    }

    # gzip 압축으로 전송 크기 최소화
    gzip on;
    gzip_types text/plain application/javascript application/wasm;
  }
}
Docker 명령어 및 docker-compose.yml:
# 이미지 빌드
docker build -t my-blazor-app:latest .

# 단독 컨테이너 실행
docker run -d -p 8080:8080 -e ASPNETCORE_ENVIRONMENT=Production --name blazor-app my-blazor-app:latest

# 로그 확인
docker logs blazor-app

# Compose로 실행
docker-compose up -d
# docker-compose.yml — 앱 + SQL Server 통합 구성
services:
  webapp:
    build: .
    ports:
      - 8080:8080
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ConnectionStrings__DefaultConnection=Server=db;Database=MyApp;User Id=sa;Password=Pass@word1!
    depends_on:
      - db

  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=Pass@word1!
    ports:
      - 1433:1433
    volumes:
      - sqldata:/var/lib/mssql/data

volumes:
  sqldata:
💡 연결 문자열 환경 변수 주입 규칙
docker-compose.yml에서 중첩된 appsettings.json 경로는 콜론(:) 대신 이중 밑줄(__)로 구분합니다.
예: ConnectionStrings:DefaultConnection → ConnectionStrings__DefaultConnection

실습 4 — GitHub Actions CI/CD 파이프라인

CI/CD 파이프라인을 구성하면 코드를 Push할 때마다 자동으로 빌드하고 배포합니다. 수동 배포 실수를 줄이고 배포 속도를 높일 수 있습니다.

# .github/workflows/deploy.yml
name: Deploy Blazor to Azure

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Setup .NET 8
      uses: actions/setup-dotnet@v3
      with:
        dotnet-version: '8.0.x'

    - name: Restore
      run: dotnet restore

    - name: Build
      run: dotnet build -c Release --no-restore

    - name: Publish
      run: dotnet publish -c Release -o ./publish --no-build

    - name: Deploy to Azure App Service
      uses: azure/webapps-deploy@v2
      with:
        app-name: 'my-blazor-app'
        publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
        package: ./publish

Azure 포털의 App Service → 배포 센터 → 게시 프로필 다운로드에서 가져온 XML을 GitHub 리포지토리 Settings → Secrets에 AZURE_WEBAPP_PUBLISH_PROFILE로 등록하면 자동 배포가 완성됩니다.

⚠️ 자주 틀리는 것 / 주의사항

 

 

⚠️ 배포 시 자주 발생하는 문제와 해결책

 

🔴
.wasm MIME 타입 누락
IIS에서 .wasm 파일 미등록 시 404 오류 발생. web.config에 application/wasm MIME 타입 추가 필수
🔴
딥링크 직접 접근 404
Blazor WebAssembly SPA 라우팅 미설정 시 /products/1 같은 URL 직접 접근 시 404. index.html 폴백 필수
🔴
IIS 앱 풀 CLR 설정 오류
CLR 버전을 v4.0으로 두면 502 Bad Gateway 발생. 반드시 “관리 코드 없음(No Managed Code)”으로 설정
🟡
Blazor Server SignalR 차단
역방향 프록시(Nginx·IIS·Azure Front Door)에서 WebSocket 업그레이드가 차단되면 앱이 전혀 동작하지 않음
  • .NET 8 기본 포트 변경: .NET 8부터 기본 HTTP 포트가 80에서 8080으로 변경되었습니다. Dockerfile이나 docker-compose.yml에서 ASPNETCORE_URLS 환경 변수로 포트를 명시적으로 지정하세요.
  • 멀티 스테이지 빌드 생략 금지: SDK 이미지(약 900MB)와 aspnet 런타임 이미지(약 250MB)를 분리하지 않으면 최종 Docker 이미지가 1GB가 넘어 배포·Pull 속도가 크게 저하됩니다.
  • Azure Free 티어의 Always On 미지원: App Service Free·Shared 티어는 일정 시간 비활성화 후 앱이 중지됩니다. Blazor Server처럼 지속적인 SignalR 연결이 필요한 앱은 Basic 이상 티어에서 Always On을 활성화해야 합니다.
  • Self-contained 배포 주의: Self-contained 배포는 서버에 .NET 런타임이 없어도 실행되지만 배포 파일 크기가 수십 MB 이상으로 커집니다. 서버 환경을 제어할 수 있다면 Framework-dependent 배포가 더 효율적입니다.
  • HTTPS 강제 리다이렉트: 운영 환경에서는 Program.cs에 app.UseHttpsRedirection();을 반드시 포함하고, 인증서 구성을 완료해야 합니다.

🎯 마무리

Blazor 앱 배포는 호스팅 모델 선택(WebAssembly vs Server)에서 전략이 갈립니다. WebAssembly는 정적 파일로 배포되어 CDN과 정적 호스팅의 장점을 최대한 활용할 수 있고, Server는 기존 ASP.NET Core 앱과 동일한 방식으로 배포합니다.

 

프로젝트 상황별 권장 배포 전략:

  1. 개인·소규모 프로젝트 → Azure App Service Free 티어로 빠르게 시작
  2. 팀 개발·지속 배포 → GitHub Actions + Azure로 CI/CD 자동화
  3. 사내 서버·온프레미스 → IIS + .NET 호스팅 번들로 기존 인프라 활용
  4. 마이크로서비스·클라우드 네이티브 → Docker + Kubernetes로 확장성 확보
✅ 핵심 정리
  • dotnet publish -c Release로 배포 패키지를 생성합니다. Self-contained는 런타임 포함(서버에 .NET 불필요), Framework-dependent는 서버에 .NET 런타임이 필요합니다.
  • 환경별 설정은 appsettings.{환경명}.json으로 분리하고 ASPNETCORE_ENVIRONMENT 환경 변수로 활성 환경을 지정합니다. 설정 우선순위는 환경 변수 > 환경별 json > 기본 json 순입니다.
  • Azure App Service는 Azure CLI 또는 ZIP 배포로 간단히 배포하며, 포털의 구성(Configuration) 탭에서 환경 변수를 관리합니다. Blazor WebAssembly는 Azure Static Web Apps가 더 경제적입니다.
  • IIS 배포는 ① .NET 호스팅 번들 설치 → ② 애플리케이션 풀을 “관리 코드 없음” 설정 → ③ 폴더 권한 부여 순서로 진행합니다. Blazor WebAssembly는 web.config에 .wasm MIME 타입 등록이 필수입니다.
  • Docker 배포는 SDK 이미지(빌드) → aspnet 런타임 이미지(실행) 멀티 스테이지 빌드를 사용합니다. Blazor WebAssembly는 Nginx 이미지로 서빙하며 SPA 라우팅 폴백(try_files)을 nginx.conf에 설정해야 합니다.
  • Blazor Server는 SignalR WebSocket을 사용하므로 모든 역방향 프록시에서 WebSocket 업그레이드 헤더를 허용해야 앱이 정상 작동합니다.
  • GitHub Actions CI/CD를 구성하면 main 브랜치 Push 시 자동 빌드·발행·배포 파이프라인이 실행되어 수동 배포 오류를 없앨 수 있습니다.

댓글 남기기

Wordpress Social Share Plugin powered by Ultimatelysocial
Copy link
URL has been copied successfully!
THREADS
RSS
error: 저작권 콘텐츠보호를 부탁드립니다.