자습서: 고객의 애플리케이션에 Power BI 보고서 포함

이 자습서에서는 고객에 대한 콘텐츠 포함(앱 소유 데이터라고도 함) 솔루션의 일부로 .NET 5.0 애플리케이션에 Power BI 보고서를 포함하는 방법을 알아봅니다. 고객에 대한 콘텐츠 포함 솔루션에서 앱 사용자는 Power BI에 로그인하거나 Power BI 라이선스를 가질 필요가 없습니다.

이 자습서에서는 다음과 같은 포함 방법을 알아봅니다.

  • Power BI 보고서.
  • 고객에 대한 콘텐츠 포함 앱에서.
  • 서비스 주체를 사용하여.
  • .NET 5.0을 사용하여.
  • Microsoft.Identity.Web 라이브러리(이 라이브러리는 .NET Core에서도 지원됨)를 사용하여.

참고 항목

이 자습서에서 사용되는 전체 솔루션은 DOTNET5-AppOwnsData-Tutorial GitHub 리포지토리에서 확인할 수 있습니다.

필수 조건

리소스

이 자습서에서는 다음을 사용합니다.

메서드

고객에 대한 콘텐츠 포함 솔루션에 Power BI 콘텐츠를 포함하려면 다음 단계를 수행합니다.

  1. Microsoft Entra 앱 및 서비스 주체를 구성합니다.

  2. 포함하는 매개 변수 값을 가져옵니다.

  3. 필요한 NuGet 패키지를 추가합니다.

  4. 서버 쪽 인증을 사용하도록 설정

  5. 앱의 클라이언트 쪽 빌드

  6. 애플리케이션을 실행합니다.

1단계 - Microsoft Entra 앱 및 서비스 주체 구성

이 자습서에서는 서비스 주체를 사용하여 Microsoft Entra ID에 대해 웹앱을 인증합니다. Microsoft Entra 토큰을 생성할 수 있는 Microsoft Entra 앱도 필요합니다. 웹앱은 Microsoft Entra 토큰을 사용하여 Power BI REST API를 호출하고 보고서, 대시보드 및 타일과 같은 Power BI 항목을 포함할 수 있습니다.

서비스 주체 지침따라 Microsoft Entra 앱을 만들고 앱의 서비스 주체가 Power BI 콘텐츠를 사용할 수 있도록 합니다.

2단계 - 포함하는 매개 변수 값 가져오기

보고서를 포함하려면 다음 값이 필요합니다.

도메인 및 테넌트 ID

할 일기본 또는 테넌트 ID를 모르는 경우 Microsoft Entra 테넌트 ID 및 기본 do기본 이름 찾기를 참조하세요.

참고 항목

다른 테넌트의 사용자에 대한 콘텐츠를 포함하려면(게스트 사용자) authorityUri 매개 변수를 조정해야 합니다.

클라이언트 ID

클라이언트 ID GUID(‘애플리케이션 ID’라고도 함)를 가져오려면 다음 단계를 수행합니다.

  1. Microsoft Azure에 로그인합니다.

  2. 앱 등록을 검색하고 앱 등록 링크를 선택합니다.

  3. Power BI 콘텐츠를 포함하는 데 사용하는 Microsoft Entra 앱을 선택합니다.

  4. 개요 섹션에서 애플리케이션(클라이언트) ID GUID를 복사합니다.

클라이언트 암호

클라이언트 암호를 가져오려면 다음 단계를 수행합니다.

  1. Microsoft Azure에 로그인합니다.

  2. 앱 등록을 검색하고 앱 등록 링크를 선택합니다.

  3. Power BI 콘텐츠를 포함하는 데 사용하는 Microsoft Entra 앱을 선택합니다.

  4. 관리에서 인증서 및 비밀을 선택합니다.

  5. 클라이언트 암호 아래에서 새 클라이언트 암호를 선택합니다.

  6. 클라이언트 암호 추가 팝업 창에서 애플리케이션 암호에 대한 설명을 제공하고 애플리케이션 암호가 만료되는 경우를 선택하고 추가를 선택합니다.

  7. 클라이언트 암호 섹션에서 새로 만든 애플리케이션 암호의 열에 문자열을 복사합니다. 클라이언트 암호 값은 ‘클라이언트 ID’입니다.

참고 항목

처음 표시될 때 클라이언트 암호 값을 복사해야 합니다. 이 페이지를 벗어나면 클라이언트 암호가 숨겨지고 해당 값을 검색할 수 없습니다.

작업 영역 ID

작업 영역 ID GUID를 가져오려면 다음 단계를 수행합니다.

  1. Power BI 서비스에 로그인.

  2. 포함하려는 보고서를 엽니다.

  3. URL에서 GUID를 복사합니다. GUID는 /groups//reports/ 사이의 숫자입니다.

    A screenshot showing workspace ID GUID in the Power B I service U R L

참고 항목

작업 영역 ID를 프로그래밍 방식으로 가져오려면 그룹 가져오기 API를 사용합니다.

보고서 ID

보고서 ID GUID를 가져오려면 다음 단계를 수행합니다.

  1. Power BI 서비스에 로그인.

  2. 포함하려는 보고서를 엽니다.

  3. URL에서 GUID를 복사합니다. GUID는 /reports//ReportSection 사이의 숫자입니다.

    A screenshot showing report ID GUID in the Power B I service U R L

참고 항목

보고서 ID를 프로그래밍 방식으로 가져오려면 그룹에서 보고서 가져오기 API를 사용합니다.

3 단계 - 필요한 NuGet 패키지 추가

시작하기 전에 Microsoft.Identity.WebMicrosoft.PowerBI.Api NuGet 패키지를 앱에 추가해야 합니다.

다음과 같이 필요한 NuGet 패키지를 앱에 추가합니다.

  • VS Code에서 터미널을 열고 다음 코드를 입력합니다.

  • Visual Studio에서 도구>NuGet 패키지 관리자>패키지 관리자 콘솔로 이동하고 다음 코드를 입력합니다.

dotnet add package Microsoft.Identity.Web
dotnet add package Microsoft.Identity.Web.UI
dotnet add package Microsoft.PowerBI.Api

4 단계 - 서버 쪽 인증을 사용하도록 설정

다음 테이블에서 파일을 만들거나 수정하여 앱에서 서버 쪽 인증을 사용하도록 설정합니다.

파일 사용
Startup.cs Microsoft.Identity.Web 인증 서비스 초기화
appsettings.json 인증 세부 정보 구성
PowerBiServiceApi.cs Microsoft Entra 토큰 가져오기 및 메타데이터 포함
HomeController.cs 포함하는 데이터를 보기에 모델로 전달

Microsoft.Identity.Web을 지원하도록 시작 파일 구성

Startup.cs의 코드를 수정하여 Microsoft.Identity.Web에서 제공하는 인증 서비스를 올바르게 초기화합니다.

다음 코드 조각을 앱의 Startup.cs 파일에 추가합니다.

참고 항목

ConfigureServices의 코드는 다음과 같은 여러 중요한 작업을 수행합니다.

  1. 액세스 토큰(Microsoft Entra 토큰)을 획득하도록 Microsoft 인증 라이브러리를 구성하는 호출 AddMicrosoftWebAppCallsWebApi 입니다.
  2. Microsoft 인증 라이브러리가 액세스 토큰을 AddInMemoryTokenCaches 캐시하고 백그라운드에서 토큰을 새로 고치는 데 사용하는 토큰 캐시를 구성하는 호출입니다.
  3. services.AddScoped(typeof(PowerBiServiceApi))를 호출하면 종속성 삽입을 사용하여 PowerBiServiceApi 클래스를 다른 클래스에 추가할 수 있는 서비스 클래스로 구성합니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using AppOwnsData.Services;

namespace AppOwnsData
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services) {

    services.AddMicrosoftIdentityWebAppAuthentication(Configuration)
            .EnableTokenAcquisitionToCallDownstreamApi()
            .AddInMemoryTokenCaches();

            services.AddScoped(typeof(PowerBiServiceApi));

            services.AddControllersWithViews(options => {
                var policy = new AuthorizationPolicyBuilder()
                    .RequireAuthenticatedUser()
                    .Build();
                options.Filters.Add(new AuthorizeFilter(policy));
            });
            services.AddRazorPages()
                    .AddMicrosoftIdentityUI();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You might want to change this for production scenarios. See https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapRazorPages();
            });
        }
    }
}

인증 세부 정보 파일 만들기

이 자습서에서 appsettings.json 파일에는 클라이언트 ID, 클라이언트 암호 등의 중요한 정보가 포함됩니다. 보안상의 이유로 설정 파일에 이 정보를 보관하지 않는 것이 좋습니다. 애플리케이션에 포함할 때는 Azure Key Vault와 같은 더 안전한 도구로 이 정보를 보관해야 합니다.

  1. 프로젝트에서 새 파일을 만들고 이름을 appsettings.json으로 지정합니다.

  2. 다음 코드를 appsettings.json에 추가합니다.

    {
     "AzureAd": {
       "Instance": "https://login.microsoftonline.com/",
       "Domain": "yourtenant.onMicrosoft.com",
       "TenantId": "",
       "ClientId": "",
       "ClientSecret": "",
       "CallbackPath": "/signin-oidc",
       "SignedOutCallbackPath": "/signout-callback-oidc"
     },
     "PowerBi": {
       "ServiceRootUrl": "https://api.powerbi.com/"
     },
     "Logging": {
       "LogLevel": {
         "Default": "Information",
         "Microsoft": "Warning",
         "Microsoft.Hosting.Lifetime": "Information"
       }
     },
    "AllowedHosts": "*"
    }
    
  3. 2단계 - 포함하는 매개 변수 값 가져오기에서 가져온 포함하는 매개 변수 값을 입력합니다.

참고 항목

위의 코드에서 PowerBi:ServiceRootUrl 매개 변수는 Power BI 서비스의 기준 URL을 추적하는 사용자 지정 구성 값으로 추가됩니다. Microsoft 퍼블릭 클라우드에서 Power BI 서비스를 프로그래밍하는 경우 URL은 https://api.powerbi.com/입니다. 그러나 정부 클라우드와 같은 다른 클라우드에서는 Power BI 서비스의 루트 URL이 다릅니다. 따라서 사용자 지정 구성 값은 프로젝트 구성 값으로 저장되므로 필요에 따라 변경할 수 있습니다.

Microsoft Entra 액세스 토큰을 가져오고 Power BI 서비스

보고서 및 대시보드와 같은 Power BI 콘텐츠를 포함하려면 앱이 Microsoft Entra 토큰가져와야 합니다. 토큰을 가져오려면 구성 개체가 필요합니다.

이 섹션의 코드에서는 .NET Core 종속성 삽입 패턴을 사용합니다. 클래스에서 서비스를 사용해야 하는 경우, 해당 서비스에 생성자 매개 변수를 추가할 수 있습니다. .NET Core 런타임은 런타임에 서비스 인스턴스 전달을 처리합니다. 이 경우 생성자는 appsettings.json에서 PowerBi:ServiceRootUrl 구성 값을 검색하는 데 사용되는 IConfiguration 매개 변수를 사용하여 .NET Core 구성 서비스의 인스턴스를 삽입합니다. tokenAcquisition으로 명명된 ITokenAcquisition 매개 변수는 Microsoft.Identity.Web 라이브러리에서 제공하는 Microsoft 인증 서비스에 대한 참조를 포함합니다. 매개 ITokenAcquisition 변수는 Microsoft Entra ID에서 액세스 토큰을 획득하는 데 사용됩니다.

RequiredScopes 필드는 Power BI 서비스 API에서 지원하는 위임된 권한 세트가 포함된 문자열 배열을 포함합니다. 애플리케이션이 네트워크를 통해 호출하여 Microsoft Entra 토큰을 획득하는 경우 Microsoft Entra ID가 반환하는 액세스 토큰에 포함할 수 있도록 위임된 권한 집합을 전달합니다.

참고 항목

Microsoft Entra 앱이 웹앱 에 필요한 범위로 구성되어 있는지 확인합니다. 자세한 내용은 Microsoft Entra 앱의 권한 변경을 참조 하세요.

  1. 앱의 프로젝트에서 Services라는 새 폴더를 만듭니다.

  2. Services 폴더에서 PowerBiServiceApi.cs라는 새 파일을 만듭니다.

  3. PowerBiServiceApi.cs에 다음 코드를 추가합니다.

    using System;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Identity.Web;
    using Microsoft.Rest;
    using Microsoft.PowerBI.Api;
    using Microsoft.PowerBI.Api.Models;
    using Newtonsoft.Json;
    
    namespace AppOwnsData.Services {
    
        // A view model class to pass the data needed to embed a single report
        public class EmbeddedReportViewModel {
            public string Id;
            public string Name;
            public string EmbedUrl;
            public string Token;
        }
    
        public class PowerBiServiceApi {
    
            private ITokenAcquisition tokenAcquisition { get; }
            private string urlPowerBiServiceApiRoot { get; }
    
            public PowerBiServiceApi(IConfiguration configuration, ITokenAcquisition tokenAcquisition) {
                this.urlPowerBiServiceApiRoot = configuration["PowerBi:ServiceRootUrl"];
                this.tokenAcquisition = tokenAcquisition;
            }
    
            public const string powerbiApiDefaultScope = "https://analysis.windows.net/powerbi/api/.default";
    
            // A method to get the Azure AD token (also known as 'access token')
            public string GetAccessToken() {
                return this.tokenAcquisition.GetAccessTokenForAppAsync(powerbiApiDefaultScope).Result;
            }
    
            public PowerBIClient GetPowerBiClient() {
                var tokenCredentials = new TokenCredentials(GetAccessToken(), "Bearer");
                return new PowerBIClient(new Uri(urlPowerBiServiceApiRoot), tokenCredentials);
            }
    
            public async Task<EmbeddedReportViewModel> GetReport(Guid WorkspaceId, Guid ReportId) {
    
                PowerBIClient pbiClient = GetPowerBiClient();
    
                // Call the Power BI service API to get the embedding data.
                var report = await pbiClient.Reports.GetReportInGroupAsync(WorkspaceId, ReportId);
    
                // Generate a read-only embed token for the report.
                var datasetId = report.DatasetId;
                var tokenRequest = new GenerateTokenRequest(TokenAccessLevel.View, datasetId);
                var embedTokenResponse = await pbiClient.Reports.GenerateTokenAsync(WorkspaceId, ReportId, tokenRequest);
                var embedToken = embedTokenResponse.Token;
    
                // Return the report embedded data to caller.
                return new EmbeddedReportViewModel {
                    Id = report.Id.ToString(),
                    EmbedUrl = report.EmbedUrl,
                    Name = report.Name,
                    Token = embedToken
                };
            }
    
        }
    }
    

HomeController.cs 파일 수정

이 코드 예제에서는 종속성 주입을 사용하여 HomeController.cs 파일을 수정합니다. 이전 단계에 따라 ConfigureServices 메서드에서 services.AddScoped를 호출하여 PowerBiServiceApi 클래스를 서비스로 구성했습니다. 이 코드를 사용하여 생성자에 PowerBiServiceApi 매개 변수를 추가하면 .NET Core 런타임에서 PowerBiServiceApi 인스턴스를 만들어 생성자에 전달합니다.

Controllers 폴더에서 HomeController.cs 파일을 열고 다음 코드에 추가합니다.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using AppOwnsData.Models;
using AppOwnsData.Services;

namespace AppOwnsData.Controllers
{
    [Authorize]
    public class HomeController : Controller
    {
        private PowerBiServiceApi powerBiServiceApi;

        public HomeController(PowerBiServiceApi powerBiServiceApi)
        {
            this.powerBiServiceApi = powerBiServiceApi;
        }

        [AllowAnonymous]
        public IActionResult Index()
        {
            return View();
        }

        public async Task<IActionResult> Embed() {

            // Replace these two GUIDs with the workspace ID and report ID you recorded earlier.
            Guid workspaceId = new Guid("11111111-1111-1111-1111-111111111111");
            Guid reportId = new Guid("22222222-2222-2222-2222-222222222222");

            var viewModel = await powerBiServiceApi.GetReport(workspaceId, reportId);

            return View(viewModel);
        }

        [AllowAnonymous]
        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

5단계 - 앱의 클라이언트 쪽 빌드

클라이언트 쪽 구현에서는 다음 표에 나열된 파일을 만들거나 수정해야 합니다.

파일 사용
embed.js 클라이언트 쪽 JavaScript 코드를 포함합니다.
Embed.cshtml 앱의 DOM(문서 개체 모델)과 보고서를 포함하기 위한 DIV를 포함합니다.

포함된 보고서의 컨테이너 만들기

이 자습서에서는 포함된 보고서의 컨테이너인 div 요소를 포함하는 Embed.cshtml 파일 및 세 가지 스크립트를 만듭니다.

  1. 보기/ 폴더에서 Embed.cshtml이라는 파일을 만듭니다.

  2. Embed.cshtml 파일에 다음 코드를 추가합니다.

    @model AppOwnsData.Services.EmbeddedReportViewModel;
    
    <div id="embed-container" style="height:800px;"></div>
    
    @section Scripts {
    
        <!-- powerbi.min.js is the JavaScript file that loads the client-side Power BI JavaScript API library.
        Make sure that you're working with the latest library version.
        You can check the latest library available in https://cdnjs.com/libraries/powerbi-client -->
        <script src="https://cdn.jsdelivr.net/npm/powerbi-client@2.18.0/dist/powerbi.min.js"></script>
    
        <!-- This script creates a JavaScript object named viewModel which is accessible to the JavaScript code in embed.js. -->
        <script> 
            var viewModel = {
                reportId: "@Model.Id",
                embedUrl: "@Model.EmbedUrl",
                token: "@Model.Token"
            }; 
        </script>
    
        <!-- This script specifies the location of the embed.js file -->
        <script src="~/js/embed.js"></script>
    }
    

클라이언트 쪽 JavaScript를 추가하여 보고서 포함

Power BI 콘텐츠를 포함하려면 구성 개체를 만들어야 합니다. 구성 개체를 만드는 방법을 자세히 알아보려면 Embed a report(보고서 포함)를 참조하세요.

이 자습서에서는 models 변수를 사용하는 보고서를 포함하기 위한 구성 개체가 포함된 embed.js라는 JavaScript 파일을 만듭니다.

window['powerbi-client'].models 호출을 사용하여 models을 초기화할 수 있습니다. models 변수는 models.Permissions.All, models.TokenType.Aad, models.ViewMode.View 등의 구성 값을 설정하는 데 사용됩니다.

powerbi.embed 함수는 models 구성 개체를 사용하여 보고서를 포함합니다.

  1. wwwroot/js 폴더에 embed.js라는 파일을 만듭니다.

  2. embed.js 파일에 다음 코드를 추가합니다.

    $(function () {
    
        // 1 - Get DOM object for the div that's the report container.
        var reportContainer = document.getElementById("embed-container");
    
        // 2 - Get the report embedding data from the view model.
        var reportId = window.viewModel.reportId;
        var embedUrl = window.viewModel.embedUrl;
        var token = window.viewModel.token
    
        // 3 - Embed the report by using the Power BI JavaScript API.
        var models = window['powerbi-client'].models;
    
        var config = {
          type: 'report',
          id: reportId,
          embedUrl: embedUrl,
          accessToken: token,
          permissions: models.Permissions.All,
          tokenType: models.TokenType.Embed,
          viewMode: models.ViewMode.View,
          settings: {
            panes: {
              filters: { expanded: false, visible: true },
              pageNavigation: { visible: false }
            }
          }
        };
    
        // Embed the report and display it within the div container.
        var report = powerbi.embed(reportContainer, config);
    
        // 4 - Add logic to resize the embed container on a window resize event.
        var heightBuffer = 12;
        var newHeight = $(window).height() - ($("header").height() + heightBuffer);
        $("#embed-container").height(newHeight);
        $(window).resize(function () {
          var newHeight = $(window).height() - ($("header").height() + heightBuffer);
          $("#embed-container").height(newHeight);
        });
    
      });
    

6단계 - 애플리케이션 실행

이전 단계를 모두 수행한 후에는 애플리케이션을 실행할 준비가 된 것입니다. 애플리케이션을 실행하고 Power BI 보고서를 포함하는 방법을 실험해 봅니다. Power BI 임베디드 분석 클라이언트 API를 사용하면 클라이언트 쪽 API를 통해 앱을 향상할 수 있습니다.

Important

개발을 위해 무료 평가판 포함 토큰을 사용한 경우 프로덕션용 용량을 구입해야 합니다. 용량을 구매할 때까지 평가판 버전 배너가 포함된 보고서의 맨 위에 계속 표시됩니다.

앱이 준비되면 포함된 앱을 프로덕션으로 이동할 수 있습니다.