Skip to main content

Command Palette

Search for a command to run...

.net으로 웹어셈블리 애플리케이션 시작하기

Updated
3 min read

.NET은 Blazor Webassembly를 통해 SPA(Single Page Application) 서비스를 제작할 수 있는 환경을 이미 제공하고 있습니다.

또한 .NET RC1 이후부터 wasm-experimental 워크로드를 설치하면 Blazor를 사용하지 않고도 웹브라우저 및 콘솔에서 동작하는 웹어셈블리용 애플리케이션을 만들 수 있습니다.

wasm-experimental 워크로드는 이후 .NET 8에 정식 릴리스 될 예정입니다.

워크로드 설치 및 프로젝트 생성

.NET 버전이 RC1 이상이여야 합니다.

wasm-toolswasm-experimental 워크로드를 설치합니다.

dotnet workload install wasm-tools
dotnet workload install wasm-experimental

그 다음 웹브라우저용 웹어셈블리 템플릿으로 프로젝트를 생성합니다.

dotnet new wasmbrowser

컴파일 및 실행

컴파일

dotnet build

실행

dotnet-serv가 설치되지 않았을 경우 dotnet tool install --global dotnet-serve로 설치합니다.

dotnet serv --directory bin\Debug\net7.0\browser-wasm\AppBundle

RC1 버전에서 dotnet run으로 실행되지 않는 문제가 있습니다. 버전 RC2에서는 개선이 된다고 합니다.

다음처럼 콘솔에서 서버가 시작되고, image.png

해당 주소로 접속하면 다음처럼 .NET으로 컴파일 된 웹어셈블리 코드가 잘 실행되는 것을 확인할 수 있습니다.

image.png

게시

다음의 명령으로 배포할 수 있습니다. 게시된 경로는 bin\Release\net7.0\browser-wasm\AppBundle 입니다.

dotnet publish -c Release

트림 설정 및 AOT 컴파일

프로젝트에 다음의 설정을 추가해서 트림 및 AOT 컴파일을 할 수 있습니다.

| csproj

...
      <PublishTrimmed>true</PublishTrimmed>
      <TrimMode>full</TrimMode>
      <RunAOTCompilation>true</RunAOTCompilation>
...

이제 게시를 했을 때 트림 및 AOT 컴파일로 인해 좀 더 컴파일 시간이 늘어나지만 좀 더 빠른 시작 시간 및 동작속도의 웹어셈블리 파일을 생성할 수 있습니다.

프로젝트 둘러보기

템플릿에 의해 기본 생성되는 프로젝트는 다음의 구조입니다.

image.png

html이 로딩되면서 웹어셈블리를 시작해야 하는데요, 그것을 담당하는 곳이 main.js 입니다. 이곳에서 관련 초기화 및 .NET 메소드를 호출하는 코드와 .NET의 main() 호출 및 매개변수를 전달하는 코드를 확인할 수 있습니다.

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

import { dotnet } from './dotnet.js'

const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);

const { setModuleImports, getAssemblyExports, getConfig, runMainAndExit } = await dotnet
    .withDiagnosticTracing(false)
    .withApplicationArgumentsFromQuery()
    .create();

setModuleImports("main.js", {
    window: {
        location: {
            href: () => globalThis.window.location.href
        }
    }
});

const config = getConfig();
const exports = await getAssemblyExports(config.mainAssemblyName);
const text = exports.MyClass.Greeting();
console.log(text);

document.getElementById("out").innerHTML = `${text}`;
await runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]);

Program.cs를 보면 JavaScript에서 호출 할 수 있도록 [JSExport] 특성을 사용할 수 있고, JavaScript 함수를 호출할 수 있도록 [JSImport] 특성을 사용하고 partial 키워드를 줘서 코드 생성기를 통해 해당 interop 코드를 생성합니다.

배포

생성된 AppBundle은 정적 파일(static files)이므로 정적 파일을 올려서 웹주소로 접근 가능하면 실행할 수 있습니다. bin\Release\net7.0\browser-wasm\AppBundle의 파일을 배포할 위치로 업로드 합니다.

github 페이지 기능을 이용해 .NET 웹어셈블리 애플리케이션을 실행해 볼 수 있습니다.

https://dimohy.github.io/FirstWebassembly/

정리

웹어셈블리 환경은 격리된 환경에서 플랫폼에 상관없이 서비스를 제공할 수 있는 멋진 환경입니다. .NET으로 만들 수 있는 웹어셈블리 애플리케이션의 가능성은 무궁무진합니다. 앞으로 .NET 웹어셈블리로 동작하는 다양한 서비스가 등장하길 기대해봅니다.

More from this blog

개발, 테스트, 운영에서의 도커 활용

핵심 원칙: "한 번 빌드하고, 어디서든 실행한다 (Build once, run anywhere)" 도커의 가장 큰 장점은 환경 일관성입니다. 동일한 도커 이미지를 사용하여 개발, 테스트, 운영 환경을 구성함으로써 "제 PC에서는 됐는데..." 하는 문제를 최소화할 수 있습니다. 1. 개발 단계 (Development) 목표: 빠른 코드 변경 반영, 쉬운 디버깅, 실제 운영 환경과 유사한 환경 구성. Docker 사용 방안: Dockerf...

May 9, 20256 min read15

[EF Core] 데이터 삭제 시 소프트 삭제 적용

DB에서 데이터를 삭제하면 일반적으로 복구할 수 없습니다. 또한 관계에 따라 영구 삭제 자체가 어려울 수도 있습니다. 그래서 데이터를 영구 삭제하는 대신 IsDeleted 속성을 true로 주고 IsDeleted 속성을 필터링해서 조회하는 방법을 사용하기도 합니다. 이를 소프트 삭제라고 합니다. 그런데 EF에서 알아서 데이터 삭제 시 소프트 삭제를 하고 쿼리시 IsDeleted 속성을 체크해서 삭제한 데이터를 제외한 데이터만 쿼리하게 하는 ...

Mar 18, 20243 min read19

[EF Core] ValueConverter를 이용해서 엔터티 속성의 도메인 관리

EF Core를 사용하면서 문자열 길이 등의 특성을 일일이 지정하는 것은 번거롭습니다. ... [MaxLength(32)] public string? 제목 { get; set; } 엔터티가 한 개일 때는 상관이 없으나 제목 유형이 여러 엔터티에 사용될 경우 유형을 지정하기 번거롭습니다. 속성 유형을 도메인으로 관리하면 참 편할텐데요, ValueConverter를 이용할 수 있습니다. 그런데 이것을 인터페이스 정적 추상를 사용해서 다음처럼 ...

Mar 16, 20242 min read8

디모이 블로그

154 posts

.NET 관련 기술을 선호하고 새로운 언어를 배우는데 관심이 있습니다.