๐ Blazor WebAssembly๋ก SPA ๊ฐ๋ฐ ์์ํ๊ธฐ ๐

์๋ ํ์ธ์, ์ฌ๋ฌ๋ถ! ์ค๋์ ์ ๋ง ํซํ ์ฃผ์ ๋ก ์ฐพ์์์ด์. ๋ฐ๋ก Blazor WebAssembly๋ฅผ ์ฌ์ฉํด์ SPA(Single Page Application)๋ฅผ ๊ฐ๋ฐํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ์ด๊ฑฐ ์ง์ง ๋๋ฐ์ด์์! ๐
์์ฆ ์น ๊ฐ๋ฐ ํธ๋ ๋๋ฅผ ๋ณด๋ฉด SPA๊ฐ ๋์ธ์์์? ๊ทธ๋ฐ๋ฐ C# ๊ฐ๋ฐ์๋ค์ ์ข ์์ฌ์ ์ฃ . JavaScript ํ๋ ์์ํฌ๋ค๋ง ์ฃผ๋ชฉ๋ฐ๋ ๊ฒ ๊ฐ๊ณ ... ๊ทผ๋ฐ ์ด์ ๊ทธ๋ด ํ์ ์์ด์! Blazor WebAssembly๊ฐ ๋ฑ์ฅํ๊ฑฐ๋ ์! ์ด์ C# ๊ฐ๋ฐ์๋ค๋ ํ์คํ ๊ฐ๋ฐ์ ๊ฟ์ ์ด๋ฃฐ ์ ์์ด์. ์ด๋ ์ธ์? ๊ธฐ๋๋์ง ์๋์? ใ ใ ใ
๐ก ์๊ณ ๊ณ์ จ๋์? Blazor WebAssembly๋ฅผ ์ฌ์ฉํ๋ฉด C#์ผ๋ก ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ์ ์์ด์. ์ด๊ฒ ๋ฐ๋ก ๋ง์ดํฌ๋ก์ํํธ๊ฐ ์ฐ๋ฆฌ์๊ฒ ์ค ์ ๋ฌผ์ด์ฃ !
์, ์ด์ ๋ถํฐ Blazor WebAssembly์ ์ธ๊ณ๋ก ๋น ์ ธ๋ณผ๊น์? ์ค๋น๋์ จ๋์? ๊ทธ๋ผ ๊ณ ๊ณ ์ฝ~! ๐โโ๏ธ๐จ
๐ Blazor WebAssembly๋ ๋ญ์ผ? ๐
์, ๋จผ์ Blazor WebAssembly๊ฐ ๋ญ์ง ์์๋ณผ๊น์? ์ด๋ฆ๋ถํฐ ์ข ๋ฉ์์์์? ใ ใ ใ
Blazor WebAssembly๋ ๋ง์ดํฌ๋ก์ํํธ๊ฐ ๊ฐ๋ฐํ ํด๋ผ์ด์ธํธ ์ฌ์ด๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ์์. ์ด ๋ ์์ ํน๋ณํ ์ ์ ๋ญ๋๊ณ ์? ๋ฐ๋ก C#์ ์ฌ์ฉํด์ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ์คํ๋๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค ์ ์๋ค๋ ๊ฑฐ์์! ๐ฎ
๊ทธ๋ผ ์ด๊ฒ ์ ๋๋จํ ๊ฑด์ง ์ข ๋ ์์ธํ ์์๋ณผ๊น์?
- ๐ C#์ผ๋ก ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ด ๊ฐ๋ฅํด์: JavaScript? ์๋ ~ ์ด์ C#์ผ๋ก ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ํ ์ ์์ด์. C# ๊ฐ๋ฐ์๋ค์๊ฒ๋ ์ ๋ง ๊ฟ๋ง ๊ฐ์ ์ผ์ด์ฃ !
- ๐ WebAssembly ๊ธฐ๋ฐ์ด์์: WebAssembly๋ ๋ธ๋ผ์ฐ์ ์์ ๋ค์ดํฐ๋ธ์ ๊ฐ๊น์ด ์ฑ๋ฅ์ผ๋ก ์ฝ๋๋ฅผ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ์ ์ด์์. ๋น ๋ฅด๊ณ ํจ์จ์ ์ด์ฃ !
- ๐ .NET ์ํ๊ณ์์ ์ฐ๊ฒฐ: .NET์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ด์. ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ๋๊ตฌ ๋ฑ ๋ชจ๋ ๊ฒ์ด ์ฌ๋ฌ๋ถ์ ๊ฒ์ด์์!
- ๐ ํฌ๋ก์ค ํ๋ซํผ: ๋ชจ๋ ์ต์ ์น ๋ธ๋ผ์ฐ์ ์์ ๋์ํด์. IE๋ ์๋ ~ ๐
์ด๋์? ๋ฒ์จ๋ถํฐ ํฅ๋ถ๋์ง ์๋์? ใ ใ ใ ์ ๋ ์ฒ์ Blazor WebAssembly๋ฅผ ์์์ ๋ ์ ๋ง ๋๋์ด์. C#์ผ๋ก ์น ๊ฐ๋ฐ์ ํ๋ค๋, ์ด๊ฒ ๋ง์ด ๋ผ์? ๊ทผ๋ฐ ์ง์ง์์! ๐
๐ ์ฌ๋ฏธ์๋ ์ฌ์ค: Blazor๋ผ๋ ์ด๋ฆ์ 'Browser'์ 'Razor'๋ฅผ ํฉ์น ๊ฑฐ์์. Razor๋ ASP.NET์ ๋ทฐ ์์ง์ด์ฃ . ์ด๋ฆ๋ถํฐ ์ผ์ค ์๋ค์, ๊ทธ์ตธ?
์, ์ด์ Blazor WebAssembly๊ฐ ๋ญ์ง ๋์ถฉ ๊ฐ์ด ์ค์๋์? ๊ทธ๋ผ ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ฐ๋ฐ์ ์์ํด๋ณผ๊น์? ๊ทผ๋ฐ ๊ทธ์ ์ ์ ๊น! Blazor WebAssembly๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ์ค๋น๋ฌผ๋ค์ด ์์ด์. ๋ค์ ์น์ ์์ ์์๋ณด๋๋ก ํด์!
์์ ๊ทธ๋ฆผ์ ๋ณด๋ฉด Blazor WebAssembly์ ์ฃผ์ ๊ตฌ์ฑ ์์๋ค์ ํ๋์ ๋ณผ ์ ์์ด์. C#, .NET, WebAssembly, ๊ทธ๋ฆฌ๊ณ ๋ธ๋ผ์ฐ์ ๊ฐ ๋ง๋ ๋ฉ์ง ํ๋ชจ๋๋ฅผ ์ด๋ฃจ๊ณ ์์ฃ ? ์ด๊ฒ ๋ฐ๋ก Blazor WebAssembly์ ๋งค๋ ฅ์ด์์! ๐
๐ ๏ธ Blazor WebAssembly ๊ฐ๋ฐ ์ค๋นํ๊ธฐ ๐ ๏ธ
์, ์ด์ Blazor WebAssembly๋ก ๊ฐ๋ฐ์ ์์ํ๊ธฐ ์ํ ์ค๋น๋ฅผ ํด๋ณผ๊น์? ๊ฑฑ์ ๋ง์ธ์, ์ด๋ ต์ง ์์์! ใ ใ ใ
1. .NET SDK ์ค์นํ๊ธฐ
๊ฐ์ฅ ๋จผ์ ํด์ผ ํ ์ผ์ .NET SDK๋ฅผ ์ค์นํ๋ ๊ฑฐ์์. Blazor WebAssembly๋ .NET 5.0 ์ด์์ ์ง์ํด์. ์ต์ ๋ฒ์ ์ ์ค์นํ๋ ๊ฒ ์ข๊ฒ ์ฃ ?
๋ง์ดํฌ๋ก์ํํธ ๊ณต์ ์ฌ์ดํธ์์ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์ด์. ์ค์น๋ ์ ๋ง ์ฌ์์. ๋ค์ด๋ก๋ ๋ฐ์ ํ์ผ์ ์คํํ๊ณ '๋ค์'๋ง ๊ณ์ ๋๋ฌ์ฃผ๋ฉด ๋ผ์. ๋ญ๊ฐ ์ด๋ ค์ด ๊ฒ ๋์ค๋ฉด ๋นํฉํ์ง ๋ง์๊ณ ๊ทธ๋ฅ '์'๋ฅผ ๋๋ฅด์ธ์. ใ ใ ใ
๐ก ํ: ์ค์น๊ฐ ์๋ฃ๋๋ฉด ๋ช
๋ น ํ๋กฌํํธ๋ PowerShell์ ์ด๊ณ dotnet --version
์ ์
๋ ฅํด๋ณด์ธ์. ๋ฒ์ ์ ๋ณด๊ฐ ๋์ค๋ฉด ์ค์น๊ฐ ์ ๋ ๊ฑฐ์์!
2. Visual Studio Code ์ค์นํ๊ธฐ
๋ค์์ผ๋ก ํ์ํ ๊ฑด ์ฝ๋ ์๋ํฐ์์. Visual Studio Code๋ฅผ ์ถ์ฒํ ๊ฒ์. ๋ฌด๋ฃ์ด๋ฉด์๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ฑฐ๋ ์. ๊ฒ๋ค๊ฐ Blazor ๊ฐ๋ฐ์ ์ํ ํ์ฅ ํ๋ก๊ทธ๋จ๋ ์์ด์!
Visual Studio Code ๊ณต์ ์ฌ์ดํธ์์ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์ด์. ์ด๊ฒ๋ ์ค์น๋ ์ ๋ง ๊ฐ๋จํด์. ๋ค์ด๋ก๋ ๋ฐ์ ํ์ผ์ ์คํํ๊ณ ... ๋ค, ๋ง์์. '๋ค์'๋ง ๊ณ์ ๋๋ฅด๋ฉด ๋ผ์. ใ ใ ใ
3. C# ํ์ฅ ํ๋ก๊ทธ๋จ ์ค์นํ๊ธฐ
Visual Studio Code์์ C# ๊ฐ๋ฐ์ ๋ ํธํ๊ฒ ํ๋ ค๋ฉด C# ํ์ฅ ํ๋ก๊ทธ๋จ์ ์ค์นํด์ผ ํด์. ์ด๊ฑด ์ ๋ง ์ฌ์์!
- Visual Studio Code๋ฅผ ์คํํด์.
- ์ผ์ชฝ ์ฌ์ด๋๋ฐ์์ ํ์ฅ ํ๋ก๊ทธ๋จ ์์ด์ฝ(๋ค๋ชจ ๋ค ๊ฐ๊ฐ ๋ถ์ด์๋ ๋ชจ์)์ ํด๋ฆญํด์.
- ๊ฒ์์ฐฝ์ 'C#'์ ์ ๋ ฅํด์.
- ๋งจ ์์ ๋์ค๋ 'C#' ํ์ฅ ํ๋ก๊ทธ๋จ์ ์ฐพ์ 'Install' ๋ฒํผ์ ํด๋ฆญํด์.
์ง์~ ์ด์ C# ํ์ฅ ํ๋ก๊ทธ๋จ์ด ์ค์น๋์์ด์! ๐
4. Blazor WebAssembly ํ ํ๋ฆฟ ์ค์นํ๊ธฐ
๋ง์ง๋ง์ผ๋ก Blazor WebAssembly ํ๋ก์ ํธ ํ ํ๋ฆฟ์ ์ค์นํด์ผ ํด์. ์ด๊ฑด ๋ช ๋ น ํ๋กฌํํธ๋ PowerShell์์ ๊ฐ๋จํ ๋ช ๋ น์ด๋ก ํ ์ ์์ด์.
dotnet new -i Microsoft.AspNetCore.Components.WebAssembly.Templates::5.0.0
์ด ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด Blazor WebAssembly ํ ํ๋ฆฟ์ด ์ค์น๋ผ์. ์ด์ ์๋ก์ด Blazor WebAssembly ํ๋ก์ ํธ๋ฅผ ๋ง๋ค ์ค๋น๊ฐ ๋ ๊ฑฐ์์!
๐ ์ฌ๋ฏธ์๋ ์ฌ์ค: Blazor WebAssembly๋ ์ฒ์์๋ ์คํ์ ์ธ ํ๋ก์ ํธ๋ก ์์ํ์ด์. ํ์ง๋ง ๊ฐ๋ฐ์๋ค์ ๋จ๊ฑฐ์ด ๊ด์ฌ ๋๋ถ์ ์ ์ ํ๋ ์์ํฌ๋ก ๋ฐ์ ํ์ฃ . ์ด๊ฒ ๋ฐ๋ก ๊ฐ๋ฐ์ ํ์! ๐ช
์, ์ด์ ๋ชจ๋ ์ค๋น๊ฐ ๋๋ฌ์ด์! ์ด๋์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ ์ด์ ์ง์ง ๊ฐ๋ฐ์ ์์ํ ์ค๋น๊ฐ ๋์์ด์. ๋ค์ ์น์ ์์๋ ์ค์ ๋ก Blazor WebAssembly ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ๐
์ ๊ทธ๋ฆผ์ Blazor WebAssembly ๊ฐ๋ฐ์ ์ํ ์ค๋น ๊ณผ์ ์ ๋ณด์ฌ์ฃผ๊ณ ์์ด์. ๊ฐ ๋จ๊ณ๋ฅผ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐ๋ผ๊ฐ๋ค ๋ณด๋ฉด ์ด๋์ ๊ฐ๋ฐ ์ค๋น ์๋ฃ! ๐
๐ ์ฒซ Blazor WebAssembly ํ๋ก์ ํธ ๋ง๋ค๊ธฐ ๐
๋๋์ด ์ฒซ Blazor WebAssembly ํ๋ก์ ํธ๋ฅผ ๋ง๋ค ์๊ฐ์ด์์! ์ ๋ง ์ค๋ ์ง ์๋์? ใ ใ ใ ์, ๊ทธ๋ผ ์์ํด๋ณผ๊น์?
1. ํ๋ก์ ํธ ์์ฑํ๊ธฐ
๋จผ์ ๋ช ๋ น ํ๋กฌํํธ๋ PowerShell์ ์ด๊ณ , ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๊ณ ์ถ์ ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํด์ฃผ์ธ์. ๊ทธ๋ฆฌ๊ณ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํด๋ณผ๊น์?
dotnet new blazorwasm -o MyFirstBlazorApp
์ด ๋ช ๋ น์ด๋ 'MyFirstBlazorApp'์ด๋ผ๋ ์ด๋ฆ์ ์๋ก์ด Blazor WebAssembly ํ๋ก์ ํธ๋ฅผ ์์ฑํด์. '-o' ์ต์ ์ output์ ์ฝ์๋ก, ํ๋ก์ ํธ ํด๋์ ์ด๋ฆ์ ์ง์ ํ๋ ๊ฑฐ์์.
๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ์ ์ ๊ธฐ๋ค๋ฆฌ์ธ์. ๋ญ๊ฐ ์ด์ฌํ ๋ค์ด๋ก๋ํ๊ณ ์ค์นํ๋ ๊ฒ ๋ณด์ผ ๊ฑฐ์์. ๊ธฐ๋ค๋ฆฌ๋ ๋์ ์ปคํผ ํ ์ ์ด๋์? โ
๐ก ํ: ํ๋ก์ ํธ ์ด๋ฆ์ ๋ง์๋๋ก ์ง์ด๋ ๋ผ์. 'MyAwesomeBlazorApp'์ด๋ผ๊ณ ํด๋ ๋๊ณ , 'ILoveBlazor'๋ผ๊ณ ํด๋ ๋ผ์. ๊ทผ๋ฐ ๋๋ฌด ๊ธธ๋ฉด ๋์ค์ ํ์ดํํ๊ธฐ ํ๋ค์ด์. ใ ใ ใ
2. ํ๋ก์ ํธ ๊ตฌ์กฐ ์ดํด๋ณด๊ธฐ
ํ๋ก์ ํธ ์์ฑ์ด ์๋ฃ๋๋ฉด, Visual Studio Code๋ฅผ ์ด๊ณ ๋ฐฉ๊ธ ๋ง๋ ํ๋ก์ ํธ ํด๋๋ฅผ ์ด์ด๋ณผ๊น์? 'File' > 'Open Folder'๋ฅผ ์ ํํ๊ณ 'MyFirstBlazorApp' ํด๋๋ฅผ ์ ํํ์ธ์.
์ผ์ชฝ ์ฌ์ด๋๋ฐ์ ํ๋ก์ ํธ ๊ตฌ์กฐ๊ฐ ๋ณด์ผ ๊ฑฐ์์. ์ด๋ค๊ฐ์? ๋ญ๊ฐ ๋ณต์กํด ๋ณด์ด๋์? ๊ฑฑ์ ๋ง์ธ์. ํ๋์ฉ ์ดํด๋ณผ ํ ๋๊น์!
- ๐ Pages: ์ฌ๊ธฐ์ Razor ์ปดํฌ๋ํธ๋ค์ด ์์ด์. ์น ํ์ด์ง์ ๋ด์ฉ์ ๋ด๋นํ์ฃ .
- ๐ Shared: ์ฌ๋ฌ ํ์ด์ง์์ ๊ณต์ ํ๋ ์ปดํฌ๋ํธ๋ค์ด ์์ด์. ์๋ฅผ ๋ค๋ฉด ๋ค๋น๊ฒ์ด์ ๋ฉ๋ด ๊ฐ์ ๊ฑฐ์ฃ .
- ๐ Program.cs: ์ ํ๋ฆฌ์ผ์ด์ ์ ์ง์ ์ ์ด์์. ์ฌ๊ธฐ์ ์ฑ์ ์์ํ๊ณ ํ์ํ ์๋น์ค๋ค์ ๊ตฌ์ฑํด์.
- ๐ _Imports.razor: ์์ฃผ ์ฌ์ฉํ๋ ๋ค์์คํ์ด์ค๋ฅผ ๋ฏธ๋ฆฌ ์ ์ธํด๋๋ ํ์ผ์ด์์.
- ๐ wwwroot/index.html: ๋ฉ์ธ HTML ํ์ผ์ด์์. Blazor ์ฑ์ด ์ฌ๊ธฐ์ ๋ก๋๋ผ์.
์ด๋์? ์๊ฐ๋ณด๋ค ๋จ์ํ์ฃ ? ใ ใ ใ
3. ํ๋ก์ ํธ ์คํํ๊ธฐ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ํ๋ก์ ํธ๋ฅผ ์คํํด๋ณผ ์ฐจ๋ก์์! ํฐ๋ฏธ๋์ ์ด๊ณ (Visual Studio Code์์๋ Ctrl+` ๋ฅผ ๋๋ฅด๋ฉด ๋ผ์) ๋ค์ ๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํด๋ณด์ธ์.
dotnet run
์ ์ ๊ธฐ๋ค๋ฆฌ๋ฉด ์ฝ์์ ๋ญ๊ฐ ์ฃผ๋ฃจ๋ฃฉ ๋์ค๊ณ , ๋ง์ง๋ง์ URL์ด ๋ณด์ผ ๊ฑฐ์์. ๋ณดํต https://localhost:5001
์ด๋ฐ ์์ด์์. ์ด URL์ ๋ธ๋ผ์ฐ์ ์ ์
๋ ฅํด๋ณด์ธ์!
์ง์~ ๐ ์ถํํด์! ์ฌ๋ฌ๋ถ์ ์ฒซ Blazor WebAssembly ์ฑ์ด ์คํ๋์์ด์!
๐ ์ฌ๋ฏธ์๋ ์ฌ์ค: Blazor WebAssembly ์ฑ์ด ์ฒ์ ๋ก๋๋ ๋๋ ์กฐ๊ธ ์๊ฐ์ด ๊ฑธ๋ฆด ์ ์์ด์. ์๋ํ๋ฉด .NET ๋ฐํ์๊ณผ ์ฑ ์ฝ๋๋ฅผ ๋ชจ๋ ๋ค์ด๋ก๋ํด์ผ ํ๊ฑฐ๋ ์. ํ์ง๋ง ํ ๋ฒ ๋ก๋๋๋ฉด ๊ทธ ๋ค์๋ถํฐ๋ ์์ฒญ ๋นจ๋ผ์ ธ์! ๋ง์น ์ฒ์์๋ ๋๋ฆฌ์ง๋ง ๋์ค์ ์์ฒญ ๋นจ๋ผ์ง๋ ๊ฑฐ๋ถ์ด ๊ฐ์์. ใ ใ ใ
4. ๊ธฐ๋ณธ ๊ตฌ์กฐ ์ดํด๋ณด๊ธฐ
๋ธ๋ผ์ฐ์ ์ ๋ํ๋ ํ์ด์ง๋ฅผ ์ดํด๋ณผ๊น์? ๊ธฐ๋ณธ์ ์ผ๋ก ์ธ ๊ฐ์ ํ์ด์ง๊ฐ ์์ด์.
- ๐ Home: ๋ฉ์ธ ํ์ด์ง์์. "Hello, world!"๋ผ๊ณ ๋ฐ๊ฒจ์ฃผ๊ณ ์์ฃ ?
- ๐ Counter: ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์ซ์๊ฐ ์ฌ๋ผ๊ฐ๋ ๊ฐ๋จํ ์นด์ดํฐ์์.
- ๐ค๏ธ Weather: ๊ฐ์ง ๋ ์จ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ฌ์ฃผ๋ ํ์ด์ง์์.
์ด ํ์ด์ง๋ค์ ๊ฐ๊ฐ Pages
ํด๋ ์์ ์๋ Index.razor
, Counter.razor
, FetchData.razor
ํ์ผ์ ํด๋นํด์.
์ด๋์? ์๊ฐ๋ณด๋ค ๋จ์ํ์ฃ ? ์ด๊ฒ ๋ฐ๋ก Blazor WebAssembly์ ๋งค๋ ฅ์ด์์. ๋ณต์กํ JavaScript ์ฝ๋ ์์ด๋ ์ด๋ฐ ๋์ ์ธ ์น ํ์ด์ง๋ฅผ ๋ง๋ค ์ ์๋ค๋! ๐
์ ๊ทธ๋ฆผ์ Blazor WebAssembly ์ฑ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ฃผ๊ณ ์์ด์. ์ธ ๊ฐ์ ์ฃผ์ ํ์ด์ง๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด ์๋์ง ํ๋์ ๋ณผ ์ ์์ฃ ?
์, ์ด์ ์ฐ๋ฆฌ์ ์ฒซ Blazor WebAssembly ์ฑ์ด ์คํ๋๊ณ ์์ด์! ์ด๋ค๊ฐ์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ ์ด์ ์ด ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๋ฐํ์ผ๋ก ์ฐ๋ฆฌ๋ง์ ๋ฉ์ง SPA๋ฅผ ๋ง๋ค์ด ๋๊ฐ ์ ์์ด์. ๋ค์ ์น์ ์์๋ ์ด ์ฑ์ ์กฐ๊ธ์ฉ ์์ ํด๋ณด๋ฉด์ Blazor WebAssembly์ ๋ ๋ง์ ๊ธฐ๋ฅ๋ค์ ์์๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ๐
๊ทธ๋ฆฌ๊ณ ์ ๊น! ํน์ ์ฌ๋ฌ๋ถ์ด ์ฌ๋ฅ๋ท์ด๋ผ๋ ์ฌ์ดํธ๋ฅผ ์๊ณ ๊ณ์ ๊ฐ์? ์ฌ๋ฅ๋ท์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฑฐ๋ํ ์ ์๋ ํ๋ซํผ์ธ๋ฐ์, ๋ง์ฝ ์ฌ๋ฌ๋ถ์ด Blazor WebAssembly ๊ฐ๋ฐ ์ค๋ ฅ์ ์์์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๋์์ ์ฃผ๊ณ ์ถ๋ค๋ฉด ์ฌ๋ฅ๋ท์์ ํ๋ํด๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด ๋ ์ ์์ด์. ๊ฐ๋ฐ์๋ค๋ผ๋ฆฌ ์ง์์ ๊ณต์ ํ๊ณ ์๋ก ๋์์ ์ฃผ๊ณ ๋ฐ๋ ๊ฑด ์ ๋ง ๋ฉ์ง ์ผ์ด์์์? ๐
๐ ๏ธ Blazor WebAssembly ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ ๐ ๏ธ
์, ์ด์ ์ฐ๋ฆฌ๋ง์ Blazor WebAssembly ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์์. ์ปดํฌ๋ํธ๊ฐ ๋ญ์ง ๋ชจ๋ฅด๊ฒ ๋ค๊ณ ์? ๊ฑฑ์ ๋ง์ธ์! ์ฝ๊ฒ ์ค๋ช ํด๋๋ฆด๊ฒ์. ใ ใ ใ
1. ์ปดํฌ๋ํธ๋?
์ปดํฌ๋ํธ๋ UI์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๋ถ๋ถ์ด์์. ์๋ฅผ ๋ค์ด, ๋ฒํผ, ํผ, ๋ํ ์์ ๋ฑ์ด ๋ชจ๋ ์ปดํฌ๋ํธ๊ฐ ๋ ์ ์์ด์. Blazor์์๋ ์ด๋ฐ ์ปดํฌ๋ํธ๋ฅผ C#๊ณผ HTML์ ์์ด์ ๋ง๋ค ์ ์์ด์. ์ ๋ง ํธ๋ฆฌํ์ฃ ?
๐ก ํ: ์ปดํฌ๋ํธ๋ฅผ ๋ ๊ณ ๋ธ๋ก์ด๋ผ๊ณ ์๊ฐํด๋ณด์ธ์. ๊ฐ๊ฐ์ ๋ธ๋ก์ ๋ ๋ฆฝ์ ์ด์ง๋ง, ์ด๋ค์ ์กฐํฉํด์ ๋ฉ์ง ์ํ์ ๋ง๋ค ์ ์์ฃ . ์ปดํฌ๋ํธ๋ ๋ง์ฐฌ๊ฐ์ง์์!
2. ์ฒซ ๋ฒ์งธ ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
์, ์ด์ ์ฐ๋ฆฌ์ ์ฒซ ๋ฒ์งธ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์? 'Greeting'์ด๋ผ๋ ๊ฐ๋จํ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์์.
- Visual Studio Code์์ 'Pages' ํด๋์ ์ฐํด๋ฆญํ๊ณ 'New File'์ ์ ํํ์ธ์.
- ํ์ผ ์ด๋ฆ์ 'Greeting.razor'๋ก ์ง์ ํ์ธ์.
- ๋ค์ ์ฝ๋๋ฅผ ์ ๋ ฅํด๋ณด์ธ์:
@page "/greeting"
<h3>Hello, Blazor!</h3>
<p>Welcome to your new app.</p>
@code {
// ์ฌ๊ธฐ์ C# ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ด์.
}
์ง์~ ์ฐ๋ฆฌ์ ์ฒซ ๋ฒ์งธ ์ปดํฌ๋ํธ๊ฐ ์์ฑ๋์์ด์! ๐
3. ์ปดํฌ๋ํธ ์ดํดํ๊ธฐ
๋ฐฉ๊ธ ๋ง๋ ์ปดํฌ๋ํธ๋ฅผ ์์ธ ํ ์ดํด๋ณผ๊น์?
@page "/greeting"
: ์ด ์ค์ ๋ผ์ฐํ ์ ์ ์ํด์. ์ด ์ปดํฌ๋ํธ๊ฐ '/greeting' URL์์ ๋ณด์ฌ์ง ๊ฑฐ๋ผ๋ ๋ป์ด์์.
: ์ด๊ฑด ๊ทธ๋ฅ HTML์ด์์. Blazor์์๋ HTML์ ์ง์ ์ฌ์ฉํ ์ ์์ด์.Hello, Blazor!
@code { ... }
: ์ฌ๊ธฐ์ C# ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ด์. ์ปดํฌ๋ํธ์ ๋ก์ง์ ๋ด๋นํ์ฃ .
4. ์ปดํฌ๋ํธ์ ๋งค๊ฐ๋ณ์ ์ถ๊ฐํ๊ธฐ
์ด์ ์ฐ๋ฆฌ์ ์ปดํฌ๋ํธ๋ฅผ ์กฐ๊ธ ๋ ๋๋ํ๊ฒ ๋ง๋ค์ด๋ณผ๊น์? ์ด๋ฆ์ ๋ฐ์์ ์ธ์ฌํ ์ ์๊ฒ ํด๋ณผ ๊ฑฐ์์.
'Greeting.razor' ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด๋ณด์ธ์:
@page "/greeting"
@page "/greeting/{Name}"
<h3>Hello, @Name!</h3>
<p>Welcome to your new app.</p>
@code {
[Parameter]
public string Name { get; set; } = "Blazor";
}
์์ฐ! ์ด์ ์ฐ๋ฆฌ์ ์ปดํฌ๋ํธ๊ฐ ํจ์ฌ ๋ ์ ์ฐํด์ก์ด์. ์ด๋ค ์ ์ด ๋ฐ๋์๋์ง ๋ณผ๊น์?
- ๋ ๊ฐ์
@page
์ง์๋ฌธ์ด ์์ด์. ์ด์ '/greeting'๊ณผ '/greeting/SomeName' ๋ ๋ค ์ด ์ปดํฌ๋ํธ๋ก ์ฐ๊ฒฐ๋ผ์. [Parameter]
์์ฑ์ด ๋ถ์Name
ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ์ด์. ์ด๋ ๊ฒ ํ๋ฉด URL์์ ์ด๋ฆ์ ๋ฐ์์ฌ ์ ์์ด์.Hello, @Name!
์์@Name
์ C# ์ฝ๋์Name
ํ๋กํผํฐ ๊ฐ์ ์ถ๋ ฅํด์.
๐ ์ฌ๋ฏธ์๋ ์ฌ์ค: Blazor์ '@' ๊ธฐํธ๋ ๋ง๋ฒ์ ์งํก์ด ๊ฐ์์. HTML ์์์ C# ์ฝ๋๋ฅผ ์คํํ๊ฒ ํด์ฃผ๊ฑฐ๋ ์. ๋ง์น ํด๋ฆฌํฌํฐ๊ฐ "์๊ฐ๋ฅด๋์ ๋ ๋น์ค์ฌ~" ํ๋ ๊ฒ์ฒ๋ผ, ์ฐ๋ฆฌ๋ "@"๋ฅผ ์ฌ์ฉํด์ HTML์ ๋ง๋ฒ์ ๊ฑธ์ด์! ใ ใ ใ
5. ์ปดํฌ๋ํธ ์ฌ์ฉํ๊ธฐ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด๋ณผ๊น์? 'Pages/Index.razor' ํ์ผ์ ์ด๊ณ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด๋ณด์ธ์:
@page "/"
<h1>Welcome to Blazor!</h1>
<greeting></greeting>
<greeting name="Alice"></greeting>
์ด์ ์ฑ์ ์คํํ๊ณ ํํ์ด์ง๋ก ๊ฐ๋ณด์ธ์. ์ด๋ค๊ฐ์? ์ฐ๋ฆฌ์ Greeting ์ปดํฌ๋ํธ๊ฐ ๋ ๋ฒ ๋ํ๋์ฃ ? ํ๋๋ ๊ธฐ๋ณธ ์ด๋ฆ "Blazor"๋ก, ๋ค๋ฅธ ํ๋๋ "Alice"๋ผ๋ ์ด๋ฆ์ผ๋ก ์ธ์ฌํ๊ณ ์์ด์.
6. ๋์ ์ปดํฌ๋ํธ ๋ง๋ค๊ธฐ
๋ง์ง๋ง์ผ๋ก, ์ฐ๋ฆฌ์ ์ปดํฌ๋ํธ๋ฅผ ์กฐ๊ธ ๋ ๋์ ์ผ๋ก ๋ง๋ค์ด๋ณผ๊น์? ์ฌ์ฉ์๊ฐ ์ด๋ฆ์ ์ ๋ ฅํ ์ ์๊ฒ ํด๋ณผ ๊ฑฐ์์.
'Greeting.razor' ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ ํด๋ณด์ธ์:
@page "/greeting"
@page "/greeting/{Name}"
<h3>Hello, @Name!</h3>
<p>Welcome to your new app.</p>
<input placeholder="Enter your name">
@code {
[Parameter]
public string Name { get; set; } = "Blazor";
}
์ด์ ๋ญ๊ฐ ๋ฌ๋ผ์ก๋์ง ๋ณผ๊น์?
: ์ด ์ ๋ ฅ ํ๋๋
Name
ํ๋กํผํฐ์ ์๋ฐฉํฅ ๋ฐ์ธ๋ฉ๋ผ์.- ์ฌ์ฉ์๊ฐ ์ด๋ฆ์ ์ ๋ ฅํ๋ฉด, ์ธ์ฌ๋ง์ด ์ฆ์ ์ ๋ฐ์ดํธ๋ผ์. ์ ๋ง ๋ฉ์ง์ฃ ?
์์ฐ! ์ด์ ์ฐ๋ฆฌ๋ ์ง์ง ๋์ ์ธ Blazor WebAssembly ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์์ด์. ์ด๋ค๊ฐ์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ
์ ๊ทธ๋ฆผ์ Blazor WebAssembly ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฌ์ค์. HTML ํ ํ๋ฆฟ๊ณผ C# ์ฝ๋๊ฐ '@' ๊ธฐํธ๋ก ์ฐ๊ฒฐ๋์ด ์์ฃ . ์ด๊ฒ ๋ฐ๋ก Blazor์ ๋ง๋ฒ์ด์์! ๐
์, ์ด์ ์ฌ๋ฌ๋ถ์ Blazor WebAssembly ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ์ ๋ง์คํฐํ์ด์! ๐๐๐ ์ด๊ฑธ ๋ฐํ์ผ๋ก ๋ ๋ณต์กํ๊ณ ๋ฉ์ง ์ปดํฌ๋ํธ๋ค์ ๋ง๋ค ์ ์์ ๊ฑฐ์์. ์๋ฅผ ๋ค์ด, ํฌ๋ ๋ฆฌ์คํธ, ๋ ์จ ์์ ฏ, ํน์ ๊ฐ๋จํ ๊ฒ์๋ ๋ง๋ค ์ ์์ฃ .
๊ทธ๋ฆฌ๊ณ ๊ธฐ์ตํ์ธ์. ๊ฐ๋ฐ์ ์ฐ์ต์ด ์ค์ํด์. ๊ณ์ ์๋ก์ด ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค๊ณ ์คํํด๋ณด์ธ์. ๊ทธ๋ฌ๋ค ๋ณด๋ฉด ์ด๋์ ์ฌ๋ฌ๋ถ์ Blazor WebAssembly ์ ๋ฌธ๊ฐ๊ฐ ๋์ด ์์ ๊ฑฐ์์! ๐
๋ค์ ์น์ ์์๋ Blazor WebAssembly์์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ๐
๐ Blazor WebAssembly์์ ๋ฐ์ดํฐ ๋ค๋ฃจ๊ธฐ ๐
์, ์ด์ ์ฐ๋ฆฌ์ Blazor WebAssembly ์ฑ์์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๋ฐฉ๋ฒ์ ์์๋ณผ ๊ฑฐ์์. ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฑด ๋ชจ๋ ์ฑ์ ํต์ฌ์ด์ฃ . ์ค๋น๋์ จ๋์? ๊ณ ๊ณ ์ฝ~! ๐
1. ์ํ ๊ด๋ฆฌ ์ดํดํ๊ธฐ
Blazor WebAssembly์์ '์ํ'๋ ๋ญ๊น์? ๊ฐ๋จํ ๋งํด์, ์ฑ์ด ๊ธฐ์ตํ๊ณ ์๋ ๋ฐ์ดํฐ์์. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ด๋ฆ, ์ฅ๋ฐ๊ตฌ๋ ๋ด์ฉ, ๊ฒ์ ์ ์ ๋ฑ์ด ๋ชจ๋ ์ํ๊ฐ ๋ ์ ์์ด์.
Blazor์์๋ ์ปดํฌ๋ํธ์ ํ๋๋ ํ๋กํผํฐ๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ ์ ์์ด์. ์๋ฅผ ๋ค์ด๋ณผ๊น์?
@code {
private int count = 0; // ์ด๊ฒ ์ํ์์!
private void IncrementCount()
{
count++; // ์ํ๋ฅผ ๋ณ๊ฒฝํด์
}
}
์ฌ๊ธฐ์ count
๊ฐ ๋ฐ๋ก ์ํ์์. IncrementCount
๋ฉ์๋๋ ์ด ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ณ ์์ฃ .
2. ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ์ฌ์ฉํ๊ธฐ
Blazor์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ ์ค ํ๋๋ ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ด์์. ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ์ฌ์ฉํ๋ฉด C# ์ฝ๋์ ๋ฐ์ดํฐ์ HTML์ ์ฝ๊ฒ ์ฐ๊ฒฐํ ์ ์์ด์.
์๋ฅผ ๋ค์ด๋ณผ๊น์? ๋ค์๊ณผ ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด๋ณด์ธ์:
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
์ฌ๊ธฐ์ @currentCount
๋ C# ์ฝ๋์ currentCount
๋ณ์ ๊ฐ์ HTML์ ํ์ํด์. ๊ทธ๋ฆฌ๊ณ @onclick="IncrementCount"
๋ ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ C# ๋ฉ์๋์ ์ฐ๊ฒฐํด์. ์ ๋ง ํธ๋ฆฌํ์ฃ ? ใ
ใ
ใ
๐ก ํ: ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ์ ๋ง์น ๋ง๋ฒ์ ๋ ๊ฐ์์. C# ์ฝ๋์ HTML์ ๋จ๋จํ ์ฐ๊ฒฐํด์ฃผ์ฃ . ์ด ๋ ๋๋ถ์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉด UI๊ฐ ์๋์ผ๋ก ์ ๋ฐ์ดํธ๋ผ์. ์ ๋ง ํธ๋ฆฌํ์ฃ ?
3. HTTP ์์ฒญ์ผ๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
์ค์ ์ฑ์์๋ ๋๋ถ๋ถ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํด์. Blazor WebAssembly์์๋ HttpClient
๋ฅผ ์ฌ์ฉํด HTTP ์์ฒญ์ ๋ณด๋ผ ์ ์์ด์.
์๋ฅผ ๋ค์ด, ๊ฐ์ง ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด๋ณผ๊น์?
@page "/users"
@inject HttpClient Http
<h1>Users</h1>
@if (users == null)
{
<p>Loading...</p>
}
else
{
<ul>
@foreach (var user in users)
{
<li>@user.Name</li>
}
</ul>
}
@code {
private User[] users;
protected override async Task OnInitializedAsync()
{
users = await Http.GetFromJsonAsync<user>("https://jsonplaceholder.typicode.com/users");
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
}
</user>
์ด ์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ ์ผ์ ํด์:
@inject HttpClient Http
๋กHttpClient
๋ฅผ ์ฃผ์ ๋ฐ์์.OnInitializedAsync
๋ฉ์๋์์ HTTP GET ์์ฒญ์ ๋ณด๋ด ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์.- ๋ฐ์ดํฐ ๋ก๋ฉ ์ค์๋ "Loading..."์ ํ์ํ๊ณ , ๋ก๋ฉ์ด ์๋ฃ๋๋ฉด ์ฌ์ฉ์ ๋ชฉ๋ก์ ๋ณด์ฌ์ค์.
์ด๋์? ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ๋ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์์ฃ ? ใ ใ ใ
4. ํผ ๋ค๋ฃจ๊ธฐ
์น ์ฑ์์ ํผ์ ์ ๋ง ์ค์ํด์. Blazor์์๋ ํผ์ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์์ด์. ๊ฐ๋จํ ๋ก๊ทธ์ธ ํผ์ ๋ง๋ค์ด๋ณผ๊น์?
@page "/login"
<h3>Login</h3>
<editform model="@loginModel" onvalidsubmit="HandleValidSubmit">
<dataannotationsvalidator></dataannotationsvalidator>
<validationsummary></validationsummary>
<div class="form-group">
<label for="username">Username:</label>
<inputtext id="username" class="form-control"></inputtext>
<validationmessage for="@(() => loginModel.Username)"></validationmessage>
</div>
<div class="form-group">
<label for="password">Password:</label>
<inputtext id="password" class="form-control" type="password"></inputtext>
<validationmessage for="@(() => loginModel.Password)"></validationmessage>
</div>
<button type="submit" class="btn btn-primary">Login</button>
</editform>
@code {
private LoginModel loginModel = new LoginModel();
private void HandleValidSubmit()
{
Console.WriteLine($"Login attempt: {loginModel.Username}");
// ์ฌ๊ธฐ์ ์ค์ ๋ก๊ทธ์ธ ๋ก์ง์ ๊ตฌํํ๋ฉด ๋ผ์
}
public class LoginModel
{
[Required]
public string Username { get; set; }
[Required]
[StringLength(100, MinimumLength = 6)]
public string Password { get; set; }
}
}
์ด ์ปดํฌ๋ํธ๋ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ด ์์ด์:
EditForm
์ ์ฌ์ฉํด ํผ์ ๋ง๋ค์ด์.DataAnnotationsValidator
๋ก ์ ๋ ฅ๊ฐ์ ๊ฒ์ฆํด์.InputText
๋ก ํ ์คํธ ์ ๋ ฅ ํ๋๋ฅผ ๋ง๋ค๊ณ ,@bind-Value
๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ธ๋ฉํด์.ValidationMessage
๋ก ๊ฐ ํ๋์ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฉ์์ง๋ฅผ ํ์ํด์.
์์ฐ! ์ด์ ์ฐ๋ฆฌ๋ Blazor WebAssembly์์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ๋ค์ ๋ฐฐ์ ์ด์. ์ด๋ค๊ฐ์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ
์ ๊ทธ๋ฆผ์ Blazor WebAssembly์์์ ๋ฐ์ดํฐ ํ๋ฆ์ ๋ณด์ฌ์ค์. ์ปดํฌ๋ํธ๊ฐ ์๋ฒ์ HTTP ์์ฒญ์ ๋ณด๋ด๊ณ , ์๋ฒ๊ฐ ์๋ต์ ๋ณด๋ด๋ฉด ์ปดํฌ๋ํธ๊ฐ ๊ทธ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํด UI๋ฅผ ์ ๋ฐ์ดํธํ์ฃ . ๊ฐ๋จํ์ฃ ? ใ ใ ใ
์, ์ด์ ์ฌ๋ฌ๋ถ์ Blazor WebAssembly์์ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ๋ค์ ์๊ฒ ๋์์ด์. ์ด๊ฑธ ๋ฐํ์ผ๋ก ๋ ๋ณต์กํ๊ณ ๋ฉ์ง ์ฑ์ ๋ง๋ค ์ ์์ ๊ฑฐ์์. ์๋ฅผ ๋ค์ด, ์จ๋ผ์ธ ์ผํ๋ชฐ, ์์ ๋ฏธ๋์ด ์ฑ, ํน์ ๋ณต์กํ ๋์๋ณด๋๋ ๋ง๋ค ์ ์์ฃ .
๊ทธ๋ฆฌ๊ณ ๊ธฐ์ตํ์ธ์. ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฑด ์ฐ์ต์ด ํ์ํด์. ๊ณ์ ์๋ก์ด ๊ธฐ๋ฅ์ ๋ง๋ค๊ณ ์คํํด๋ณด์ธ์. ๊ทธ๋ฌ๋ค ๋ณด๋ฉด ์ด๋์ ์ฌ๋ฌ๋ถ์ Blazor WebAssembly ๋ฐ์ดํฐ ๋ง์ ์ฌ๊ฐ ๋์ด ์์ ๊ฑฐ์์! ๐งโโ๏ธ
๋ค์ ์น์ ์์๋ Blazor WebAssembly ์ฑ์ ์ต์ ํํ๊ณ ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณผ ๊ฑฐ์์. ๊ธฐ๋๋์ง ์๋์? ๐
๐ Blazor WebAssembly ์ฑ ์ต์ ํ ๋ฐ ๋ฐฐํฌํ๊ธฐ ๐
๋๋์ด ์ฐ๋ฆฌ์ Blazor WebAssembly ์ฑ์ด ์์ฑ๋์์ด์! ๐ ์ด์ ์ด ์ฑ์ ์ต์ ํํ๊ณ ์ธ์์ ๊ณต๊ฐํ ์ฐจ๋ก์์. ์ค๋น๋์ จ๋์? ์ถ๋ฐ~! ๐โโ๏ธ๐จ
1. ์ฑ ์ต์ ํํ๊ธฐ
Blazor WebAssembly ์ฑ์ ์ต์ ํํ๋ ๋ช ๊ฐ์ง ํ์ ์์๋ณผ๊น์?
- ๋ ์ด์ง ๋ก๋ฉ ์ฌ์ฉํ๊ธฐ: ๋ชจ๋ ์ปดํฌ๋ํธ๋ฅผ ํ ๋ฒ์ ๋ก๋ํ์ง ๋ง๊ณ , ํ์ํ ๋ ๋ก๋ํ์ธ์.
- ํธ๋ฆฌ ์์ดํน ํ์ฉํ๊ธฐ: ์ฌ์ฉํ์ง ์๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํด ์ฑ ํฌ๊ธฐ๋ฅผ ์ค์ผ ์ ์์ด์.
- ์์ถ ์ฌ์ฉํ๊ธฐ: Brotli๋ gzip ์์ถ์ ์ฌ์ฉํด ์ ์ก๋๋ ๋ฐ์ดํฐ ํฌ๊ธฐ๋ฅผ ์ค์ด์ธ์.
- ์บ์ฑ ์ ๋ต ์ธ์ฐ๊ธฐ: ์ ์ ํ ์บ์ฑ์ผ๋ก ์ฑ์ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ด์.
์๋ฅผ ๋ค์ด, ๋ ์ด์ง ๋ก๋ฉ์ ์ฌ์ฉํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ํ ์ ์์ด์:
@page "/lazycomponent"
@if (shouldRender)
{
<dynamiccomponent type="@typeof(LazyLoadedComponent)"></dynamiccomponent>
}
@code {
private bool shouldRender;
protected override void OnInitialized()
{
shouldRender = true;
}
}
์ด๋ ๊ฒ ํ๋ฉด LazyLoadedComponent
๊ฐ ํ์ํ ๋๋ง ๋ก๋๋ผ์. ์ฑ์ ์ด๊ธฐ ๋ก๋ฉ ์๊ฐ์ ์ค์ผ ์ ์์ฃ !
๐ก ํ: ์ต์ ํ๋ ๋ง์น ๋ค์ด์ดํธ ๊ฐ์์. ๋ถํ์ํ ๊ฒ๋ค์ ์ ๊ฑฐํ๊ณ , ํจ์จ์ ์ผ๋ก ๋ง๋๋ ๊ฑฐ์ฃ . ๊ทธ ๊ฒฐ๊ณผ ์ฐ๋ฆฌ ์ฑ์ ๋ ์ฌํ๊ณ ๋น ๋ฅธ ๋ชธ๋งค(?)๋ฅผ ๊ฐ๊ฒ ๋ผ์! ใ ใ ใ
2. ์ฑ ๋น๋ํ๊ธฐ
์ฑ์ ๋ฐฐํฌํ๊ธฐ ์ ์ ๋จผ์ ๋น๋ํด์ผ ํด์. ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํด๋ณด์ธ์:
dotnet publish -c Release
์ด ๋ช ๋ น์ด๋ ๋ฆด๋ฆฌ์ฆ ๋ชจ๋๋ก ์ฑ์ ๋น๋ํด์. ์ต์ ํ๋ ๋ฒ์ ์ ์ฑ์ด ์์ฑ๋์ฃ .
3. ์ ์ ์น ํธ์คํ ์ฌ์ฉํ๊ธฐ
Blazor WebAssembly ์ฑ์ ์ ์ ํ์ผ๋ค๋ก ๊ตฌ์ฑ๋์ด ์์ด์. ๋ฐ๋ผ์ ์ ์ ์น ํธ์คํ ์๋น์ค๋ฅผ ์ฌ์ฉํด ์ฝ๊ฒ ๋ฐฐํฌํ ์ ์์ด์. ๋ช ๊ฐ์ง ์ต์ ์ ์ดํด๋ณผ๊น์?
- GitHub Pages: GitHub ์ ์ฅ์์ ์ฐ๋ํด ๋ฌด๋ฃ๋ก ํธ์คํ ํ ์ ์์ด์.
- Azure Static Web Apps: Microsoft Azure์ ์๋น์ค๋ก, CI/CD ํ์ดํ๋ผ์ธ๋ ์ ๊ณตํด์.
- Netlify: ์ฌ์ฉํ๊ธฐ ์ฝ๊ณ ๋ฌด๋ฃ ํ๋๋ ์ ๊ณตํ๋ ์ธ๊ธฐ ์๋ ํธ์คํ ์๋น์ค์์.
- Firebase Hosting: Google์ ์๋น์ค๋ก, ๋น ๋ฅด๊ณ ์์ ํ ํธ์คํ ์ ์ ๊ณตํด์.
์๋ฅผ ๋ค์ด, GitHub Pages๋ฅผ ์ฌ์ฉํด ๋ฐฐํฌํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ ์ดํด๋ณผ๊น์?
- GitHub์ ์ ์ ์ฅ์๋ฅผ ๋ง๋์ธ์.
- ๋น๋๋ ์ฑ ํ์ผ๋ค์ ์ด ์ ์ฅ์์ ํธ์ํ์ธ์.
- ์ ์ฅ์ ์ค์ ์์ GitHub Pages๋ฅผ ํ์ฑํํ๊ณ , ๋ฐฐํฌํ ๋ธ๋์น์ ํด๋๋ฅผ ์ ํํ์ธ์.
- ์ง์! ์ฌ๋ฌ๋ถ์ ์ฑ์ด
https://username.github.io/repository-name
์ ๋ฐฐํฌ๋์์ด์!
์ ๋ง ์ฝ์ฃ ? ใ ใ ใ
4. PWA(Progressive Web App) ๋ง๋ค๊ธฐ
Blazor WebAssembly ์ฑ์ PWA๋ก ๋ง๋ค๋ฉด ๋์ฑ ๋ค์ดํฐ๋ธ ์ฑ ๊ฐ์ ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ด์. PWA๋ ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ์ด ์์ฃ :
- ์คํ๋ผ์ธ์์๋ ๋์ํด์.
- ํ ํ๋ฉด์ ์ค์นํ ์ ์์ด์.
- ํธ์ ์๋ฆผ์ ๋ณด๋ผ ์ ์์ด์.
Blazor ์ฑ์ PWA๋ก ๋ง๋ค๋ ค๋ฉด, ํ๋ก์ ํธ ํ์ผ(.csproj
)์ ๋ค์ ์ค์ ์ถ๊ฐํ์ธ์:
<serviceworkerassetsmanifest>service-worker-assets.js</serviceworkerassetsmanifest>
๊ทธ๋ฆฌ๊ณ wwwroot
ํด๋์ manifest.json
ํ์ผ์ ์ถ๊ฐํ์ธ์:
{
"name": "My Awesome Blazor App",
"short_name": "BlazorApp",
"start_url": "./",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#03173d",
"icons": [
{
"src": "icon-512.png",
"type": "image/png",
"sizes": "512x512"
}
]
}
์ด๋ ๊ฒ ํ๋ฉด ์ฌ๋ฌ๋ถ์ Blazor ์ฑ์ด PWA๊ฐ ๋ผ์! ๐
์ ๊ทธ๋ฆผ์ Blazor WebAssembly ์ฑ์ ๋ฐฐํฌ ๊ณผ์ ์ ๋ณด์ฌ์ค์. ๋น๋ํ๊ณ , ์ต์ ํํ๊ณ , ๋ฐฐํฌํ๋ ๋จ๊ณ๋ฅผ ๊ฑฐ์น์ฃ . ๊ฐ ๋จ๊ณ๊ฐ ์ค์ํด์!
์, ์ด์ ์ฌ๋ฌ๋ถ์ Blazor WebAssembly ์ฑ์ด ์ธ์์ ๊ณต๊ฐ๋ ์ค๋น๊ฐ ๋์์ด์! ๐ ์ด๋ค๊ฐ์? ์๊ฐ๋ณด๋ค ์ฝ์ฃ ? ใ ใ ใ
๊ธฐ์ตํ์ธ์. ๋ฐฐํฌ๋ ๋์ด ์๋๋ผ ์์์ด์์. ์ฌ์ฉ์๋ค์ ํผ๋ ๋ฐฑ์ ๋ฐ์ ๊ณ์ํด์ ์ฑ์ ๊ฐ์ ํ๊ณ ๋ฐ์ ์์ผ ๋๊ฐ์ธ์. ๊ทธ๊ฒ ๋ฐ๋ก ์ข์ ๊ฐ๋ฐ์์ ์์ธ์์!
๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์. ์ฌ๋ฌ๋ถ์ด ๋ง๋ Blazor WebAssembly ์ฑ์ ์ ๋ง ๋๋จํ ๊ฑฐ์์. C#์ผ๋ก ์น ์ฑ์ ๋ง๋ค์๋ค๋, ์๊ฐ๋ง ํด๋ ๋ฉ์ง์ง ์๋์? ๐๐๐
๐ ์ฌ๋ฏธ์๋ ์ฌ์ค: Blazor WebAssembly๋ ์ฒ์์๋ ์คํ์ ์ธ ํ๋ก์ ํธ์์ด์. ํ์ง๋ง ๊ฐ๋ฐ์๋ค์ ๋จ๊ฑฐ์ด ๊ด์ฌ ๋๋ถ์ ์ ์ ํ๋ ์์ํฌ๊ฐ ๋์์ฃ . ์ฌ๋ฌ๋ถ๋ ์ด์ ์ด ํ์ ์ ์ธ ๊ธฐ์ ์ ์ผ๋ถ๊ฐ ๋ ๊ฑฐ์์!
5. ์ฑ๋ฅ ๋ชจ๋ํฐ๋งํ๊ธฐ
์ฑ์ ๋ฐฐํฌํ ํ์๋ ์ฑ๋ฅ์ ๊ณ์ ๋ชจ๋ํฐ๋งํด์ผ ํด์. ๋ช ๊ฐ์ง ๋๊ตฌ๋ฅผ ์๊ฐํด๋๋ฆด๊ฒ์:
- Browser DevTools: ๋ธ๋ผ์ฐ์ ์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ๋คํธ์ํฌ ์์ฒญ, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋ฑ์ ํ์ธํ ์ ์์ด์.
- Lighthouse: Google์์ ์ ๊ณตํ๋ ์คํ์์ค ๋๊ตฌ๋ก, ์น ์ฑ์ ์ฑ๋ฅ, ์ ๊ทผ์ฑ, SEO ๋ฑ์ ๋ถ์ํด์ค์.
- Azure Application Insights: ์ค์๊ฐ์ผ๋ก ์ฑ์ ์ฑ๋ฅ๊ณผ ์ฌ์ฉ๋์ ๋ชจ๋ํฐ๋งํ ์ ์๋ ๊ฐ๋ ฅํ ๋๊ตฌ์์.
์๋ฅผ ๋ค์ด, Lighthouse๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด Chrome ๋ธ๋ผ์ฐ์ ์์ F12๋ฅผ ๋๋ฌ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ด๊ณ , 'Lighthouse' ํญ์ ์ ํํ๋ฉด ๋ผ์. ์ ๋ง ์ฝ์ฃ ?
6. ์ง์์ ์ธ ํตํฉ ๋ฐ ๋ฐฐํฌ(CI/CD) ๊ตฌ์ถํ๊ธฐ
๋ง์ง๋ง์ผ๋ก, CI/CD ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํด๋ณด๋ ๊ฑด ์ด๋จ๊น์? ์ด๋ ๊ฒ ํ๋ฉด ์ฝ๋ ๋ณ๊ฒฝ์ฌํญ์ ์๋์ผ๋ก ํ ์คํธํ๊ณ ๋ฐฐํฌํ ์ ์์ด์.
GitHub Actions๋ฅผ ์ฌ์ฉํ ๊ฐ๋จํ CI/CD ์ค์ ์์๋ฅผ ๋ณผ๊น์?
name: Deploy to GitHub Pages
on:
push:
branches: [ main ]
jobs:
deploy-to-github-pages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
- name: Publish .NET Core Project
run: dotnet publish BlazorApp.csproj -c Release -o release --nologo
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: gh-pages
folder: release/wwwroot
์ด ์ค์ ์ .github/workflows/main.yml
ํ์ผ๋ก ์ ์ฅํ๋ฉด, main ๋ธ๋์น์ ํธ์ํ ๋๋ง๋ค ์๋์ผ๋ก ์ฑ์ด ๋น๋๋๊ณ GitHub Pages์ ๋ฐฐํฌ๋ผ์. ์ ๋ง ํธ๋ฆฌํ์ฃ ? ใ
ใ
ใ
๋ง๋ฌด๋ฆฌ
์, ์ด์ ์ฐ๋ฆฌ๋ Blazor WebAssembly ์ฑ์ ๊ฐ๋ฐํ๊ณ , ์ต์ ํํ๊ณ , ๋ฐฐํฌํ๋ ์ ์ฒด ๊ณผ์ ์ ์ดํด๋ดค์ด์. ์ด๋ ์ จ๋์? ์ฒ์์๋ ๋ณต์กํด ๋ณด์์ง๋ง, ํ๋์ฉ ํด๋ณด๋ ๊ทธ๋ ๊ฒ ์ด๋ ต์ง ์์ฃ ?
์ฌ๋ฌ๋ถ์ด ๋ง๋ Blazor WebAssembly ์ฑ์ด ์ด์ ์ ์ธ๊ณ ์ฌ๋๋ค์๊ฒ ๊ณต๊ฐ๋์์ด์. ์ ๋ง ๋๋จํด์! ๐๐๐
์์ผ๋ก๋ ๊ณ์ ํ์ตํ๊ณ ์คํํด๋ณด์ธ์. Blazor WebAssembly๋ ๊ณ์ ๋ฐ์ ํ๊ณ ์์ด์. ์๋ก์ด ๊ธฐ๋ฅ๋ค์ด ๊ณ์ ๋์ค๊ณ ์์ฃ . ์ฌ๋ฌ๋ถ๋ ์ด ํ์ ์ ์ผ๋ถ๊ฐ ๋์ด๋ณด๋ ๊ฑด ์ด๋จ๊น์?
๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์. ๊ฐ๋ฐ์ ์ฌ์ ์ด์์. ๋ชฉ์ ์ง๊ฐ ์๋๋ผ ๊ณผ์ ์ ์ฆ๊ธฐ๋ ๊ฒ ์ค์ํด์. ์ด๋ ค์์ด ์๋๋ผ๋ ํฌ๊ธฐํ์ง ๋ง๊ณ ๊ณ์ ๋์ ํด๋ณด์ธ์. ์ธ์ ๊ฐ ์ฌ๋ฌ๋ถ๋ Blazor WebAssembly ์ ๋ฌธ๊ฐ๊ฐ ๋ ๊ฑฐ์์! ๐
๋ง์ง๋ง์ผ๋ก, ์ฌ๋ฌ๋ถ์ ๊ฒฝํ์ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ๊ณต์ ํ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์์. ๋ธ๋ก๊ทธ๋ฅผ ์์ฑํ๊ฑฐ๋, ์ปจํผ๋ฐ์ค์์ ๋ฐํ๋ฅผ ํด๋ณด๋ ๊ฑด ์ด๋จ๊น์? ์ฌ๋ฌ๋ถ์ ๊ฒฝํ์ด ๋ค๋ฅธ ๋๊ตฐ๊ฐ์๊ฒ๋ ํฐ ๋์์ด ๋ ์ ์์ด์.
์, ์ด์ ์ ๋ง ๋์ด์์. ์ฌ๋ฌ๋ถ์ Blazor WebAssembly ์ฌ์ ์ด ์ฆ๊ฒ๊ณ ๋ณด๋์ฐผ๊ธฐ๋ฅผ ๋ฐ๋๊ฒ์. ํ์ดํ ! ๐ช๐
๊ด๋ จ ํค์๋
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ