8 min read

Blazor 웹 애플리케이션에 React UI 컴포넌트 끼얹기

Justin Yoo

지난 빌드 2020 행사에서 엄청나게 많은 서비스와 기술들이 소개가 되었다. 이 중에서 프론트엔드 애플리케이션 개발에 한 획을 그을만한 내용이 하나 있었는데, 바로 Blazor 웹 어셈블리에 대한 것이다. 웹 어셈블리는 쉽게 말해서 웹 브라우저에서 자바스크립트 언어가 아닌 일반 프로그래밍 언어로 만들어진 바이너리를 작동시키는 기술이라고 이해하면 좋다. Blazor는 바로 이 웹 어셈블리를 이용해 닷넷 라이브러리를 웹브라우저에서 직접 실행시킬 수 있게 한다. Blazor에 대한 소개는 빌드 발표 동영상을 참조하도록 한다.

다른 프론트엔드 프레임워크와 마찬가지로 Blazor 웹 어셈블리 역시 자체 완결성을 갖고 있어서 다른 프론트엔드 프레임워크와 섞어 쓰기에는 까다로울 수 있다. 그럼에도 불구하고 기존의 컴포넌트 기반 프론트엔드 프레임워크라면 가능하기도 한데, 이 포스트에서는 React를 기반으로 하는 Fluent UI 컴포넌트를 Blazor 웹 어셈블리 웹 앱에 추가하는 방법에 대해 알아보기로 한다.

이 포스트에 쓰인 샘플 코드는 이곳https://github.com/devkimchi/Blazor-React-Sample에서 다운로드 받을 수 있다.

기본 Blazor 웹 어셈블리 앱 만들기

Blazor 서버 기반의 웹 애플리케이션과 달리 Blazor 웹 어셈블리 앱을 개발하기 위해서는 최신 버전의 .NET Core 3.1 SDK 3.1.4 버전 이상을 설치해야 한다. 자신의 운영체제에 맞는 설치 파일을 다운로드 받아서 설치하도록 하자. 설치가 끝났다면 Blazor 시작하기를 참고해서 간단한 앱을 하나 만들어 보자.

dotnet new blazorwasm -n BlazorJsSample

이 포스트에서는 웹 어셈블리 형태의 앱을 만들 예정이므로 blazorwasm을 선택했다. 만약 Blazor 서버 앱을 만들고자 한다면 blazorserver를 선택한다.

이후 dotnet run 명령어를 통해 앱을 실행시켜 보면 아래와 같은 화면을 보게 된다. Counter 페이지로 이동해서 Click me 버튼을 클릭하면 숫자가 올라가는 것도 확인할 수 있다.

여기까지는 Blazor 시작하기 문서에 나와 있는 바와 같다.

React UI 컴포넌트 추가하기

Fluent UIMicrosoft 365에 포함된 애플리케이션에 적용된 UI 프레임워크이다. 이 프레임워크에는 현재 React를 적용했는데, 웹 애플리케이션을 제작할 때 컴포넌트 방식으로 추가하기 쉽게 되어 있다. 이 포스트에서는 Progress Indicator 콘트롤을 이용해서 Click me 버튼을 누를 때 마다 콘트롤이 변하는 것을 간단하게 구현해 보자. 해당 콘트롤 문서 페이지에 있는 CodePen을 통해 제공되는 예제 코드를 활용하면 된다.

원래 Hassan HabibBlazor 서버를 이용한 예제를 유튭에 올려놓은 것이 있다. 이를 참고해서 Blazor 웹 어셈블리에 맞게 변형시켰다.

먼저 index.html 파일을 열어 아래와 같이 React 관련 자바스크립트를 CDN으로부터 가져온다.

<script crossorigin src="//unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="//unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script crossorigin src="//unpkg.com/office-ui-fabric-react@7/dist/office-ui-fabric-react.js"></script>

Blazor 웹 어셈블리C# 코드에서 자바스크립트를 호출한다거나, 반대로 자바스크립트에서 C# 코드를 호출할 수 있는데 이는 웹 어셈블리의 자바스크립트 상호운용성을 기반으로 한다. 이제 아래 자바스크립트를 작성한다. Blazor에서 RenderProgressBar 라는 펑션으로 count 값을 넘겨주면 이 펑션은 ProgressIndicator 컴포넌트를 생성하고 reactProgressBar라는 영역에 렌더링한다.

Blazor 에서 호출하는 자바스크립트 펑션은 기본적으로 window 아래에 존재하는 글로벌 스코프로 작동한다.

<script>
window.RenderProgressBar = (count) => {
const Progress = () => React.createElement(
Fabric.ProgressIndicator,
{
'label': 'React Counter',
'description': count,
'percentComplete': (count % 10) * 0.1
},
null
);
ReactDOM.render(Progress(), document.getElementById('reactProgressBar'));
}
</script>

이제 Counter.razor 페이지를 수정해 보자. 위에 작성한 자바스크립트 펑션을 호출해야 한다. 자바스크립트 펑션을 닷넷 코드에서 호출하기 위해서는 IJSRuntime 인스턴스를 이용해야 하는데, 이는 페이지에서 @inject 디렉티브를 통해 주입할 수 있다 (line #2). 그리고 IncrementCount() 메소드를 async로 바꾸고 (line #15), 그 메소드 안에서 InvokeVoidAsync() 메소드를 호출한다. 이 메소드를 통해 위에 작성한 자바스크립트의 RenderProgressBar 펑션을 호출하는 것이다 (line #19). 마지막으로 reactProgressBar 라는 ID로 컴포넌트가 렌더링될 수 있는 자리를 마련해 놓는다 (line #10).

@page "/counter"
@inject IJSRuntime Jsr
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<div id="reactProgressBar"></div>
@code {
private int currentCount = 0;
private async void IncrementCount()
{
currentCount++;
await Jsr.InvokeVoidAsync("RenderProgressBar", currentCount);
}
}

이렇게 한 후 다시 애플리케이션을 실행시켜서 Click me 버튼을 클릭해 보자. 그러면 아래와 같이 Progress Indicator가 보인다.


이렇게 해서 Blazor 웹 어셈블리 애플리케이션에 React 기반의 컴포넌트를 추가하는 방법에 대해 알아보았다. 여기서 고려하지 않은 부분이 몇 가지가 있는데,

  • 카운터 값이 바뀔 때 마다 컴포넌트를 새롭게 렌더링한다. 새롭게 렌더링하는 대신, Blazor 애플리케이션이 자체적으로 상태 관리가 가능하므로 이를 활용하는 방법이 더 좋을 수도 있다. 다만, 복잡도가 증가한다는 점도 고려해 두도록 하자.
  • React 라이브러리를 CDN에 직접 링크했다. npm 패키지를 이용할 수도 있는데, 이는 다음 포스트에서 다뤄보기로 한다.