[๋งˆ๊ฐ] 2023.02 Blazor Meetup with Blueport

(์ด๋ฒˆ ํ™๋ณด ๊ธ€์€ ์‚ฌ์ „ ํ˜‘์˜๋ฅผ ํ†ตํ•ด ๊ณต๋™ ํ™๋ณด๋ฅผ ์ง„ํ–‰ํ•˜๊ธฐ๋กœ ๋…ผ์˜ํ•˜์—ฌ ๊ฒŒ์‹œ ๊ธ€์„ ๋ฐœํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค.)

์•ˆ๋…•ํ•˜์„ธ์š”. ๋‹ท๋„ท๋ฐ๋ธŒ ์šด์˜์ง„ ๋‚จ์ •ํ˜„์ž…๋‹ˆ๋‹ค.

2์›” 23์ผ ๋ชฉ์š”์ผ ์˜คํ›„ 2์‹œ๋ถ€ํ„ฐ 4์‹œ๊นŒ์ง€ ์„œ์ดˆ๋™ ๋Œ€๊ฐ๋นŒ๋”ฉ 12์ธต, ๋ธ”๋ฃจํฌํŠธ ์„ธ๋ฏธ๋‚˜๋ฃธ์—์„œ Blazor ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฐ‹์—…์„ ์ง„ํ–‰ํ•œ๋‹ค๋Š” ์†Œ์‹์„ ๊ณต์œ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

ํ–ฅํ›„ ์ •๊ธฐ์ ์œผ๋กœ ๋ฐ‹์—…์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ, Blazor์˜ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‹ค๋ฌด์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋…ธํ•˜์šฐ๋ฅผ ๊พธ์ค€ํžˆ ์ง€์‹ ๋‚˜๋ˆ”ํ•˜๋Š” ์œ ์ตํ•œ ์ปจํผ๋Ÿฐ์Šค๋กœ ์ฑ„์›Œ์งˆ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

์ปจํผ๋Ÿฐ์Šค ๋“ฑ๋ก์€ 2023๋…„ 2์›” Blazor ๋ฐ‹์—… - ์˜จ์˜คํ”„๋ฏน์Šค :: ๋ชจ์ž„๋ฌธํ™” ํ”Œ๋žซํผ ์—์„œ ํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋งŽ์€ ๊ด€์‹ฌ๊ณผ ์ฐธ์„, ๊ทธ๋ฆฌ๊ณ  ๊ณต์œ ๊ฐ€ ์ปค๋ฎค๋‹ˆํ‹ฐ ์šด์˜์— ํฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๊ณ ๋ง™์Šต๋‹ˆ๋‹ค!

image

7๊ฐœ์˜ ์ข‹์•„์š”

Winform์—์„œ Blazor๋กœ ๊ฐ€๋Š” ์ข‹์€ ๊ฒฝํ—˜ ๊ณต์œ ํ•˜์—ฌ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์–ด์ œ ์ œ๊ฐ€ ์—ฌ์ญค๋ณธ Blazor Browser์—์„œ TCP IP์™€ ๊ฐ™์€ ํ†ต์‹ ์ด ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ํ™•์ธ์ž…๋‹ˆ๋‹ค.

@page "/counter"
@using System.Net.Sockets;

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<button class="btn btn-primary" @onclick="SendTcpMessage">Send</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }

    private async void SendTcpMessage()
    {
        await Task.Run(() =>
        {
            try
            {
                // ์„œ๋ฒ„์˜ IP ์ฃผ์†Œ์™€ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
                string serverIP = "127.0.0.1";
                int serverPort = 8880;

                // TcpClient ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
                TcpClient client = new TcpClient(serverIP, serverPort);

                // NetworkStream ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ณ  ๋ฐ›์Šต๋‹ˆ๋‹ค.
                NetworkStream stream = client.GetStream();

                // ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ๋ฌธ์ž์—ด์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
                string message = "Hello, server!";

                // ๋ฌธ์ž์—ด์„ ๋ฐ”์ดํŠธ ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ NetworkStream์„ ํ†ตํ•ด ์„œ๋ฒ„์— ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
                byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
                stream.Write(data, 0, data.Length);

                Console.WriteLine("Sent: {0}", message);

                // ์„œ๋ฒ„์—์„œ ๋ณด๋‚ธ ์‘๋‹ต์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
                data = new byte[256];
                string responseData = string.Empty;
                int bytes = stream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.UTF8.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", responseData);

                // TcpClient์™€ NetworkStream ๊ฐ์ฒด๋ฅผ ๋‹ซ์Šต๋‹ˆ๋‹ค.
                stream.Close();
                client.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error: {0}", ex);
            }
        });
    }
}

Send Button์„ ํด๋ฆญํ•˜๋ฉด System.PlatformNotSupportedException์ด ๋ฐœ์ƒ๋ฉ๋‹ˆ๋‹ค.
.NET์— ์žˆ๋Š” ๋‚ด์šฉ์ด๋”๋ผ๋„ Browser์—์„œ ๋ง‰๊ณ  ์žˆ๋Š” ๊ธฐ๋Šฅ๋“ค์€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

3๊ฐœ์˜ ์ข‹์•„์š”

Blazor wasm์˜ ๋ชจ๋…ธ ๋Ÿฐํƒ€์ž„์—์„œ ๋ชจ๋“  .NET API๊ฐ€ ์ง€์›๋˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์‹ฌ์ง€์–ด๋Š” .NET Standard 2.0๊ณผ๋„ ์™„์ „ํžˆ ํ˜ธํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•œ ์˜ˆ๋กœ ํ•ด์‹œ ์ƒ์„ฑ API๋ฅผ ์ œ์™ธํ•œ .NET์˜ ๋ชจ๋“  ์•”ํ˜ธํ™” API๋Š” ์•„์ง ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ง€์›๋˜์ง€ ์•Š๋Š” API๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•˜๋ฉด PlatformNotSupportedException ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ Blazor wasm์—์„œ TCP ํ†ต์‹ ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด JavaScript InterOp์„ ํ†ตํ•ด WebSocket์„ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์•„ ๋ณด์ด๋„ค์š”.

5๊ฐœ์˜ ์ข‹์•„์š”

์–ด์ œ meetup์—์„œ๋„ ์ด์ ์—์„œ ๊ถ๊ธˆํ•˜์‹  ๋ถ„๋“ค์ด ๋งŽ์•˜๋Š”๋ฐ์š”
wasm ์€ ์–ด๋””๊นŒ์ง€๋‚˜ ์›น ๋ฒ ์ด์Šค ๊ธฐ๋ฐ˜์— richํ•œ ํ™˜๊ฒฝ์˜ ์†”๋ฃจ์…˜์ด์ง€
๊ณผ๊ฑฐ active x๊ธ‰์œผ๋กœ ๊ธฐ๋Œ€ํ•˜์‹ ๊ฒƒ ๊ฐ™์•„์š”
์•„๋งˆ ๋ชฉ์ ์„ ๋‹ฌ์„ฑํ•˜์‹ค๋ ค๋ฉด client ์— ๋ฏธ๋“ค์›จ์–ด ๊ฐ™์€๊ฑธ ๋‘ฌ์„œ proxy ๊ฐœ๋…์œผ๋กœ
์ ‘๊ทผํ•ด๋ณด๋Š”๊ฒƒ์ด ์ข‹์„๊ฒƒ ๊ฐ™์•„์š”

4๊ฐœ์˜ ์ข‹์•„์š”

์•ˆ๋…•ํ•˜์„ธ์š”. ๊น€์ง„์„์ž…๋‹ˆ๋‹ค.

๋ฐ‹์—…์—์„œ ์งˆ๋ฌธํ•˜์‹  ๋‚ด์šฉ์„ ์ œ๊ฐ€ ์ž˜ ์ดํ•ดํ•˜์ง€ ๋ชป ํ–ˆ์—ˆ๋‚˜ ๋ณด๋„ค์š”.
๋‹ค์Œ ๋ฐ‹์—…์—์„œ๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฐ”์ฝ”๋“œ ์ธ์‡„ ๊ฐ™์€ ๊ฒƒ์„ ํ•ด๋ณด๊ณ  ์‹ถ์œผ๋‹ˆ
ํ•ด๋ณด๋ฉด์„œ ํ˜น์‹œ ์ €๋Ÿฐ ๊ฒŒ ๋˜๋Š” ๊ธธ์ด ์žˆ๋Š” ์ง€ ์ฐพ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

3๊ฐœ์˜ ์ข‹์•„์š”

์•ˆ๋…•ํ•˜์„ธ์š” ์ด์ข…ํ›ˆ๋‹˜!
https://cafe.naver.com/infragisticskorea/391
์— 3์›” ๋ฐ‹์—… agenda๋กœ ์š”์ฒญํ•ด์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค :slight_smile:

2๊ฐœ์˜ ์ข‹์•„์š”