반응형

ValuesController

using HelloEmpty.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace HelloEmpty.controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        [HttpGet]
        public List<HelloMessage> Get()
        {
            List<HelloMessage> message = new List<HelloMessage>();
            message.Add(new HelloMessage() { Message = "Hello Web API 1!" });
            message.Add(new HelloMessage() { Message = "Hello Web API 2!" });
            message.Add(new HelloMessage() { Message = "Hello Web API 3!" });
            return message;
        }
    }
}

get() 이 클라에서 서버로 api/Values 경로로 api 를 쏘면 

서버에서 보낼 내용을 message 에 담아 브라우저에 보낸다

 

 

HelloMessage

namespace HelloEmpty.Models
{
    public class HelloMessage
    {
        public string Message { get; set; }
    }
}

실제 데이터는 Models 에 들어있게 된다

 

 

program 부분인데 이 부분은 디폴트이다

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HelloEmpty
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

 

 

Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HelloEmpty
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //mvc 를 사용하겠다는 것
            //services.AddControllersWithViews();
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();


            //홈페이지 실행할때 어떤 주소로 어떤 부분을 연동하여 실행할지에 대한 부분
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                //endpoints.MapRazorPages();
                //endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
                /*
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
                */
            });
        }
    }
}

 

DotNet Core 3.1 버전으로 하면 StartUp.cs 가 생성된다

 

 

실행결과

 

실제 데이터가 JSON 형태로 온것을 알 수 있다

 

반응형
반응형

 

 

우리는 웹 어플리케이션을 개발할 때, 보통 java, .NET, Node.js 등의 framework 또는 language를 사용하여 server-side project를 만든다. 그리고 Angular, React, Vue.js와 같은 javascript framework를 사용하여 브라우저에 데이터를 보여준다.

 

하지만, 우리는 server-side application에서 사용한 언어를 client-side에는 사용할 수가 없다. server-side와 client-side는 기본적으로 단절되어있다. 

 

우리가 만약, server language를 client에도 재사용한다면 좋지 않겠는가? 우리는 WebAssembly를 사용하여 그렇게 할 수 있다. 

 

Blazor는 무엇이고, 어떻게 사용해야 하는가?

Blazor는 C#을 사용하여 interactive web application을 만들 수 있는 오픈소스 framework이다. 우리는 Blazor에서 server, client code에 모두 C#을 사용할 수 있다. .NET runtime은 브라우저에서 우리가 생성한 .NET DLL을 실행할 수 있다. 

 

추가적인 plugin없이 주요 브라우저에서 실행이 가능하다. .NET standard와 호환하는 library를 사용할 수 있다. (NuGet package 포함) 

 

Blazor application은 WebAssembly에서 실행되고, WebAssembly는 JavaScript sandbox에서 실행된다. 

JavaScript와의 연결이 되어 있으므로, web sockets, file API, DOM의 브라우저 기능을 사용할 수 있다. 

 

Blazor application에서 JavaScript를 호출할 수 있고, 그 반대도 가능하다. 

 

Blazor Application의 Different Models

Blazor Server

Blazor Server는 ASP.NET Core application의 server측에서만 동작하고, SignalR을 사용하여 HTML과 통신한다. blazor.server.js라는 파일을 통해 가능하다. 

server-side application은 메모리에 남아있기 때문에, 사용자당 instance가 생성된다. 

장점은, Blazor WebAssembly에 비해 다운로드 사이즈가 작다. older browser에서도 디버깅이 가능하다. 

 

단점은, 서버와 연결되어 있어야 하기 때문에 offline support는 없다. 확장성도 리스크가 될 수 있지만, 동시접속 천단위까지 제공이 가능하다. 마지막으로, serverless deployment는 불가능하며, ASP.NET Core server가 반드시 필요하다. 

 

Blazor WebAssembly

WebAssembly의 도움으로 브라우저 client에서 실행된다. application이 실행되면 browser로 모든 파일을 다운받는다. (HTML, CSS, JavaScript files, .NET Standard DLL files)

 

offline mode에서 동작한다. server가 필요하지 않다. static files로 구성되어 있기 때문에, CDN, Server, Azure Storage에 배포가 가능하다. 

 

장점은, native browser application의 속도와 비슷한 정도로 빠르다. offline mode에서 동작이 가능하다. serverless deployment가 가능하다. browser로 file만 받으면, server는 필요하지 않다. 추가 plugin 없이, modern browser에서 동작이 가능하다. 배포가 쉽다. 

 

브라우저에서만 실행되기 때문에, 브라우저 capability에 의해 성능이 제한된다. 

 

단점은 최초 로딩시간이 길다. older browser에서는 동작하지 않는다. older browser에서 동작해야 한다면 Blazor server-side application이 더 나은 선택이 되겠다. 

 

Blazor Server와 Blazor WebAssembly Application의 차이점

두 application의 차이점을 살펴보자. 

 

1. index.html, _Host.cshtml

 wwwroot 폴더를 보면 Blazor WebAssembly App은 index.html 파일이 없고, Blazor 서버 앱은 없다. 

index.html파일은 blazor.webassembly.js 파일을 참조하고, application의 모든 파일을 다운로드 한다. 

이와 비슷한 일은 Blazor 서버 앱 Page/_Host.cshtml 파일에서 발생한다. 이 파일에서 참조하는 blazor.server.js 파일은 client WebSocket connection을 담당한다. 

 

그 외 Counter, Index, FetchData 파일이 동일하게 들어가 있으며, 이것은 component files를 재사용 할 수 있다는 뜻이다. 

 

2. setting

Blazor 서버 앱은 Startup.cs, appsettings.json 파일이 있고, Blazor WebAssembly App에는 없다. 

Blazor WebAssembly App에서 서비스를 등록하기 위해서는 Program.cs 파일을 사용해야 한다. 

 

 

ref : https://bigexecution.tistory.com/65

 

반응형
반응형

SPA 중심에는 대표적인 라이브러리/프론트프레임워크 React, vue/Angular, Blazor WebAssembly가 있다.

📖 SPA (Single Page Application)

기존의 웹서비스는 클라이언트(사용자)가 요청하면 서버가 해당 웹 페이지를 HTML 코드로 계산하고 반환하며, 많은 요청이 이루어지면 계산이 더욱 오래 걸립니다.

SPA는 모든 처리가 단일 페이지에서 수행되는 방식입니다. 첫 로드시에만 웹페이지를 계산하여 HTML로 반환합니다. 그 이후에는 필요한 데이터를 HTML로 전달받지 않고 (서버에서 렌더링 X) 필요한 데이터만 서버로부터 JSON으로 전달받아 동적으로 렌더링 합니다.

장점

1. 빠른 로딩 시간 (Quick Loading Time)

  • 단일 페이지에서 웹 앱에서 페이지가 로드되면 서버는 더 이상 HTML 또는 CSS를 보내지 않기 때문입니다.
    (Google Reasearch에 따르면 페이지를 로드하는 데 200 밀리 초 이상 걸리면 비즈니스와 판매에 큰 영향을 미침)

2. 좋은 캐싱 능력 (Good Caching Abilities)

  • 로컬 데이터를 효율적으로 캐시 할 수 있습니다. SPA는 하나의 요청 만 보내고 서버의 모든 데이터를 저장, 데이터에 대한 지속적인 액세스가 있기 때문에 사용자는 오프라인으로 작업할 수도 있습니다. (방문자에게 데이터비용을 요구하지 않음)

3. 신속한 프런트 엔드 개발 (Rapid Front-End Developement)

  • 단일 페이지 애플리케이션 아키텍쳐이기 때문

4. 향상된 사용자 경험 (Improved User Experience)

  • 굳이 새 페이지가 로드 될 때까지 기다릴 필요가 없음, 콘텐츠의 동적인 로드는 사용자에게 좋은 경험을 제공

주의

초기 구동속도가 느릴 수 있음.

검색엔진 최적화(SEO)

 

왜 SPA를 사용하나요?

단일 페이지 웹 앱 (SPA)는 웹 개발을 고려할 때 이상적인 선택입니다. Saas플랫폼, SEO가 중요하지 않은 커뮤니티에 쓰입니다.

프로그램과 사용자간의 훌륭하고 풍부한 통신을 원한다면 SPA 접근 방식이 필요합니다.

 

 

 

 

기존 MVC 등은 페이지 단위를 받는 형태였다고 함..  비효율적인 구조..

 

ref : https://dhddl.tistory.com/230

반응형
반응형

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp2
{

    public enum ClassType
    {
        Knight,
        Archer,
        Mage
    }

    public class Player
    {
        public ClassType ClassType { get; set; }
        public int Level { get; set; }
        public int HP { get; set; }
        public int Attack { get; set; }
        public List<int> Items { get; set; } = new List<int>();
    }

    class Linq
    {
        static List<Player> _players = new List<Player>();

        static void Main(string[] args)
        {

            Random rand = new Random();

            for(int i=0;i<100;++i)
            {
                ClassType type = ClassType.Knight;
                switch(rand.Next(0, 3))
                {
                    case 0:
                        type = ClassType.Knight;
                        break;
                    case 1:
                        type = ClassType.Archer;
                        break;
                    case 2:
                        type = ClassType.Mage;
                        break;
                }

                Player player = new Player()
                {
                        ClassType = type,
                        Level = rand.Next(1, 100),
                        HP = rand.Next(100, 1000),
                        Attack = rand.Next(5, 50)
                };

                for(int j=0;j<5;++j)
                {
                    player.Items.Add(rand.Next(1, 101));
                }
                

                _players.Add(player);
            }

            //join
            {

                List<int> levels = new List<int>() { 1, 5, 9};

                var playerLevels = 
                    from p in _players
                    join l in levels            //player와 levels를 조인하는데
                    on p.Level equals l     //레벨 i 와 player.level 이 같은것만 조인한다
                    select p;

                foreach(var p in playerLevels)
                {
                    Console.WriteLine(p.Level);
                }
                int test = 0;
            }

            GetHightLevelKnights();


        }

        //레벨이 50 이상인 knight 만 추려서 레벨을 낮음->놎음 순으로 정렬
        private static void GetHightLevelKnights()
        {
            //linq 문법으로 db 쿼리문 처럼 조회 할 수 있다
            //from 은 foreach 로 생각해도 괜찮다
            //실행 순서는 from where orderby select 순으로실행된다 생각하면 된다
            var players =
                from p in _players
                where p.ClassType == ClassType.Knight && p.Level >= 50
                orderby p.Level
                select p;

            foreach (Player p in players)
            {
                Console.WriteLine($"{ p.Level} {p.HP} {p.ClassType}");
            }
        }
    }
}

 

player와 levels를 조인하는데 레벨 i 와 player.level 이 같은것만 조인하게 한다

 

                 List<int> levels = new List<int>() { 1, 5, 9};

                var playerLevels = 
                    from p in _players
                    join l in levels            
                    on p.Level equals l    

                    select p;

 

 

 

 

 

표준 Linq 방식

    public enum ClassType
    {
        Knight,
        Archer,
        Mage
    }

    public class Player
    {
        public ClassType ClassType { get; set; }
        public int Level { get; set; }
        public int HP { get; set; }
        public int Attack { get; set; }
        public List<int> Items { get; set; } = new List<int>();
    }

    class Linq
    {
        static List<Player> _players = new List<Player>();

        static void Main(string[] args)
        {

            Random rand = new Random();

            for(int i=0;i<100;++i)
            {
                ClassType type = ClassType.Knight;
                switch(rand.Next(0, 3))
                {
                    case 0:
                        type = ClassType.Knight;
                        break;
                    case 1:
                        type = ClassType.Archer;
                        break;
                    case 2:
                        type = ClassType.Mage;
                        break;
                }

                Player player = new Player()
                {
                        ClassType = type,
                        Level = rand.Next(1, 100),
                        HP = rand.Next(100, 1000),
                        Attack = rand.Next(5, 50)
                };

                for(int j=0;j<5;++j)
                {
                    player.Items.Add(rand.Next(1, 101));
                }
                

                _players.Add(player);
            }

            //중첩 from , ex : 모든 아이템 목록을 추출할때
            {
                var items = from p in _players
                            from i in p.Items
                            where i > 95
                            select new { p, i };

                var li = items.ToList();
                foreach(var elem in li)
                {
                    Console.WriteLine(elem.i +" : " + elem.p);
                }
            }


            //linq 표준연산자
            {
                var players =
               from p in _players
               where p.ClassType == ClassType.Knight && p.Level >= 50
               orderby p.Level
               select p;

                //위 결과와 아래 결과는 같다

                //from 은 생략 가능
                var sameResult = _players
                    .Where(p => p.ClassType == ClassType.Knight && p.Level >= 50)
                    .OrderBy(p => p.Level)
                    .Select(p => p);


                int iii = 0;
            }

두개의 결과가 같은 것을 볼 수 있다

 

            //linq 표준연산자
            {
                var players =
               from p in _players
               where p.ClassType == ClassType.Knight && p.Level >= 50
               orderby p.Level
               select p;

                //위 결과와 아래 결과는 같다

                //from 은 생략 가능
                var sameResult = _players
                    .Where(p => p.ClassType == ClassType.Knight && p.Level >= 50)
                    .OrderBy(p => p.Level)
                    .Select(p => p);

 

결과 : 

세부적인 기능을 사용하고 싶다면 함수형 linq 를 사용하면 된다

 

반응형

'프로그래밍(Programming) > C#' 카테고리의 다른 글

default 연산자  (0) 2023.04.25
linq (2)  (0) 2023.04.09
Linq (1)  (0) 2023.04.08
async/await & 커피와 베이컨  (0) 2023.04.07
C# - ArraySegment  (0) 2023.01.04
반응형
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp2
{

    public enum ClassType
    {
        Knight,
        Archer,
        Mage
    }

    public class Player
    {
        public ClassType ClassType { get; set; }
        public int Level { get; set; }
        public int HP { get; set; }
        public int Attack { get; set; }
        public List<int> Items { get; set; } = new List<int>();
    }

    class Linq
    {
        static List<Player> _players = new List<Player>();

        static void Main(string[] args)
        {

            Random rand = new Random();

            for(int i=0;i<100;++i)
            {
                ClassType type = ClassType.Knight;
                switch(rand.Next(0, 3))
                {
                    case 0:
                        type = ClassType.Knight;
                        break;
                    case 1:
                        type = ClassType.Archer;
                        break;
                    case 2:
                        type = ClassType.Mage;
                        break;
                }

                Player player = new Player()
                {
                        ClassType = type,
                        Level = rand.Next(1, 100),
                        HP = rand.Next(100, 1000),
                        Attack = rand.Next(5, 50)
                };

                for(int j=0;j<5;++j)
                {
                    player.Items.Add(rand.Next(1, 101));
                }
                

                _players.Add(player);
            }

            //중첩 from , ex : 모든 아이템 목록을 추출할때
            {
                var items = from p in _players
                            from i in p.Items
                            where i > 95
                            select new { p, i };

                var li = items.ToList();
                foreach(var elem in li)
                {
                    Console.WriteLine(elem.i +" : " + elem.p);
                }
            }
            


            GetHightLevelKnights();


        }

        //레벨이 50 이상인 knight 만 추려서 레벨을 낮음->놎음 순으로 정렬
        private static void GetHightLevelKnights()
        {
            //linq 문법으로 db 쿼리문 처럼 조회 할 수 있다
            //from 은 foreach 로 생각해도 괜찮다
            //실행 순서는 from where orderby select 순으로실행된다 생각하면 된다
            var players =
                from p in _players
                where p.ClassType == ClassType.Knight && p.Level >= 50
                orderby p.Level
                select p;

            foreach (Player p in players)
            {
                Console.WriteLine($"{ p.Level} {p.HP} {p.ClassType}");
            }
        }
    }
}

 

palyer 에 

 public List<int> Items { get; set; } = new List<int>();

를 추가 한다음

 

from from 구문으로 item 의 모든 목록을 출력하는 구문이다

 

            //중첩 from , ex : 모든 아이템 목록을 추출할때
            {
                var items = from p in _players
                            from i in p.Items
                            where i > 95
                            select new { p, i };

                var li = items.ToList();
                foreach(var elem in li)
                {
                    Console.WriteLine(elem.i +" : " + elem.p);
                }
            }

 

 

 

 

Group 처리

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp2
{

    public enum ClassType
    {
        Knight,
        Archer,
        Mage
    }

    public class Player
    {
        public ClassType ClassType { get; set; }
        public int Level { get; set; }
        public int HP { get; set; }
        public int Attack { get; set; }
        public List<int> Items { get; set; } = new List<int>();
    }

    class Linq
    {
        static List<Player> _players = new List<Player>();

        static void Main(string[] args)
        {

            Random rand = new Random();

            for(int i=0;i<100;++i)
            {
                ClassType type = ClassType.Knight;
                switch(rand.Next(0, 3))
                {
                    case 0:
                        type = ClassType.Knight;
                        break;
                    case 1:
                        type = ClassType.Archer;
                        break;
                    case 2:
                        type = ClassType.Mage;
                        break;
                }

                Player player = new Player()
                {
                        ClassType = type,
                        Level = rand.Next(1, 100),
                        HP = rand.Next(100, 1000),
                        Attack = rand.Next(5, 50)
                };

                for(int j=0;j<5;++j)
                {
                    player.Items.Add(rand.Next(1, 101));
                }
                

                _players.Add(player);
            }

            //중첩 from , ex : 모든 아이템 목록을 추출할때
            {
                var items = from p in _players
                            from i in p.Items
                            where i > 95
                            select new { p, i };

                var li = items.ToList();
                foreach(var elem in li)
                {
                    Console.WriteLine(elem.i +" : " + elem.p);
                }
            }

            //group
            {
                var playerByLevel = from p in _players
                                    group p by p.Level into g           //g 로 그룹화된 데이터를 받는다
                                    orderby g.Key
                                    select new { g.Key, Players = g };
                int jj = 0;
            }


            GetHightLevelKnights();


        }

        //레벨이 50 이상인 knight 만 추려서 레벨을 낮음->놎음 순으로 정렬
        private static void GetHightLevelKnights()
        {
            //linq 문법으로 db 쿼리문 처럼 조회 할 수 있다
            //from 은 foreach 로 생각해도 괜찮다
            //실행 순서는 from where orderby select 순으로실행된다 생각하면 된다
            var players =
                from p in _players
                where p.ClassType == ClassType.Knight && p.Level >= 50
                orderby p.Level
                select p;

            foreach (Player p in players)
            {
                Console.WriteLine($"{ p.Level} {p.HP} {p.ClassType}");
            }
        }
    }
}

 

코드 중

            //group
            {
                var playerByLevel = from p in _players
                                    group p by p.Level into g           //g 로 그룹화된 데이터를 받는다
                                    orderby g.Key
                                    select new { g.Key, Players = g };
               
            }

이 부분이 플레이어들을 같은 level 로 그룹화 한다음 각 그룹끼리는 key 값에 의해 정렬 되도록 처리한 것이다

into 는 그룹화 한것을 g 라는 집합으로 넣겠다는 것

 

결과 : 

 

반응형

'프로그래밍(Programming) > C#' 카테고리의 다른 글

default 연산자  (0) 2023.04.25
linq (3)  (0) 2023.04.10
Linq (1)  (0) 2023.04.08
async/await & 커피와 베이컨  (0) 2023.04.07
C# - ArraySegment  (0) 2023.01.04
반응형

 

 

T1 과 젠지(Gen)이 영혼의 한타를 펼친다

이번에도 회전 초밥 슈퍼플레이가 배달될 것인가

 

 

 

 

 

https://www.youtube.com/watch?v=mV77sRWO1Us

반응형
반응형
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp2
{

    public enum ClassType
    {
        Knight,
        Archer,
        Mage
    }

    public class Player
    {
        public ClassType ClassType { get; set; }
        public int Level { get; set; }
        public int HP { get; set; }
        public int Attack { get; set; }
    }

    class Linq
    {
        static List<Player> _players = new List<Player>();

        static void Main(string[] args)
        {

            Random rand = new Random();

            for(int i=0;i<100;++i)
            {
                ClassType type = ClassType.Knight;
                switch(rand.Next(0, 3))
                {
                    case 0:
                        type = ClassType.Knight;
                        break;
                    case 1:
                        type = ClassType.Archer;
                        break;
                    case 2:
                        type = ClassType.Mage;
                        break;
                }

                Player player = new Player()
                {
                        ClassType = type,
                        Level = rand.Next(1, 100),
                        HP = rand.Next(100, 1000),
                        Attack = rand.Next(5, 50)
                };

                _players.Add(player);
            }

            GetHightLevelKnights();


        }

        //레벨이 50 이상인 knight 만 추려서 레벨을 낮음->놎음 순으로 정렬
        private static void GetHightLevelKnights()
        {
            //linq 문법으로 db 쿼리문 처럼 조회 할 수 있다
            //from 은 foreach 로 생각해도 괜찮다
            //실행 순서는 from where orderby select 순으로실행된다 생각하면 된다
            var players =
                from p in _players
                where p.ClassType == ClassType.Knight && p.Level >= 50
                orderby p.Level
                select p;

            foreach (Player p in players)
            {
                Console.WriteLine($"{ p.Level} {p.HP} {p.ClassType}");
            }
        }
    }
}

 

 

linq 문법으로 db 쿼리문 처럼 조회 할 수 있다
from 은 foreach 로 생각해도 괜찮다
실행 순서는 from where orderby select 순으로실행된다 생각하면 된다

=> 이것이 원래 db 의 쿼리 구문을 이해하는 순서인데 c# 의 linq 에서는 select를 아예 밑으로 내려놨음


            var players =
                from p in _players
                where p.ClassType == ClassType.Knight && p.Level >= 50
                orderby p.Level
                select p;

 

 

 

유니티에선 linq 가 ios 버전에서 문제가 발생 할 수 있어서(불안전해서) 안쓰는게 좋다

(현재 버전 확인 필요)

 

서버에선 linq 활용을 하기에 DB 와의 명령어등의 호환성 좋아서 사용하는것은 괜찮다

 

 

db 관련 참고글 https://3dmpengines.tistory.com/category/%EC%84%9C%EB%B2%84%28Server%29/DB

 

'서버(Server)/DB' 카테고리의 글 목록

[3D] [M]athematic [P]hysics Engines

3dmpengines.tistory.com

 

반응형

'프로그래밍(Programming) > C#' 카테고리의 다른 글

linq (3)  (0) 2023.04.10
linq (2)  (0) 2023.04.09
async/await & 커피와 베이컨  (0) 2023.04.07
C# - ArraySegment  (0) 2023.01.04
ThreadLocal<T> 와 AsyncLocal<T> 의 차이점  (0) 2022.12.29

+ Recent posts