# 보고서 디자이너 컨트롤에서 AI 지원 기능 활성화

## Content

## 소개

이 튜토리얼에서는 서로 협력하는 두 개의 프로젝트로 구성된 AI 지원 리포팅 솔루션을 구축하는 과정을 안내합니다:

* ActiveReports AI 미들웨어를 사용해 AI 리포팅 엔드포인트를 제공하는 **ASP.NET Core 백엔드**입니다. 클라이언트로부터 데이터 세트 설명을 받아 LLM 제공업체(OpenAI, Azure OpenAI, Google Gemini, 또는 로컬 Ollama 모델)로 전송하고, 바로 사용 가능한 리포트 항목(테이블, 테이블릭스, 차트)을 반환합니다.
* 해당 엔드포인트를 호출하는 **클라이언트 측 ActiveReportsJS 웹 보고서 디자이너**입니다. 최종 사용자가 필드를 하나씩 구성하는 대신, 클릭 한 번으로 데이터로부터 리포트 레이아웃을 생성할 수 있게 해줍니다.

이 튜토리얼을 마치면 다음 내용을 배우게 됩니다:

* ASP.NET Core 최소 API 프로젝트를 생성하고 ActiveReports AI NuGet 패키지를 설치하는 방법
* `Program.cs`에서 AI 제공업체(OpenAI, Azure OpenAI, Google Gemini, 또는 Ollama)와 AI 리포팅 미들웨어를 구성하는 방법
* 다른 출처(origin)에서 호스팅되는 디자이너가 엔드포인트를 호출할 수 있도록 CORS를 활성화하는 방법
* ActiveReportsJS 웹 보고서 디자이너에서 AI 지원 `Explore` 기능을 활성화하고 이를 사용자의 엔드포인트로 연결하는 방법
* 두 프로젝트를 함께 실행하고 AI를 사용해 데이터로부터 보고서 레이아웃을 생성하는 방법

## 필수 조건

이 튜토리얼을 시작하기 전에 다음 요구 사항이 충족되었는지 확인하세요:

* **.NET SDK**: .NET 8.0 SDK 이상
* **Node.js**: npm이 포함된 최신 LTS 버전의 Node.js. 클라이언트 측 디자이너를 설치하고 서비스하는 데 사용됩니다.
* **Visual Studio** **(선택 사항)**: `dotnet` CLI 대신 IDE에서 백엔드를 빌드하려는 경우, `ASP.NET 및 웹 개발` 워크로드가 포함된 Visual Studio 2022 이상.
* **AI 제공업체 계정**: 선택한 제공업체에 따라 다음 중 하나가 필요합니다:
    * OpenAI API 키.
    * 배포 이름, 엔드포인트 URL, API 키를 갖춘 Azure OpenAI 리소스.
    * Gemini용 Google AI Studio API 키.
    * 모델이 다운로드된(예: `ollama pull llama3.2`) 로컬 [Ollama](https://ollama.com/) 설치.
* **C#, JavaScript, Visual Studio에 대한 기본 지식**: C# 프로그래밍, 일반 JavaScript, Visual Studio 사용에 대한 기본적인 이해가 있다고 가정합니다. 복습이 필요하다면 [Microsoft C# 가이드](https://docs.microsoft.com/en-us/dotnet/csharp/)와 [Visual Studio 문서](https://learn.microsoft.com/en-us/visualstudio)가 좋은 자료가 될 것입니다.

## 솔루션 개요

두 프로젝트는 HTTP를 통해 서로 통신합니다:

1. **웹 보고서 디자이너**(정적 파일로 제공됨, 예: `http-server`를 통해)는 `http://127.0.0.1:8080`과 같은 특정 출처(origin)에서 브라우저 내에서 실행됩니다.
2. 사용자가 데이터 집합에 대해 [Explore 기능](/activereportsjs/docs/ReportAuthorGuide/Report-Designer-Interface#explore-기능)을 실행하면, 디자이너는 데이터 집합의 필드를 설명하는 `POST` 요청을 백엔드의 AI 리포팅 엔드포인트(기본값 `/api/reporting/ai`)로 전송합니다.
3. **ASP.NET Core 백엔드**는 `http://localhost:5100`과 같은 다른 출처에서 실행됩니다. 백엔드의 AI 리포팅 미들웨어는 요청을 받아 필드로 구성된 프롬프트를 구성된 AI 제공업체로 전달하고, 생성된 리포트 항목 정의([테이블](/activereportsjs/docs/ReportAuthorGuide/Report-Items/Data-Regions/Table), [테이블릭스](/activereportsjs/docs/ReportAuthorGuide/Report-Items/Data-Regions/Tablix), 또는 [차트](https://docapp.mescius.io/manage/ArticleEdit//activereportsjs/docs/v6.2/)[차트](/activereportsjs/docs/ReportAuthorGuide/Report-Items/Data-Regions/Chart))를 JSON 형태로 반환합니다.
4. 디자이너는 반환된 리포트 항목을 리포트 레이아웃에 직접 렌더링합니다.

두 프로젝트가 서로 다른 포트에서 실행되므로, 백엔드에서 **CORS**가 활성화되어 있어야 합니다. 그렇지 않으면 브라우저가 디자이너의 요청을 차단합니다.

## Part 1 — AI 리포팅 백엔드 구축

### 새 프로젝트 생성

1. Visual Studio를 실행합니다(이 튜토리얼은 Visual Studio 2022를 기준으로 하지만, 다른 버전에서도 단계는 유사하며, 명령줄에서 `dotnet new web`을 사용하는 경우에도 동일합니다)
2. Visual Studio 시작 창에서 `Create a new project` 옵션을 선택합니다.
3. 프로젝트 템플릿 목록에서 `ASP.NET Core Empty`를 찾아 선택합니다. `Next` 버튼을 클릭해 계속합니다.
4. `Configure your new project` 대화 상자에서 프로젝트 이름(예: `ActiveReportsAIBackEnd`)을 지정하고, 적절한 위치를 선택한 후 `Next`를 클릭합니다.
5. `Additional Information` 대화 상자에서 대상 프레임워크로 `.NET 8.0`(또는 그 이상)을 선택하고 `Create`를 클릭합니다.

CLI를 선호하는 경우, 다음과 같이 동일하게 실행할 수 있습니다:

```auto
dotnet new web -n ActiveReportsAIBackEnd
```

### ActiveReports NuGet 패키지 설치

다음 두 개의 패키지가 필요합니다.

* `MESCIUS.ActiveReports.AI.Web` — AI 리포팅 엔드포인트를 제공하는 ASP.NET Core 미들웨어입니다.
* 사용하려는 AI 서비스에 맞는 제공업체 패키지 하나:

| 제공업체 | 패키지 |
| ---- | --- |
| OpenAI | `MESCIUS.ActiveReports.Design.AI.OpenAI` |
| Azure OpenAI | `MESCIUS.ActiveReports.Design.AI.AzureOpenAI` |
| Google Gemini | `MESCIUS.ActiveReports.Design.AI.Google` |
| Ollama (local) | `MESCIUS.ActiveReports.Design.AI.Ollama` |

설치하려면:

1. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 `Manage NuGet Packages`를 선택합니다.
2. `Browse` 탭으로 이동해 `MESCIUS.ActiveReports.AI.Web`을 검색합니다. 선택한 후 `Install`을 클릭합니다.
3. 사용하려는 AI 서비스에 맞는 제공업체 패키지에 대해서도 동일하게 반복합니다.
4. `License Acceptance` 대화 상자에서 설치된 패키지의 라이선스 조건에 동의합니다.

또는 CLI에서 (OpenAI를 사용하는 예시):

```auto
dotnet add package MESCIUS.ActiveReports.AI.Web 
dotnet add package MESCIUS.ActiveReports.Design.AI.OpenAI
```

### AI 제공업체 구성

`Program.cs`를 열고 `builder.Build()` 이전에 AI 제공업체를 등록합니다. 설치한 패키지에 맞는 아래 블록을 선택하세요.
**옵션 A — OpenAI**

```csharp
using GrapeCity.ActiveReports.Design.AI.OpenAI.Extensions;

builder.Services.AddOpenAI(config =>
{
    config.ApiKey = "sk-..."; // your OpenAI API key
    config.Model = "gpt-4o";
    config.Timeout = 300 * 1000; // milliseconds
});
```

**옵션 B — Azure OpenAI**

```csharp
using GrapeCity.ActiveReports.Design.AI.AzureOpenAI.Extensions;

builder.Services.AddAzureOpenAI(config =>
{
    config.Endpoint = "https://my-resource.openai.azure.com/";
    config.DeploymentName = "my-gpt4o-deployment";
    config.Model = "gpt-4o";
    config.ApiKey = "...";
    config.Timeout = 300 * 1000; // milliseconds
});
```

**옵션 C — Google Gemini**

```csharp
using GrapeCity.ActiveReports.Design.AI.Google.Extensions;

builder.Services.AddGemini(config =>
{
    config.ApiKey = "AIza...";
    config.Model = "gemini-2.0-flash";
    config.Timeout = 300 * 1000; // milliseconds
});
```

**옵션 D — Ollama (local)**

```csharp
using GrapeCity.ActiveReports.Design.AI.Ollama.Extensions;

builder.Services.AddOllama(config =>
{
    config.Endpoint = "http://localhost:11434";
    config.Model = "llama3.2";
    config.Timeout = 300 * 1000; // milliseconds
});
```

> **참고:** `Timeout`은 모든 제공업체에서 선택 사항이며 기본값은 `90000`(90초)입니다. AI가 생성하는 레이아웃은 데이터 집합이 클 경우 시간이 다소 걸릴 수 있으므로, 예시에서는 이 값을 5분으로 늘렸습니다.

> **보안 팁:** 위 예시처럼 `Program.cs`에 API 키를 하드코딩하지 마세요(간단한 로컬 테스트 목적이 아니라면). 개발 환경에서는 [user-secrets](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets)를 사용하고, 프로덕션 환경에서는 환경 변수나 비밀 관리자(Azure Key Vault 등)를 사용한 후, `builder.Configuration["OpenAI:ApiKey"]`로 값을 읽어오세요.

### AI 리포팅 미들웨어 활성화

`Program.cs`에서 계속해서, `builder.Build()` 이후에 AI 리포팅 미들웨어를 추가합니다:

```csharp
using GrapeCity.ActiveReports.AI.Web.Extensions;

app.UseAIReporting();
```

기본적으로 이 엔드포인트는 `/api/reporting/ai`에 마운트됩니다. 다른 경로를 사용하려면 오션 델리게이트를 전달하세요.

```csharp
app.UseAIReporting(options =>
{
    options.ApiEndPoint = "/api/custom/ai";
});
```

이 엔드포인트는 `type` 쿼리 매개변수가 `table`, `tablix`, `chart` 중 하나인 `POST` 요청만 허용합니다. 그 외의 메서드나 타입은 오류를 반환하므로, 이를 시도하기 위해 추가로 구성할 사항은 없습니다.

### CORS 활성화

웹 보고서 디자이너는 다른 출처(`localhost`의 다른 포트, 또는 완전히 다른 호스트)에서 제공되므로, 백엔드에서 명시적으로 허용하지 않는 한 브라우저는 AI 엔드포인트로의 요청을 차단합니다. `builder.Build()` 이전에 CORS 정책을 등록하고, `UseAIReporting()` 이전에 이를 적용하세요:

```csharp
const string CorsPolicyName = "AllowAnyOrigin";

builder.Services.AddCors(options =>
{
    options.AddPolicy(CorsPolicyName, policy =>
    {
        policy.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader();
    });
});

var app = builder.Build();

app.UseCors(CorsPolicyName);
app.UseAIReporting();
```

`AllowAnyOrigin()`은 로컬 개발 환경에서는 편리하지만, 프로덕션 환경에서는 지나치게 허용적입니다. 디자이너를 서비스할 호스트가 정해지면, 이를 명시적인 허용 목록으로 교체하세요:

```csharp
policy.WithOrigins("https://my-designer-host.example.com")
      .AllowAnyMethod()
      .AllowAnyHeader();
```

### 전체 코드 종합

완성된 `Program.cs` (OpenAI 버전)는 다음과 같은 모습이어야 합니다:

```csharp
using GrapeCity.ActiveReports.AI.Web.Extensions;
using GrapeCity.ActiveReports.Design.AI.OpenAI.Extensions;

namespace ActiveReportsAIBackEnd
{
    public class Program
    {
        private const string CorsPolicyName = "AllowAnyOrigin";

        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            builder.Services.AddOpenAI(config =>
            {
                config.ApiKey = "sk-...";
                config.Timeout = 300 * 1000;
                config.Model = "gpt-4o";
            });

            builder.Services.AddCors(options =>
            {
                options.AddPolicy(CorsPolicyName, policy =>
                {
                    policy.AllowAnyOrigin()
                          .AllowAnyMethod()
                          .AllowAnyHeader();
                });
            });

            var app = builder.Build();

            app.UseCors(CorsPolicyName);
            app.UseAIReporting();

            app.Run();
        }
    }
}
```

### 백엔드 실행

1. 프로젝트를 빌드하려면 Visual Studio의 `Build` 메뉴로 이동해 `Build Solution`을 선택하세요(또는 `dotnet build`를 실행하세요).
2. Visual Studio에서 `Start Debugging`/`Start Without Debugging`으로 애플리케이션을 시작하거나, CLI에서 `dotnet run`을 실행하세요.
3. 프로젝트가 수신 대기하는 URL을 확인하세요(`Properties/launchSettings.json` 또는 콘솔 출력을 확인) — 예를 들어 `http://localhost:5100`입니다. 다음 단계에서 클라이언트 프로젝트를 구성할 때 이 값이 필요합니다.

## Part 2 — ActiveReportsJS 웹 보고서 디자이너 연결

### 클라이언트 프로젝트 설정

1. 클라이언트 프로젝트를 위한 새 폴더(예: `arjs-test-app`)를 만들고 `npm init -y`로 초기화합니다.
2. ActiveReportsJS 패키지와 간단한 정적 파일 서버를 설치합니다:

```auto
npm install @mescius/activereportsjs@latest
npm install http-server --save
```

3. 폴더를 정적 파일로 제공할 수 있도록 `package.json`에 `start` 스크립트를 추가합니다:

```json
{
  "scripts": {
    "start": "http-server"
  },
  "dependencies": {
    "@mescius/activereportsjs": "^6.2.0-beta.7237",
    "http-server": "^14.1.1"
  }
}
```

### 디자이너 페이지 생성하기

다음 내용으로 `index.des.html` 파일을 생성합니다:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>ARJS Report designer</title>
    <link rel="stylesheet" type="text/css" href="node_modules/@mescius/activereportsjs/styles/ar-js-ui.css" />
    <link rel="stylesheet" type="text/css" href="node_modules/@mescius/activereportsjs/styles/ar-js-designer.css" />
    <script src="node_modules/@mescius/activereportsjs/dist/ar-js-core.js"></script>
    <script src="node_modules/@mescius/activereportsjs/dist/ar-js-designer.js"></script>
    <style>
      #designer-host {
        width: 100%;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="designer-host"></div>
    <script>
      var designer = new MESCIUS.ActiveReportsJS.ReportDesigner.Designer("#designer-host", {
        data: {
          dataSets: {
            visible: true,
            canModify: true,
            features: {
              explore: {
                enabled: true,
                apiEndpoint: "http://localhost:5100/api/reporting/ai"
              }
            }
          }
        }
      });
      designer.setReport({ id: "Reports/Products.rdlx-json", displayName: "my report" });
    </script>
  </body>
</html>
```

관련 부분은 `data.dataSets.features.explore` 블록입니다:

* `enabled`는 필드 목록 패널에서 데이터 집합에 대한 AI 지원 "Explore" 작업을 켭니다. 기본값은 `false`입니다.
* `apiEndpoint`는 백엔드에서 제공하는 AI 리포팅 엔드포인트의 절대 또는 상대 URL입니다. 기본값은 `/api/reporting/ai`(디자이너가 백엔드와 동일한 출처/앱에서 제공될 때 유용함)이지만, 여기서는 다른 출처인 `http://localhost:5100/api/reporting/ai` — 1부에서 백엔드를 실행했을 때 출력된 주소를 가리킵니다.

### 클라이언트 실행

1. 정적 파일 서버를 시작합니다.

```auto
npm start
```

2. `http-server`는 수신 대기 중인 URL을 출력합니다.(일반적으로 `http://127.0.0.1:8080`). 브라우저에서 `http://127.0.0.1:8080/index.des.html`을 엽니다..

웹 보고서 디자이너가 빈(또는 지정된) 리포트를 연 상태로 로드되어야 합니다.

## AI 지원 보고서 디자인 사용하기

두 프로젝트가 모두 실행 중인 상태에서 [Explore 기능](/activereportsjs/docs/ReportAuthorGuide/Report-Designer-Interface#explore-기능) 문서의 안내를 따르세요.

## 문제 해결

* **브라우저 콘솔에 CORS 오류가 발생하는 경우** (`has been blocked by CORS policy`): 백엔드가 실행 중인지, `AddCors`/`UseCors`가 위 예시대로 구성되어 있는지, 그리고 `UseCors`가 `UseAIReporting`보다 먼저 호출되는지 확인하세요.
* **AI 엔드포인트 호출 시 404 Not Found가 발생하는 경우**: `index.des.html`의 `apiEndpoint`가 백엔드가 실제로 수신 대기 중인 포트와 일치하는지, 그리고 경로가 `AIReportingOptions`의 `ApiEndPoint`(기본값 `/api/reporting/ai`)와 일치하는지 다시 확인하세요.
* **401/403 또는 제공업체 오류가 발생하는 경우**: 제공업체에 맞게 구성한 API 키, 배포 이름(Azure OpenAI), 또는 엔드포인트(Ollama)가 올바른지, 그리고 계정/모델이 할당량이나 속도 제한에 도달하지 않았는지 확인하세요.
* **큰 데이터 집합에서 타임아웃이 발생하는 경우**: 구성한 제공업체의 `config.Timeout`(밀리초 단위) 값을 늘리세요.