<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>CHashtag</title>
    <link>https://chashtag.tistory.com/</link>
    <description>.net을 사랑하는 개발자입니다.
</description>
    <language>ko</language>
    <pubDate>Mon, 10 Aug 2026 01:08:23 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>HyoSeong</managingEditor>
    <image>
      <title>CHashtag</title>
      <url>https://tistory1.daumcdn.net/tistory/3470897/attach/fafd5ec6d75c4f36862a79e7c061cabc</url>
      <link>https://chashtag.tistory.com</link>
    </image>
    <item>
      <title>1. 인프라 구축</title>
      <link>https://chashtag.tistory.com/entry/1-%EC%9D%B8%ED%94%84%EB%9D%BC-%EA%B5%AC%EC%B6%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저는 지금 개발을 진행하기 전, 어떤 구성으로 서비스를 개발, 배포, 운영할 지에 대한 고민을 하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개발 Stack&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 BE는 제 본업인 asp.net core 기반으로 작업. 이부분은 달리 선택할 게 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB는 mssql free plan(express)을 사용할 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남은건 FE인데,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 미적 감각이 거의 없다시피 하고, 그러다보니 프론트 개발 자체를 정말 싫어해 걱정이 많은데요,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선은 bootstrap과 약간의 Vue를 섞어서 진행해볼까 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배포 환경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 dockerizing을 할 예정인데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포되는 클라우드 서비스를 어떤걸 사용할지 많은 고민이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1인 개발자들에게 AWS가 꽤 좋은 선택지라는 말을 들어 그쪽을 알아보고 있었는데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상시 떠있어야 할거라 aws Lambda는 우선 제외,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ec2를 사용하면 월 10만원 내외로 초기 배포를 진행할 수 있겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 와중, iptime ddns세팅을 잘 하면, 로컬 피씨에서 도커라이징 된 서버를 띄울 수 있지 않을까 라는 생각이 들어 지금 검토중에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검토 결과, https세팅, cloudflare 기능 등을 활용하기엔 iptime.org 를 ddns세팅하는것이 큰 이점이 없어서,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 &quot;dive-nomad.com&quot; 도메인을 구매,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 도메인을 Cloudflare 등록 후, cloudfalred tunneling 기능을 이용하여 로컬 PC의 dockerizing된 nginx로 연결시켜 주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피씨를 항시 켜 두어야 하지만, 저는 원래 그러고 살아서 큰 부담이 없었습니다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프라 세팅을 하면서 느낀점은, chatgpt가 정말 많이 좋아졌구나를 느끼며, 1인 풀스택 개발이 시간은 많이 들겠지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불가능한일은 아니겠구나를 다시한번 느끼는 하루였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료1: cloudflare tunnel (&lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크&lt;/a&gt;)&lt;/p&gt;
&lt;figure id=&quot;og_1744602405548&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Cloudflare Tunnel &amp;middot; Cloudflare Zero Trust docs&quot; data-og-description=&quot;Cloudflare Tunnel provides you with a secure way to connect your resources to Cloudflare without a publicly routable IP address. With Tunnel, you do not send traffic to an external IP &amp;mdash; instead, a lightweight daemon in your infrastructure (cloudflared) c&quot; data-og-host=&quot;developers.cloudflare.com&quot; data-og-source-url=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/&quot; data-og-url=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/6UFHk/hyYFCkZPzC/UcIE93ckTNOL4DhtMH6mxK/img.png?width=1800&amp;amp;height=1013&amp;amp;face=0_0_1800_1013,https://scrap.kakaocdn.net/dn/udkyP/hyYFCL28b8/qp1EyAI6YmT0ntDRGVVdz1/img.png?width=1800&amp;amp;height=1013&amp;amp;face=0_0_1800_1013&quot;&gt;&lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/6UFHk/hyYFCkZPzC/UcIE93ckTNOL4DhtMH6mxK/img.png?width=1800&amp;amp;height=1013&amp;amp;face=0_0_1800_1013,https://scrap.kakaocdn.net/dn/udkyP/hyYFCL28b8/qp1EyAI6YmT0ntDRGVVdz1/img.png?width=1800&amp;amp;height=1013&amp;amp;face=0_0_1800_1013');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Cloudflare Tunnel &amp;middot; Cloudflare Zero Trust docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Cloudflare Tunnel provides you with a secure way to connect your resources to Cloudflare without a publicly routable IP address. With Tunnel, you do not send traffic to an external IP &amp;mdash; instead, a lightweight daemon in your infrastructure (cloudflared) c&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.cloudflare.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2533&quot; data-origin-height=&quot;1246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQVNPK/btsNiZlMObz/Li3pllMQK54R0lp3PxhoW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQVNPK/btsNiZlMObz/Li3pllMQK54R0lp3PxhoW1/img.png&quot; data-alt=&quot;대략적인 인프라 구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQVNPK/btsNiZlMObz/Li3pllMQK54R0lp3PxhoW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQVNPK%2FbtsNiZlMObz%2FLi3pllMQK54R0lp3PxhoW1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2533&quot; height=&quot;1246&quot; data-origin-width=&quot;2533&quot; data-origin-height=&quot;1246&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;대략적인 인프라 구성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 자세히 다루고 싶지만, 시간도 부족하고, 실력도 부족해서, 우선 여기까지만 다루도록 하겠습니다.&lt;/p&gt;</description>
      <category>뭐 이런 걸 다 만들어주시고/Dive Nomad</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/172</guid>
      <comments>https://chashtag.tistory.com/entry/1-%EC%9D%B8%ED%94%84%EB%9D%BC-%EA%B5%AC%EC%B6%95#entry172comment</comments>
      <pubDate>Mon, 14 Apr 2025 13:04:00 +0900</pubDate>
    </item>
    <item>
      <title>0. 들어가기 앞서</title>
      <link>https://chashtag.tistory.com/entry/0-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%95%9E%EC%84%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇번 언급했었지만, 저는 프리다이빙 강사를 부업으로 삼고 있고, 다이빙 투어를 1년에 3번 이상 다니는 다이버입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 와중, 다이빙 여행 계획을 짜는 과정이 굉장히 비효율적이라는 사실을 인식하였고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그것을 개선하기 위한,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Diver들을 위한 플랫폼, &quot;Dive Nomad&quot; 를 개발하기로 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 개발은 우선 저 혼자 진행할 예정이라,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 예산, 저 개발기간 속에서 다양한 의사결정을 하며 서비스를 만들어나가려 하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 과정을 이곳에 남겨볼까 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자 그럼 시작합니다.&lt;/p&gt;</description>
      <category>뭐 이런 걸 다 만들어주시고/Dive Nomad</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/171</guid>
      <comments>https://chashtag.tistory.com/entry/0-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%95%9E%EC%84%9C#entry171comment</comments>
      <pubDate>Sun, 6 Apr 2025 15:23:01 +0900</pubDate>
    </item>
    <item>
      <title>[C#] asp.net core Memory Leak 분석 2 - CancellationTokenSource</title>
      <link>https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-2-CancellationTokenSource</link>
      <description>&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;Memory Leak 시리즈&lt;br /&gt;&lt;br /&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-1-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%95%9E%EC%84%9C&quot;&gt;Memory&amp;nbsp;Leak 분석 1 - 들어가기 앞서,,&lt;/a&gt;&amp;nbsp; &lt;br /&gt;- &lt;a href=&quot;https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-2-CancellationTokenSource&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Memory Leak 분석 2 - CancellationTokenSource&lt;/a&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 글을 진행하기 앞서, CancellationToken&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; 에 대한 설명을 간단히 해야 할 것 같은데,,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(&lt;s&gt;귀찮으니&lt;/s&gt; 나중에 별도 게시글로 작성을 하고, 링크를 추가하도록 하겠습니다)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Live Service를 대상으로 약 4시간 간격으로 dotnet-dump 를 진행하여 두 메모리를 Compare하였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;Byte[], string 등 많은 객체들이 증가하고 있었지만, 그 중 CancellationTokenSource관련 객체들이 수만개씩 늘어나 있는것을 확인하였다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;빠르게 CancellationTokenSource를 사용하는 코드를 찾아보니 한 코드가 눈에 띄었다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;서비스에는 API동작이 끝난 후, Response와 관련이 없는 추가 동작을 진행해야 하는 경우를 대비하기 위해,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;Background Service가 돌아가고 있다. (당연히 Singleton이다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;가령, 오래 걸리는 작업에 대한 시작 요청을 보낸 뒤, 해당 작업을 처리하기 위함이라거나,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;API 통계 처리 등을 해당 service를 통해 진행한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(가끔 이 부분에서 지연이 발생하는데, 이것이 end user까지의 응답 지연으로 이어지지 않았으면 하는 의도이다)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;아무튼, 이 코드는 대략 이런식이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;(이 &lt;a href=&quot;https://github.com/RaythaHQ/raytha/blob/main/src/Raytha.Infrastructure/BackgroundTasks/QueuedHostedService.cs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;코드&lt;/a&gt;를 참고했었던 것 같다.)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1741006157607&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class BackgroundWorker : BackgroundService
{
    private readonly IQueue _queue;

    private readonly IServiceScopeFactory _serviceScopeFactory;

    public BackgroundWorker(
        IQueue queue,
        IServiceScopeFactory serviceScopeFactory)
    {
        _queue = queue;
        _serviceScopeFactory = serviceScopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        await Task.Yield();

        while (cancellationToken.IsCancellationRequested is false)
        {
            // 작업을 가져오고
            var (item, ownCancelToken) = _queue.Dequeue(cancellationToken);

            if (ownCancelToken.IsCancellationRequested)
            {
                continue;
            }
			
            // Token 을 결합한 뒤,
            var combinedCancelTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, ownCancelToken);

            // Scope 를 생성
            using var scope = _serviceScopeFactory.CreateScope();
            
            var mediator = scope.ServiceProvider.GetService&amp;lt;IMediator&amp;gt;();
			
            // 요청받은 작업을 처리한다.
            await mediator.Publish(item, combinedCancelTokenSource.Token);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, 이 코드에는 두 가지 심각한 결함이 있다. (Memory Leak을 제외하더라도 하나가 더 있다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 보인다면, 당신을 제 스승으로 삼겠습니다. (꾸벅)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 메모리 Leak 부터 살펴보자,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CancellationTokenSource&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요 녀석은 여러 CancellationToken을 합쳐주는 녀석이라고 생각하면 편하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각기 다른 곳에서 Cancel요청이 들어올 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 로직에선,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. BackgroundService에서 Stop 요청이 왔을 경우,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 이는 Shut-down 요청이 들어올 경우가 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. item에서 받아온 CancellationToken에서 Stop요청이 왔을 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 이는 실 사용자로부터 온 Cancel 요청일 가능성이 크다. (BackgroundQueue 에서 꺼내 처리하기 때문에, 현실적으로 Cancel요청이 들어올 확률은 지극히 낮지만.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼 이런 경우, 대부분 CancellationToken은 하나만 인자로 넘길 수 있기 때문에, 이를 합쳐주는 작업이 필요하고, 그게 바로 CancellationTokenSource인 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;s&gt;그게 아니라면 CancellationToken을 IEnumerable 로 받거나, params로 받아야 할 수도 있다 ㅋㅋ&lt;/s&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* CancellationTokenSource에 대한 더 자세한 내용은 이 &lt;a href=&quot;https://learn.microsoft.com/ko-kr/dotnet/standard/threading/how-to-listen-for-multiple-cancellation-requests&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크&lt;/a&gt;를 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼, 두 Token을 Link 하는 과정 중에, 두 객체가 서로 엮이게 되고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BackgroundService는 SINGLETON 이기 때문에, 해당 Service가 죽기 전까지 Queue에 들어온 모~~든 Token이 할당 해제되지 않고 남아있게 되는 것이다. (GC 입장에서는 당연한 행동이다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 어떻게 해결해야 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; Dispose!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CancellationTokenSource는 기본적으로 IDisposable을 구현하고 있어, Dispose해주거나, using 하면 된다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(길게 썼지만 참,, 허무한 이슈)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 코드의 나머지 두번째 문제점은 무엇일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 얼마전에 사소한 문제로 알게된 것인데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Web request는 ExceptionHandler 를 구현하여 Exception이 터져도 큰 문제가 발생하지 않지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BackgroundService는 그런 대응을 하지 않을 경우, 내부 로직에서 Exception이 터지면 BackgroundService가 그냥 죽어버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;restart를 구현하는것도 하나의 방법일 수도 있지만, try-catch만 잘해주어도 큰 문제가 발생하지 않는다.&lt;/p&gt;</description>
      <category>C#/ASP.NET</category>
      <category>chashtag</category>
      <category>memory</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/170</guid>
      <comments>https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-2-CancellationTokenSource#entry170comment</comments>
      <pubDate>Mon, 3 Mar 2025 21:55:08 +0900</pubDate>
    </item>
    <item>
      <title>Memory Leak 분석 1 - 들어가기 앞서,,</title>
      <link>https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-1-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%95%9E%EC%84%9C</link>
      <description>&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Memory Leak 시리즈&lt;br /&gt;&lt;br /&gt;- &lt;a href=&quot;https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-1-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%95%9E%EC%84%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Memory Leak 분석 1 - 들어가기 앞서,,&lt;/a&gt;&lt;br /&gt;- &lt;a href=&quot;https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-2-CancellationTokenSource&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Memory Leak 분석 2 - CancellationTokenSource&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든것이 순조로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 꾸준히 늘고 있었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;늘어난 트래픽과 데이터에 대응하기 위해 쿼리 개선, 인프라 개선 등의 작업이 이루어지고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불필요한 에러로그를 정리하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 모니터링 시스템을 구축하며 늘어나는 유저를 받아들일 준비가 순조롭게 진행중이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 어느날, Devops engineer로부터 연락이 왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;서비스 메모리가 꾸준히 오르고 있어요&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빠르게 Datadog을 열어 수치를 확인해보니 정말 그랬다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(혹시모를 정보 누출이 우려돼 해당 게시글에서는 자료화면은 준비하지 않을 예정)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어, 메모리는 1년 전부터 꾸준히 늘고 있었다는 것,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(배포가 이루어 질때마다 서비스가 다시 켜지면서 꽤 안정적으로 돌아가고 있었던 것 ㅋㅋ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오 그럼 그냥 이대로 둬도 되는거 아니냐!&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;겠냐?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럴 순 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번 뿌리를 뽑아보자!&lt;/p&gt;
&lt;div id=&quot;gtx-trans&quot; style=&quot;position: absolute; left: 37px; top: 121px;&quot;&gt;
&lt;div class=&quot;gtx-trans-icon&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>C#/ASP.NET</category>
      <category>C#</category>
      <category>dotNET</category>
      <category>memoryleak</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/169</guid>
      <comments>https://chashtag.tistory.com/entry/Memory-Leak-%EB%B6%84%EC%84%9D-1-%EB%93%A4%EC%96%B4%EA%B0%80%EA%B8%B0-%EC%95%9E%EC%84%9C#entry169comment</comments>
      <pubDate>Mon, 3 Mar 2025 21:26:36 +0900</pubDate>
    </item>
    <item>
      <title>asp.net DI의 life cycle (Singleton, Scope, Transient)</title>
      <link>https://chashtag.tistory.com/entry/aspnet-DI%EC%9D%98-life-cycle-Singleton-Scope-Transient</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;asp.net (혹은 core) 에는 3가지 Life cycle이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Life cycle은 무엇이며, 어떤 경우에 적절한지 한번 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Web Server에서의 Life Cycle&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Server는, Request를 받고, Response를 내보내 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수많은 Request들을 처리하게 되는데, 이 때 DI는 필수적이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 새로운 객체를 생성하는 것이 불필요한 경우도 있고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부 변수를 다른 Request와는 절대 공유해서는 안되는 경우도 있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는, 하나의 Request내에서만 공유되도록 하고싶을 수도 있죠.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AddSingleton()&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 Inject될때 최초 만들어둔 singleton 객체로 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점이자 단점은, 매번 동일한 객체를 반환한다는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AddScope()&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scope는 하나의 Request에 한해서 동일한 객체를 Inject합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AddTransient()&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 Request안에서 여러번 Inject될 때, 매번 새로운 객체가 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;여담으로 이런 질문을 면접 때 받은적이 있었는데,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;오픈소스를 복붙해서 잘 모르겠습니다&quot; 라고 대답한 기억이 있네요,,;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(어떻게 붙었지 나?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현하려는 객체 특성에 맞는 적절한 Life Cycle을 지정하는것이 정말 중요하니, 꼭 개념 알고계시면 좋을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 오랜만에 글을 쓰려니 잘 안되네요,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 꾸준히 작성해보려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>C#/ASP.NET</category>
      <category>ASP.NET</category>
      <category>backend</category>
      <category>lifecycle</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/168</guid>
      <comments>https://chashtag.tistory.com/entry/aspnet-DI%EC%9D%98-life-cycle-Singleton-Scope-Transient#entry168comment</comments>
      <pubDate>Mon, 13 May 2024 21:37:45 +0900</pubDate>
    </item>
    <item>
      <title>[C#] !! 연산자 (parameter null check)</title>
      <link>https://chashtag.tistory.com/entry/C-%EC%97%B0%EC%82%B0%EC%9E%90-parameter-null-check</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서&amp;nbsp;&quot;!!&quot;는&amp;nbsp;parameter&amp;nbsp;null&amp;nbsp;check&amp;nbsp;기능으로&amp;nbsp;사용되는&amp;nbsp;연산자입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;연산자는&amp;nbsp;parameter&amp;nbsp;값이&amp;nbsp;null인지&amp;nbsp;아닌지를&amp;nbsp;판단하는&amp;nbsp;기능을&amp;nbsp;수행합니다. &lt;br /&gt;&lt;br /&gt;&quot;!!&quot;&amp;nbsp;연산자는&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676902088223&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;string myString = null;
bool isNotNull = !!myString;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의&amp;nbsp;코드에서는&amp;nbsp;myString이&amp;nbsp;null이므로&amp;nbsp;isNotNull&amp;nbsp;변수에&amp;nbsp;false&amp;nbsp;값이&amp;nbsp;할당됩니다.&amp;nbsp;만약&amp;nbsp;myString에&amp;nbsp;문자열이&amp;nbsp;할당되어&amp;nbsp;있다면&amp;nbsp;isNotNull&amp;nbsp;변수에&amp;nbsp;true&amp;nbsp;값이&amp;nbsp;할당됩니다. &lt;br /&gt;&lt;br /&gt;C#에서는&amp;nbsp;null&amp;nbsp;check를&amp;nbsp;위해&amp;nbsp;if문을&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;일반적입니다.&amp;nbsp;하지만&amp;nbsp;&quot;!!&quot;&amp;nbsp;연산자를&amp;nbsp;사용하면&amp;nbsp;코드를&amp;nbsp;간결하게&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있으며&amp;nbsp;가독성도&amp;nbsp;높일&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676902104443&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if(myString != null)
{
    // do something
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;코드를&amp;nbsp;&quot;!!&quot;&amp;nbsp;연산자를&amp;nbsp;사용하여&amp;nbsp;간결하게&amp;nbsp;작성하면&amp;nbsp;다음과&amp;nbsp;같습니다. &lt;/p&gt;
&lt;pre id=&quot;code_1676902115006&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bool isNotNull = !!myString;

if(isNotNull)
{
    // do something
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉,&amp;nbsp;&quot;!!&quot;&amp;nbsp;연산자는&amp;nbsp;null&amp;nbsp;check를&amp;nbsp;간편하게&amp;nbsp;처리할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;기능을&amp;nbsp;제공하는&amp;nbsp;연산자입니다. &lt;br /&gt;&lt;br /&gt;하지만,&amp;nbsp;&quot;!!&quot;&amp;nbsp;연산자는&amp;nbsp;가독성이나&amp;nbsp;유지보수성&amp;nbsp;등에서&amp;nbsp;문제가&amp;nbsp;될&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;따라서,&amp;nbsp;이&amp;nbsp;연산자를&amp;nbsp;남발하지&amp;nbsp;않고&amp;nbsp;상황에&amp;nbsp;맞게&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>!!</category>
      <category>C#</category>
      <category>chashtag</category>
      <category>csharp</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/160</guid>
      <comments>https://chashtag.tistory.com/entry/C-%EC%97%B0%EC%82%B0%EC%9E%90-parameter-null-check#entry160comment</comments>
      <pubDate>Mon, 20 Feb 2023 23:08:54 +0900</pubDate>
    </item>
    <item>
      <title>[C#/WPF] Listview SelectedItems command Binding (MVVM패턴)</title>
      <link>https://chashtag.tistory.com/entry/CWPF-Listview-SelectedItems-command-Binding-MVVM%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;WPF의 Listview는 많은 데이터를 표시할 수 있도록 도와주는 UI 요소 중 하나입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 SelectedItems 속성을 바인딩하는 것이 불가능했지만, 최신 버전의 WPF에서는 Command로 처리할 수 있도록 업데이트되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 Prism 라이브러리를 이용하여 Mvvm 패턴을 적용한 예제를 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Prism은 MVVM 패턴을 구현하는 데 도움이 되는 많은 기능을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선, Prism 라이브러리를 사용하려면 NuGet 패키지 관리자에서 Prism.Core 패키지를 설치해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 후, ListView와 Command를 바인딩하는 방법을 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ListView의 Behaviors 클래스 가져오기&lt;/h4&gt;
&lt;pre id=&quot;code_1676901572192&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;xmlns:i=&quot;http://schemas.microsoft.com/expression/2010/interactivity&quot;
xmlns:prism=&quot;http://prismlibrary.com/&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ListView에&amp;nbsp;대한&amp;nbsp;Behaviors&amp;nbsp;클래스를&amp;nbsp;사용하여&amp;nbsp;SelectedItems와&amp;nbsp;연결된&amp;nbsp;ICommand를&amp;nbsp;설정합니다.&lt;/h4&gt;
&lt;pre id=&quot;code_1676901594729&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;ListView Name=&quot;myListView&quot; ItemsSource=&quot;{Binding MyItems}&quot; SelectionMode=&quot;Multiple&quot;&amp;gt;
    &amp;lt;i:Interaction.Behaviors&amp;gt;
        &amp;lt;prism:InvokeCommandAction Command=&quot;{Binding MyCommand}&quot; CommandParameter=&quot;{Binding ElementName=myListView, Path=SelectedItems}&quot; /&amp;gt;
    &amp;lt;/i:Interaction.Behaviors&amp;gt;
&amp;lt;/ListView&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의&amp;nbsp;코드에서&amp;nbsp;MyCommand는&amp;nbsp;ICommand를&amp;nbsp;구현한&amp;nbsp;ViewModel의&amp;nbsp;속성입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;속성은&amp;nbsp;SelectedItems&amp;nbsp;속성과&amp;nbsp;연결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ViewModel에서&amp;nbsp;MyCommand&amp;nbsp;속성을&amp;nbsp;구현합니다.&lt;/h4&gt;
&lt;pre id=&quot;code_1676901618678&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MainViewModel : BindableBase
{
    private ObservableCollection&amp;lt;string&amp;gt; _myItems;
    private ICommand _myCommand;

    public ObservableCollection&amp;lt;string&amp;gt; MyItems
    {
        get { return _myItems; }
        set { SetProperty(ref _myItems, value); }
    }

    public ICommand MyCommand
    {
        get { return _myCommand; }
        set { SetProperty(ref _myCommand, value); }
    }

    public MainViewModel()
    {
        MyItems = new ObservableCollection&amp;lt;string&amp;gt;() { &quot;Item 1&quot;, &quot;Item 2&quot;, &quot;Item 3&quot;, &quot;Item 4&quot; };
        MyCommand = new DelegateCommand&amp;lt;IList&amp;gt;(OnMyCommandExecuted);
    }

    private void OnMyCommandExecuted(IList selectedItems)
    {
        // do something with selected items
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의&amp;nbsp;코드에서&amp;nbsp;DelegateCommand를&amp;nbsp;사용하여&amp;nbsp;MyCommand&amp;nbsp;속성을&amp;nbsp;구현합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;속성은&amp;nbsp;SelectedItems&amp;nbsp;속성과&amp;nbsp;연결됩니다.&amp;nbsp;OnMyCommandExecuted&amp;nbsp;메서드에서는&amp;nbsp;선택된&amp;nbsp;항목을&amp;nbsp;처리합니다. &lt;br /&gt;&lt;br /&gt;이제&amp;nbsp;ListView의&amp;nbsp;SelectedItems를&amp;nbsp;ICommand와&amp;nbsp;바인딩하는&amp;nbsp;방법과&amp;nbsp;Prism&amp;nbsp;라이브러리를&amp;nbsp;사용하여&amp;nbsp;Mvvm&amp;nbsp;패턴을&amp;nbsp;구현하는&amp;nbsp;방법을&amp;nbsp;알아봤습니다.&amp;nbsp;이를&amp;nbsp;통해&amp;nbsp;ViewModel에서&amp;nbsp;ListView의&amp;nbsp;선택된&amp;nbsp;항목을&amp;nbsp;처리할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>C#/WPF</category>
      <category>C#</category>
      <category>chashtag</category>
      <category>csharp</category>
      <category>ListView</category>
      <category>WPF</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/159</guid>
      <comments>https://chashtag.tistory.com/entry/CWPF-Listview-SelectedItems-command-Binding-MVVM%ED%8C%A8%ED%84%B4#entry159comment</comments>
      <pubDate>Mon, 20 Feb 2023 23:00:55 +0900</pubDate>
    </item>
    <item>
      <title>[C#/WPF] Converter사용하여 bool 반대값 binding하기</title>
      <link>https://chashtag.tistory.com/entry/CWPF-Converter%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-bool-%EB%B0%98%EB%8C%80%EA%B0%92-binding%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;WPF에서&amp;nbsp;Converter를&amp;nbsp;사용하여&amp;nbsp;bool의&amp;nbsp;반대값을&amp;nbsp;binding하는&amp;nbsp;방법은&amp;nbsp;매우&amp;nbsp;간단합니다.&amp;nbsp;Converter는&amp;nbsp;데이터를&amp;nbsp;변환하는데&amp;nbsp;사용되며,&amp;nbsp;이를&amp;nbsp;사용하면&amp;nbsp;XAML&amp;nbsp;코드에서&amp;nbsp;데이터&amp;nbsp;변환을&amp;nbsp;수행할&amp;nbsp;수&amp;nbsp;있습니다. &lt;br /&gt;&lt;br /&gt;Converter를&amp;nbsp;사용하여&amp;nbsp;bool의&amp;nbsp;반대값을&amp;nbsp;binding하는&amp;nbsp;예제를&amp;nbsp;보여드리겠습니다. &lt;br /&gt;&lt;br /&gt;먼저,&amp;nbsp;Converter&amp;nbsp;클래스를&amp;nbsp;작성합니다.&amp;nbsp;이&amp;nbsp;클래스는&amp;nbsp;IValueConverter&amp;nbsp;인터페이스를&amp;nbsp;구현해야&amp;nbsp;하며,&amp;nbsp;Convert와&amp;nbsp;ConvertBack&amp;nbsp;메서드를&amp;nbsp;구현해야&amp;nbsp;합니다.&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676900388748&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Globalization;
using System.Windows.Data;

namespace MyConverter
{
    public class BooleanNegationConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool)
            {
                return !(bool)value;
            }

            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is bool)
            {
                return !(bool)value;
            }

            return value;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&amp;nbsp;XAML&amp;nbsp;코드에서&amp;nbsp;Converter를&amp;nbsp;사용하여&amp;nbsp;bool의&amp;nbsp;반대값을&amp;nbsp;binding할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과&amp;nbsp;같이&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676900403877&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;Window xmlns:local=&quot;clr-namespace:MyConverter&quot;&amp;gt;
    &amp;lt;Window.Resources&amp;gt;
        &amp;lt;local:BooleanNegationConverter x:Key=&quot;BooleanNegationConverter&quot;/&amp;gt;
    &amp;lt;/Window.Resources&amp;gt;

    &amp;lt;StackPanel&amp;gt;
        &amp;lt;CheckBox x:Name=&quot;checkBox&quot; Content=&quot;CheckBox&quot;/&amp;gt;
        &amp;lt;TextBlock Text=&quot;{Binding ElementName=checkBox, Path=IsChecked, Converter={StaticResource BooleanNegationConverter}}&quot;/&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/Window&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;코드에서&amp;nbsp;Converter를&amp;nbsp;선언하고,&amp;nbsp;CheckBox의&amp;nbsp;IsChecked&amp;nbsp;속성을&amp;nbsp;TextBlock의&amp;nbsp;Text&amp;nbsp;속성에&amp;nbsp;binding하면,&amp;nbsp;CheckBox가&amp;nbsp;체크되면&amp;nbsp;TextBlock에는&amp;nbsp;false가&amp;nbsp;표시되고,&amp;nbsp;CheckBox가&amp;nbsp;체크되지&amp;nbsp;않으면&amp;nbsp;TextBlock에는&amp;nbsp;true가&amp;nbsp;표시됩니다. &lt;br /&gt;&lt;br /&gt;이것이&amp;nbsp;WPF에서&amp;nbsp;Converter를&amp;nbsp;사용하여&amp;nbsp;bool의&amp;nbsp;반대값을&amp;nbsp;binding하는&amp;nbsp;방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;</description>
      <category>C#/WPF</category>
      <category>C#</category>
      <category>chashtag</category>
      <category>WPF</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/158</guid>
      <comments>https://chashtag.tistory.com/entry/CWPF-Converter%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-bool-%EB%B0%98%EB%8C%80%EA%B0%92-binding%ED%95%98%EA%B8%B0#entry158comment</comments>
      <pubDate>Mon, 20 Feb 2023 22:40:27 +0900</pubDate>
    </item>
    <item>
      <title>[C#] JWT 암호화, 복호화 예제</title>
      <link>https://chashtag.tistory.com/entry/C-JWT-%EC%95%94%ED%98%B8%ED%99%94-%EB%B3%B5%ED%98%B8%ED%99%94-%EC%98%88%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JWT란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT는 인증과 정보 교환을 위한 안전한 방법을 제공하는 토큰 기반의 개방형 표준입니다. JWT는 세 부분으로 구성되어 있습니다. 헤더(header), 내용(payload), 서명(signature)으로 이루어져 있으며 각각은 Base64Url로 인코딩되어 하나의 문자열로 만들어져 전송됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Header : JWT의 타입과 사용하는 해시 알고리즘 등의 정보를 포함합니다.&lt;/li&gt;
&lt;li&gt;Payload : 토큰에 포함할 클레임(Claim) 정보를 담습니다. 클레임이란 사용자 정보, 권한 정보 등을 의미합니다.&lt;/li&gt;
&lt;li&gt;Signature : 헤더와 페이로드, 비밀키를 조합하여 생성된 서명값으로, 토큰의 변조 여부를 검증합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JWT&amp;nbsp;암호화하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서 JWT를 암호화하는 방법은 다음과 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1676899923239&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

// 토큰 발급
public string IssueJwtToken(string userId, string userRole, string secretKey)
{
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
    var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

    var claims = new[]
    {
        new Claim(ClaimTypes.NameIdentifier, userId),
        new Claim(ClaimTypes.Role, userRole)
    };

    var token = new JwtSecurityToken(
        issuer: &quot;yourdomain.com&quot;,
        audience: &quot;yourdomain.com&quot;,
        claims: claims,
        expires: DateTime.Now.AddHours(1),
        signingCredentials: signingCredentials);

    return new JwtSecurityTokenHandler().WriteToken(token);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;코드에서&amp;nbsp;secretKey는&amp;nbsp;서버에서&amp;nbsp;사용하는&amp;nbsp;암호화&amp;nbsp;키입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;signingCredentials&amp;nbsp;객체는&amp;nbsp;JWT에&amp;nbsp;서명하기&amp;nbsp;위한&amp;nbsp;보안&amp;nbsp;자격&amp;nbsp;증명입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;claims는&amp;nbsp;JWT에&amp;nbsp;담길&amp;nbsp;클레임(claim)&amp;nbsp;정보입니다.&amp;nbsp;issuer와&amp;nbsp;audience는&amp;nbsp;JWT의&amp;nbsp;발급자와&amp;nbsp;대상자&amp;nbsp;정보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JWT&amp;nbsp;복호화하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT를&amp;nbsp;복호화하기&amp;nbsp;위해서는&amp;nbsp;토큰&amp;nbsp;검증을&amp;nbsp;수행해야&amp;nbsp;합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검증은&amp;nbsp;서명된&amp;nbsp;토큰의&amp;nbsp;유효성을&amp;nbsp;검사하는&amp;nbsp;것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서&amp;nbsp;JWT를&amp;nbsp;검증하는&amp;nbsp;방법은&amp;nbsp;다음과&amp;nbsp;같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676899960176&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;

// 토큰 검증
public ClaimsPrincipal ValidateJwtToken(string jwtToken, string secretKey)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var validationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey)),
        ValidateIssuer = true,
        ValidIssuer = &quot;yourdomain.com&quot;,
        ValidateAudience = true,
        ValidAudience = &quot;yourdomain.com&quot;,
        ValidateLifetime = true,
        ClockSkew = TimeSpan.Zero
    };

    try
    {
        SecurityToken validatedToken;
        return tokenHandler.ValidateToken(jwtToken, validationParameters, out validatedToken);
    }
    catch (SecurityTokenException)
    {
        return null;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위&amp;nbsp;코드에서&amp;nbsp;jwtToken은&amp;nbsp;검증할&amp;nbsp;JWT&amp;nbsp;토큰입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ValidateToken&amp;nbsp;메서드는&amp;nbsp;JWT&amp;nbsp;토큰을&amp;nbsp;검증하고,&amp;nbsp;ClaimsPrincipal&amp;nbsp;객체를&amp;nbsp;반환합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반환된&amp;nbsp;ClaimsPrincipal&amp;nbsp;객체에서는&amp;nbsp;Identity&amp;nbsp;속성으로&amp;nbsp;인증된&amp;nbsp;사용자의&amp;nbsp;정보를&amp;nbsp;가져올&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*chatGPT가 작성한 게시글입니다.&lt;/p&gt;</description>
      <category>C#</category>
      <category>C#</category>
      <category>chashtag</category>
      <category>JWT</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/157</guid>
      <comments>https://chashtag.tistory.com/entry/C-JWT-%EC%95%94%ED%98%B8%ED%99%94-%EB%B3%B5%ED%98%B8%ED%99%94-%EC%98%88%EC%A0%9C#entry157comment</comments>
      <pubDate>Mon, 20 Feb 2023 22:36:56 +0900</pubDate>
    </item>
    <item>
      <title>[C#] bigint란 무엇이며, bigint는 무한한 값을 저장할 수 있을까?</title>
      <link>https://chashtag.tistory.com/entry/C-bigint%EB%9E%80-bigint%EB%8A%94-%EB%AC%B4%ED%95%9C%ED%95%9C-%EA%B0%92%EC%9D%84-%EC%A0%80%EC%9E%A5%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;C#에서의 BigIntegers는 매우 큰 정수를 표현하기 위한 자료형입니다. 일반적인 정수형이 다룰 수 있는 범위를 넘어서는 수치 데이터를 다루기 위해서 사용됩니다. 이번 글에서는 C#에서 BigIntegers에 대해 설명하며, 이 자료형이 실제로 무한한 값을 저장할 수 있는지에 대해 살펴보겠습니다. 또한 BigIntegers의 내부 구현 방식에 대해서도 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BigIntegers란&amp;nbsp;무엇인가요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;C#의 BigIntegers는 매우 큰 정수를 표현하기 위한 자료형입니다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 자료형은 .NET Framework 4.0 이상에서 사용할 수 있으며, 다른 정수형 자료형과 마찬가지로 System.Numerics 네임스페이스에서 제공됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigIntegers는 다음과 같은 방법으로 생성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676899572598&quot; class=&quot;csharp&quot; data-ke-language=&quot;csharp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System.Numerics;

// BigInteger 변수 생성
BigInteger bigInt = BigInteger.Parse(&quot;123456789012345678901234567890&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BigIntegers는&amp;nbsp;정말&amp;nbsp;무한한&amp;nbsp;값을&amp;nbsp;저장할&amp;nbsp;수&amp;nbsp;있는가요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로&amp;nbsp;BigIntegers는&amp;nbsp;무한한&amp;nbsp;값을&amp;nbsp;저장할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;것은&amp;nbsp;아닙니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;자료형이&amp;nbsp;다룰&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;최대&amp;nbsp;값은&amp;nbsp;2^Int32.MaxValue&amp;nbsp;-&amp;nbsp;1입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;값은&amp;nbsp;79,228,162,514,264,337,593,543,950,335&amp;nbsp;이하의&amp;nbsp;정수를&amp;nbsp;표현할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&amp;nbsp;범위를&amp;nbsp;벗어나는&amp;nbsp;수치&amp;nbsp;데이터를&amp;nbsp;다루려면&amp;nbsp;다른&amp;nbsp;방법을&amp;nbsp;찾아야&amp;nbsp;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BigIntegers의&amp;nbsp;내부&amp;nbsp;구현&amp;nbsp;방식은&amp;nbsp;어떻게&amp;nbsp;되나요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigInteger는&amp;nbsp;.NET&amp;nbsp;Framework&amp;nbsp;4.0&amp;nbsp;이상에서&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;클래스로,&amp;nbsp;매우&amp;nbsp;큰&amp;nbsp;정수&amp;nbsp;값을&amp;nbsp;저장하고&amp;nbsp;연산하는&amp;nbsp;데&amp;nbsp;사용됩니다.&amp;nbsp;내부&amp;nbsp;구현&amp;nbsp;방식은&amp;nbsp;C#&amp;nbsp;언어의&amp;nbsp;기본&amp;nbsp;형식인&amp;nbsp;int,&amp;nbsp;long과는&amp;nbsp;다르게,&amp;nbsp;고급&amp;nbsp;수학적&amp;nbsp;알고리즘을&amp;nbsp;이용하여&amp;nbsp;구현됩니다. &lt;br /&gt;&lt;br /&gt;BigInteger&amp;nbsp;클래스는&amp;nbsp;내부적으로&amp;nbsp;int나&amp;nbsp;long&amp;nbsp;등의&amp;nbsp;기본&amp;nbsp;자료형의&amp;nbsp;배열을&amp;nbsp;사용하여&amp;nbsp;정수&amp;nbsp;값을&amp;nbsp;저장합니다.&amp;nbsp;배열의&amp;nbsp;크기는&amp;nbsp;저장하려는&amp;nbsp;값의&amp;nbsp;크기에&amp;nbsp;따라&amp;nbsp;동적으로&amp;nbsp;조정됩니다. &lt;br /&gt;&lt;br /&gt;BigInteger&amp;nbsp;클래스는&amp;nbsp;내부적으로&amp;nbsp;4개의&amp;nbsp;필드를&amp;nbsp;사용하여&amp;nbsp;값을&amp;nbsp;저장합니다.&amp;nbsp;이&amp;nbsp;중에서&amp;nbsp;가장&amp;nbsp;중요한&amp;nbsp;필드는&amp;nbsp;_bits&amp;nbsp;필드로,&amp;nbsp;이&amp;nbsp;필드는&amp;nbsp;uint[]&amp;nbsp;형식의&amp;nbsp;배열로&amp;nbsp;저장됩니다.&amp;nbsp;이&amp;nbsp;배열의&amp;nbsp;각&amp;nbsp;요소는&amp;nbsp;32비트&amp;nbsp;unsigned&amp;nbsp;integer&amp;nbsp;값을&amp;nbsp;저장합니다.&amp;nbsp;이&amp;nbsp;배열은&amp;nbsp;저장하려는&amp;nbsp;값에&amp;nbsp;따라&amp;nbsp;자동으로&amp;nbsp;크기가&amp;nbsp;조정되며,&amp;nbsp;큰&amp;nbsp;값일수록&amp;nbsp;배열의&amp;nbsp;크기가&amp;nbsp;커집니다. &lt;br /&gt;&lt;br /&gt;BigInteger&amp;nbsp;클래스는&amp;nbsp;이진수&amp;nbsp;연산(binary&amp;nbsp;operation)을&amp;nbsp;중심으로&amp;nbsp;구현되어&amp;nbsp;있습니다.&amp;nbsp;예를&amp;nbsp;들어,&amp;nbsp;덧셈,&amp;nbsp;뺄셈,&amp;nbsp;곱셈,&amp;nbsp;나눗셈,&amp;nbsp;모듈러스&amp;nbsp;연산&amp;nbsp;등의&amp;nbsp;연산은&amp;nbsp;모두&amp;nbsp;이진수&amp;nbsp;연산으로&amp;nbsp;구현됩니다.&amp;nbsp;이를&amp;nbsp;위해&amp;nbsp;BigInteger&amp;nbsp;클래스는&amp;nbsp;기본적으로&amp;nbsp;수학적&amp;nbsp;연산에&amp;nbsp;사용되는&amp;nbsp;다양한&amp;nbsp;알고리즘을&amp;nbsp;지원합니다. &lt;br /&gt;&lt;br /&gt;BigInteger&amp;nbsp;클래스는&amp;nbsp;내부적으로&amp;nbsp;매우&amp;nbsp;복잡한&amp;nbsp;알고리즘을&amp;nbsp;사용하여&amp;nbsp;값을&amp;nbsp;저장하고&amp;nbsp;연산합니다.&amp;nbsp;이를&amp;nbsp;통해&amp;nbsp;매우&amp;nbsp;큰&amp;nbsp;정수&amp;nbsp;값을&amp;nbsp;빠르게&amp;nbsp;연산할&amp;nbsp;수&amp;nbsp;있으며,&amp;nbsp;기본&amp;nbsp;자료형보다&amp;nbsp;훨씬&amp;nbsp;큰&amp;nbsp;범위의&amp;nbsp;정수&amp;nbsp;값을&amp;nbsp;다룰&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*ChatGPT가 생성한 게시글입니다.&lt;/p&gt;</description>
      <category>C#</category>
      <author>HyoSeong</author>
      <guid isPermaLink="true">https://chashtag.tistory.com/156</guid>
      <comments>https://chashtag.tistory.com/entry/C-bigint%EB%9E%80-bigint%EB%8A%94-%EB%AC%B4%ED%95%9C%ED%95%9C-%EA%B0%92%EC%9D%84-%EC%A0%80%EC%9E%A5%ED%95%A0-%EC%88%98-%EC%9E%88%EC%9D%84%EA%B9%8C#entry156comment</comments>
      <pubDate>Mon, 20 Feb 2023 22:29:32 +0900</pubDate>
    </item>
  </channel>
</rss>