JavaScript와 Blazor의 상호 운용성
Blazor는 JavaScript가 아닌 C# 구성 요소를 사용하여 동적 콘텐츠가 있는 웹 페이지 또는 HTML 섹션을 만듭니다. 그러나 Blazor JS interop(JavaScript 상호 운용성)을 사용하여 Blazor 앱에서 JavaScript 라이브러리를 호출하고 .NET C# 코드에서 JavaScript 함수를 호출할 수 있습니다.
이 단원에서는 Blazor 페이지의 C# 코드에서 JavaScript를 호출하는 방법과 JavaScript 함수에서 C# 메서드를 호출하는 방법을 알아봅니다. 다음 단원에서는 JavaScript 라이브러리의 경고 구성 요소를 사용하여 Blazor 피자 배달 웹 사이트를 업데이트합니다.
Blazor JavaScript 상호 운용성 사용
일반적인 Blazor 구성 요소는 레이아웃 및 사용자 인터페이스 논리를 사용하여 런타임에 HTML을 렌더링합니다. C# 코드를 사용하여 사용자 및 외부 서비스와 상호 작용하는 이벤트 및 기타 동적 페이지 기능을 처리합니다. 대부분의 경우 JavaScript 코드를 사용할 필요가 없습니다. 대신 많은 동등한 기능을 제공하는 .NET 라이브러리와 함께 Blazor를 사용할 수 있습니다.
그러나 기존 JavaScript 라이브러리를 사용해야 하는 경우가 있습니다. 예를 들어 일부 오픈 소스 JavaScript 라이브러리는 특수한 방식으로 구성 요소를 렌더링하고 사용자 인터페이스 요소를 처리합니다. 또는 C#으로 변환하는 대신 재사용하려는 기존의 검증된 JavaScript 코드가 있을 수 있습니다.
Blazor JavaScript 상호 운용성 또는 JS interop을 사용하여 JavaScript 라이브러리를 애플리케이션에 통합할 수 있습니다. JS interop을 사용하여 .NET 메서드에서 JavaScript 함수를 호출하고 JavaScript 함수에서 .NET 메서드를 호출합니다. JS interop은 Blazor와 JavaScript 간에 데이터 및 개체 참조 마샬링을 처리하여 쉽게 전환할 수 있도록 합니다.
Blazor 앱에서 JavaScript 코드 로드
HTML <script>
요소를 사용하여 표준 HTML 웹앱에 추가하는 것과 동일한 방식으로 Blazor 앱에 JavaScript를 추가합니다. Blazor 호스팅 모델에 따라 Pages/_Host.cshtml 파일 또는 wwwroot/index.html 파일에서 기존 <script src="_framework/blazor.*.js"></script>
태그 뒤에 <script>
태그를 추가합니다. 자세한 내용은 ASP.NET Core Blazor 호스팅 모델을 참조하세요.
페이지의 <head>
요소에 스크립트를 배치하지 않는 것이 좋습니다. Blazor는 HTML 페이지의 <body>
요소에 있는 콘텐츠만 제어하므로 스크립트가 Blazor를 사용하는 경우 JS interop이 실패할 수 있습니다. 또한 JavaScript 코드를 구문 분석하는 데 걸리는 시간으로 인해 페이지가 더 느리게 표시될 수 있습니다.
<script>
태그는 HTML 웹앱에서와 마찬가지로 작동합니다. 태그 본문에 직접 코드를 작성하거나 기존 JavaScript 파일을 참조할 수 있습니다. 자세한 내용은 ASP.NET Core Blazor JavaScript 상호 운용성(JS interop): JavaScript 위치를 참조하세요.
중요
Blazor 앱의 wwwroot 폴더 아래에 JavaScript 파일을 배치합니다.
또 다른 옵션은 JavaScript 파일을 참조하는 <script>
요소를 Pages/_Host.cshtml 페이지에 동적으로 삽입하는 것입니다. 이 접근 방식은 런타임에만 확인할 수 있는 조건에 따라 다른 스크립트를 로드해야 하는 경우에 유용합니다. 또한 이 접근 방식은 페이지가 렌더링된 후 발생하는 이벤트로 논리를 트리거하는 경우 앱의 초기 로딩 속도를 단축할 수 있습니다. 자세한 내용은 ASP.NET Core Blazor 스타트업을 참조하세요.
.NET 코드에서 JavaScript 호출
IJSRuntime을 사용하여 .NET 코드에서 JavaScript 함수를 호출합니다. JS interop 런타임을 사용할 수 있도록 설정하려면 Blazor 페이지에서 파일 시작 부분 근처에 있는 @page
지시문 뒤에 IJSRuntime
추상화의 인스턴스를 삽입합니다.
IJSRuntime
인터페이스는 InvokeAsync 및 InvokeVoidAsync 메서드를 노출하여 JavaScript 코드를 호출합니다. InvokeAsync<TValue>
를 사용하여 값을 반환하는 JavaScript 함수를 호출합니다. 그렇지 않으면 InvokeVoidAsync
를 호출합니다. 이름에서 알 수 있듯이, 두 메서드는 모두 비동기식이므로 C# await
연산자를 사용하여 결과를 캡처합니다.
InvokeAsync
또는 InvokeVoidAsync
메서드에 대한 매개 변수는 호출할 JavaScript 함수의 이름이며 함수에 필요한 인수가 뒤에 추가됩니다. JavaScript 함수는 window
범위의 일부이거나 window
의 하위 범위여야 합니다. 인수는 JSON 직렬화 가능해야 합니다.
참고
JS interop은 Blazor Server 앱이 브라우저와의 SignalR 연결을 설정했을 때만 사용할 수 있습니다. 렌더링이 완료될 때까지 interop 호출을 만들 수 없습니다. 렌더링이 완료되었는지 여부를 검색하려면 Blazor 코드에서 OnAfterRender 또는 OnAfterRenderAsync 이벤트를 사용합니다.
ElementReference 개체를 사용하여 DOM 업데이트
Blazor는 DOM(문서 개체 모델)의 표현을 가상 렌더링 트리로 유지 관리합니다. 페이지 구조가 변경되면 Blazor는 차이점이 포함된 새 렌더링 트리를 생성합니다. 변경이 완료되면 Blazor는 차이점을 반복하여 사용자 인터페이스의 브라우저 표시와 JavaScript에서 사용하는 DOM의 브라우저 버전을 업데이트합니다.
많은 타사 JavaScript 라이브러리를 사용하여 페이지에서 요소를 렌더링할 수 있으며 이러한 라이브러리는 DOM을 업데이트할 수 있습니다. JavaScript 코드가 DOM의 요소를 수정하면 DOM의 Blazor 복사본은 더 이상 현재 상태와 일치하지 않습니다. 이 상황으로 인해 예기치 않은 동작이 발생할 수 있으며 보안 위험이 발생할 수 있습니다. DOM의 Blazor 뷰 손상을 초래할 수 있는 변경을 수행하지 않는 것이 중요합니다.
이 상황을 처리하는 가장 간단한 방법은 Blazor 구성 요소에 자리 표시자 요소(일반적으로 빈 <div @ref="placeHolder"></div>
요소)를 만드는 것입니다. Blazor 코드는 이 코드를 빈 공간으로 해석하며 Blazor 렌더링 트리는 해당 콘텐츠를 추적하려고 시도하지 않습니다. 이 <div>
에 JavaScript 코드 요소를 자유롭게 추가할 수 있으며 Blazor는 해당 요소를 변경하려고 시도하지 않습니다.
Blazor 앱 코드는 <div>
요소에 대한 참조를 저장할 ElementReference 형식의 필드를 정의합니다. <div>
요소의 @ref
특성은 필드 값을 설정합니다. 그런 다음, ElementReference
개체는 JavaScript 함수에 전달되며, 이 함수는 해당 참조를 사용하여 <div>
요소에 콘텐츠를 추가할 수 있습니다.
JavaScript에서 .NET 코드 호출
JavaScript 코드는 JS interop 라이브러리의 일부인 DotNet
유틸리티 클래스를 사용하여 Blazor 코드에서 정의하는 .NET 메서드를 실행할 수 있습니다. DotNet
클래스는 invokeMethod
및 invokeMethodAsync
도우미 함수를 노출합니다. invokeMethod
를 사용하여 메서드를 실행하고 결과를 기다리거나, invokeMethodAsync
를 사용하여 메서드를 비동기식으로 호출합니다. invokeMethodAsync
메서드는 JavaScript Promise
를 반환합니다.
팁
애플리케이션에서 응답성을 유지 관리하려면 .NET 메서드를 async
로 정의하고 JavaScript에서 invokeMethodAsync
를 사용하여 호출합니다.
JSInvokableAttribute를 사용하여 호출되는 .NET 메서드에 태그를 지정해야 합니다. 메서드는 public
이어야 하며 모든 매개 변수는 JSON으로 직렬화할 수 있어야 합니다. 또한 비동기 메서드의 경우 반환 형식은 void
, Task
또는 제네릭 Task<T>
개체여야 합니다. 여기서 T
는 JSON 직렬화 가능 형식입니다.
static
메서드를 호출하려면 클래스를 포함하는 .NET 어셈블리의 이름, 메서드의 식별자, 메서드가 invokeMethod
또는 invokeMethodAsync
함수의 인수로 허용하는 매개 변수를 제공합니다. 기본적으로 메서드 식별자는 메서드 이름과 동일하지만 JSInvokable
특성을 사용하여 다른 값을 지정할 수 있습니다.
JavaScript에서 .NET 인스턴스 메서드 호출
인스턴스 메서드를 실행하려면 JavaScript에 인스턴스를 가리키는 개체 참조가 필요합니다. JS interop은 .NET 코드에서 개체 참조를 만드는 데 사용할 수 있는 제네릭 DotNetObjectReference 형식을 제공합니다. 코드가 JavaScript에서 이 개체 참조를 사용할 수 있도록 설정해야 합니다.
그러면 JavaScript 코드는 .NET 메서드의 이름 및 메서드에 필요한 매개 변수를 사용하여 invokeMethodAsync
를 호출할 수 있습니다. 메모리 누수를 방지하기 위해 .NET 코드는 더 이상 필요하지 않을 때 개체 참조를 삭제해야 합니다.