<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>liha_engineer</title>
        <link>https://velog.io/</link>
        <description>갑자기 왜 춤춰?</description>
        <lastBuildDate>Tue, 09 Jun 2026 13:56:15 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>liha_engineer</title>
            <url>https://velog.velcdn.com/images/liha_engineer/profile/c3ae5cef-9112-4638-a3fd-84221109d740/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. liha_engineer. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/liha_engineer" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[260609 - Android studio에서 switch문을 쓰려는 큰 꿈]]></title>
            <link>https://velog.io/@liha_engineer/260609</link>
            <guid>https://velog.io/@liha_engineer/260609</guid>
            <pubDate>Tue, 09 Jun 2026 13:56:15 GMT</pubDate>
            <description><![CDATA[<h3 id="결론부터-말하자면-저-꿈은-좌절되었다">결론부터 말하자면 저 꿈은 좌절되었다</h3>
<p>경위: MainActivity.java에서 switch문을 쓰고 싶었다. </p>
<pre><code class="language-java">    public void onButtonClick(View view) {
        TextView text1 = (TextView) findViewById(R.id.text1);
        switch(view.getId()) {
            case R.id.button1:
                text1.setText(&quot;hello&quot;);
                break;

            case R.id.button2:
                text1.setText(&quot;world&quot;);
                break;
        }
    }</code></pre>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/35a32e88-6471-45fc-baaa-8fbd3fef884c/image.png" alt=""></p>
<p>위 코드를 썼더니 R.id.button1과 R.id.button2에 자꾸 빨간줄이 그어지는 것이다. Gemini에게 알아본 결과 결론은 사용할 수 없었다. gradle.properties에 <code>android.nonFinalResIds=false</code> 를 추가해도 소용 없었다. </p>
<p>=&gt; 이유는 <code>R.id.button1</code> 이런 식으로 쓰는건 리소스 ID가 상수라는 가정 하에 쓰는건데, Android studio 버전이 올라가면서 구글이 리소스 ID를 무조건 non-final로 쓰도록 강제했기 때문. 
=&gt; 또다른 이유는, switch문을 버리기 위해서. 
=&gt; 이 모든 것의 궁극적인 이유는 <strong>빌드 속도</strong>를 향상시키기 위해.</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/a2831bd1-34ee-43dc-8435-cf7738171356/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[260509 - Microsoft 앱들이 자꾸 내 네트워크를 의심해 ]]></title>
            <link>https://velog.io/@liha_engineer/260509</link>
            <guid>https://velog.io/@liha_engineer/260509</guid>
            <pubDate>Sat, 09 May 2026 12:08:28 GMT</pubDate>
            <description><![CDATA[<h3 id="나는-그저-윈도우10에서-핸드폰과-연결을-하고-싶었을-뿐인데">나는 그저 윈도우10에서 핸드폰과 연결을 하고 싶었을 뿐인데</h3>
<p>나는 분명히 네트워크에 연결되어 있는데 스티커 메모도 동기화가 안 되고 Microsoft store는 아예 로그인 지옥에 가두는 상황이 발생했다. </p>
<blockquote>
</blockquote>
<p>이 작업에는 인터넷 연결이 필요합니다. 인터넷에 연결하지 않은것 같습니다. 연결을 확인하고 다시 시도하세요. 0x800704cf</p>
<p>이 메시지가 뜨는 순간에도 나는 인터넷에 연결해서 Windows update를 다운로드 받는 중이었다. </p>
<pre><code class="language-shell">Get-AppXPackage -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register &quot;$($_.InstallLocation)\AppXManifest.xml&quot;}</code></pre>
<ol>
<li>Windows Powershell을 관리자 권한으로 실행해서 </li>
<li>위 메시지를 붙여넣고 엔터하자 </li>
<li>다되면 재부팅하자 </li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[260506 - 기억나지 않는 공식이 그리운 삼각형의 완성조건 (2)]]></title>
            <link>https://velog.io/@liha_engineer/260506</link>
            <guid>https://velog.io/@liha_engineer/260506</guid>
            <pubDate>Wed, 06 May 2026 06:44:11 GMT</pubDate>
            <description><![CDATA[<h3 id="나름-열심히-set도-써보고-애썼다고-생각했는데---세상에는-머리-좋은-사람이-너무-많아">나름 열심히 Set도 써보고 애썼다고 생각했는데 - 세상에는 머리 좋은 사람이 너무 많아</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/d615bd12-a5b8-48dc-a84e-156d69bfbcf5/image.png" alt=""></p>
<p>예?</p>
<pre><code class="language-js">const findTriangleSide = (sides) =&gt; {
    sides = sides.sort((a,b) =&gt; a-b) 
    const set = new Set()

    // 주어진 큰변이 제일 긴 경우: 큰변-작은변+1 부터 큰변 이하까지 
    for (let i = sides[1] - sides[0] + 1; i &lt;= sides[1]; i++) {
        set.add(i)
    }

    // 안 주어진 미지의 변이 제일 긴 경우: 큰변+1부터 작은변 + 큰변 - 1까지  
    for (let i = sides[1] + 1; i &lt;= sides[0] + sides[1] - 1; i++) {
    set.add(i)
    }

    console.log(set)
    return set.size
}

function solution(sides) {
    return findTriangleSide(sides)
}</code></pre>
<p>이게 대체 몇 줄 차이야. 아무리 공식이라지만... 그러니까 이번 기회에 기억해둬보자. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/7607a269-4ed0-4251-a567-8ae0ca0bf04c/image.png" alt=""></p>
<p>예? </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[260322 - KNOU 알고리즘 1]]></title>
            <link>https://velog.io/@liha_engineer/260322-KNOU-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1</link>
            <guid>https://velog.io/@liha_engineer/260322-KNOU-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1</guid>
            <pubDate>Sun, 22 Mar 2026 11:11:35 GMT</pubDate>
        </item>
        <item>
            <title><![CDATA[260224 - 뚝딱뚝딱 C# 문법 wk2]]></title>
            <link>https://velog.io/@liha_engineer/260224</link>
            <guid>https://velog.io/@liha_engineer/260224</guid>
            <pubDate>Tue, 24 Feb 2026 07:38:15 GMT</pubDate>
            <description><![CDATA[<h3 id="비주얼-스튜디오에서-코드-자동-정렬은-ctrl--k--d">비주얼 스튜디오에서 코드 자동 정렬은 Ctrl + K + D</h3>
<p>VS Code에서는 Ctrl + Shift + F 였던 걸로 기억하는데, 역시 IDE마다 다르다. 혹시 안 먹히면 정렬 하고싶은 부분 선택 혹은 전체 선택을 하고 눌러보자.</p>
<h3 id="지금은-구구단이-세로로-나오는데-가로로-나오게-하고-싶다면---i와-j의-위치를-뒤집자">지금은 구구단이 세로로 나오는데, 가로로 나오게 하고 싶다면 - i와 j의 위치를 뒤집자</h3>
<pre><code class="language-cs">for (int i = 2; i &lt;= 9; i++)
{
    for (int j = 1; j &lt;= 9; j++)
    {
        Console.WriteLine(i + &quot; x &quot; + j + &quot; = &quot; + (i * j));
    }
    Console.WriteLine();
}</code></pre>
<p>지금 코드는 이렇게 생겼다. </p>
<pre><code class="language-cs">            for (int i = 1; i &lt;= 9; i++)
            {
                for (int j = 2; j &lt;= 9; j++)
                {
                    Console.Write(j + &quot; x &quot; + i + &quot; = &quot; + (j * i) + &quot;\t&quot;);
                }
                Console.WriteLine();
            }</code></pre>
<p>이렇게 고쳐주면 된다. 
기존 구구단이 앞이 고정, 뒤가 움직이는 식이었는데, 우리 생각대로 가로로 찍히게 하려면 가로로 2x1, 3x1, 4x1이 찍히면 되는 식이었다. </p>
<p>뒤가 고정, 앞이 움직여야 하니 앞이 j, 뒤가 i이고 j는 2부터 시작, i는 1부터 시작인 것으로 뒤집어 주었다. </p>
<h3 id="for문도-무한-루프를-돌릴-수-있다---내부-조건을-다-생략해버리자">for문도 무한 루프를 돌릴 수 있다 - 내부 조건을 다 생략해버리자</h3>
<pre><code class="language-cs">for(;;)</code></pre>
<p>이렇게 쓰면 <code>while(true)</code> 처럼 무한루프에 빠진다. </p>
<h3 id="new-random과-new-randomnext0-n는-뭐가-다를까">new Random()과 new Random().Next(0, n)는 뭐가 다를까</h3>
<p>그냥 new Random()은 지정 시드 없이 초기화. (new Random(Int32)로 쓸 수도 있음.) Random().Next(n, m) 라고 쓰면 지정된 범위 내 임의의 정수 반환. (n이상 m미만)</p>
<h3 id="int로-int를-나누면-결과값을-double로-선언해도-소용이-없다">int로 int를 나누면 결과값을 double로 선언해도 소용이 없다</h3>
<pre><code class="language-cs">            int[] scores = new int[5];
            for (int i = 0; i &lt; scores.Length; i++)
            {
                Console.Write(&quot;학생 &quot; + (i + 1) + &quot;의 성적을 입력하세요. &quot;);
                scores[i] = int.Parse(Console.ReadLine());
            }

            int sum = 0;
            for (int i = 0; i &lt; scores.Length; i++) { sum += scores[i]; }

            double average = (double)sum / scores.Length;
            Console.WriteLine(&quot;성적의 평균은 &quot; + average + &quot;점 입니다.&quot;);</code></pre>
<p>여기서 <code>(double)sum / scores.Length;</code> 를 하지 않으면 int / int 타입이라서 average를 double로 선언해도 소용이 없다. 그래서 타입 캐스팅을 해주는 것. </p>
<h3 id="main-함수가-static이라서-실행이-안-된다">Main 함수가 static이라서 실행이 안 된다?</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/f443b3d3-3b8a-4bf0-9f17-12c325006747/image.png" alt=""></p>
<pre><code class="language-cs">namespace ConsoleApp4
{
    internal class Program
    {

        void PrintLine()
        {
            for (int i = 0; i&lt; 10; i++)
            {
                Console.WriteLine(&quot;=&quot;);
            }
        }


        public static void Main(string[] args)
        {
            Console.WriteLine(&quot;Hello, World!&quot;);
            PrintLine();
        }
    }
}
</code></pre>
<p>PrintLine() 함수는 정확히는 internal class인 Program 밑에 있는 메서드라서 Program.PrintLine() 으로 호출되어야 한다. 그런데 Main함수에 붙은 static은 인스턴스 (Program)를 생성하지 않고 그냥 실행시켜서, 이 PrintLine()이 어떤 클래스의 PrintLine()인지 알 수 없게 된다. 그래서 실행할 수 없는 것. </p>
<p>-&gt; 이건 Program.PrintLine() 이라고 써도 안 된다. 방법은 PrintLine()에다가 static을 붙이면 된다. (Main에서 static을 떼면 빌드 오류가 나기 때문)</p>
<blockquote>
</blockquote>
<h4 id="static-필드-클래스에서-딱-하나만-생기고-공유되는-변수">static 필드: 클래스에서 딱 하나만 생기고 공유되는 변수</h4>
<h4 id="static-메서드-인스턴스-없이-불러올-수-있는-메서드">static 메서드: 인스턴스 없이 불러올 수 있는 메서드</h4>
<h4 id="static이-붙은-메서드-내에서-다른-메서드를-호출하려면-걔도-static이-붙은-메서드여야-한다">static이 붙은 메서드 내에서 다른 메서드를 호출하려면 걔도 static이 붙은 메서드여야 한다.</h4>
<p>non static이면 <code>Program pr = new Program()</code> 이런 식으로 반드시 생성자를 써서, <code>pr.PrintLine()</code> 이런 식으로 호출해줘야 한다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/fa80985d-92b1-465f-a4fe-c4fbcdeebfd7/image.png" alt=""></p>
<p>이렇게 해주면 빨간 줄이 사라진다.</p>
<h3 id="비주얼-스튜디오에서-디버그-할때-메서드를-파고들고-싶다면---f11">비주얼 스튜디오에서 디버그 할때 메서드를 파고들고 싶다면 - F11</h3>
<p>F10을 누르면 콜스택이 메서드를 파고들지 않고 넘어가버린다. 메서드를 파고들고 싶다면 F11을 누르자. </p>
<h3 id="메서드-오버로딩을-볼-땐-매개변수만---반환값은-취급도-해주지-않는다">메서드 오버로딩을 볼 땐 매개변수만 - 반환값은 취급도 해주지 않는다</h3>
<blockquote>
<p>오버로딩: 같은 이름, 다른 동작</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/6b912db1-1b2a-4b8c-b966-262ea6b3d651/image.png" alt=""></p>
<p>이걸 잘 모르겠으면 늘 쓰던 <code>Console.WriteLine()</code> 을 입력해보면 오버로딩 18개를 볼 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/69ec502f-8b76-4240-b184-99846cabb379/image.png" alt=""></p>
<h3 id="사용자-정의-자료형의-시초---구조체">사용자 정의 자료형의 시초 - 구조체</h3>
<p>구조체는 값 형식(Value type) - 어딘가에 할당하거나 대입할 때 순전히 전부 복사가 일어난다. <strong>클래스와 대조되는 성질.</strong>
구조체는 struct 키워드를 사용해서 만든다. 필드와 메서드로 이루어져 있다. 
구조체도 클래스 비슷하게 <code>구조체이름.필드</code> 또는 <code>구조체이름.메서드</code> 식으로 접근한다. </p>
<h4 id="근데-구조체는-사실-클래스와는-상반되는-성질이라-잘-절충해서-사용해야-한다">근데 구조체는 사실 클래스와는 상반되는 성질이라 잘 절충해서 사용해야 한다.</h4>
<h3 id="maplength를-하면-터지는-이유---완전-고정배열이기-때문">map.Length를 하면 터지는 이유 - 완전 고정배열이기 때문</h3>
<p>JAVA의 length나 Javascript의 length를 생각하고 아무 생각없이 이차원배열 map의 map.Length를 for문의 인덱스에 걸어 썼던 나는 틱택토가 박살나는 광경을 보았다.</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/46b3192f-ca60-4fd7-ad12-ec967ba065c1/image.png" alt=""></p>
<p>엙? 찍어본 콘솔에는 map.Length()가 25가 찍히는 것을 보았다. 5*5로 전체 길이를 리턴하고 있었다. 다섯 줄이 있으니까 5가 나올거라는 예상은 잘못 되었다.</p>
<h4 id="내가-원하는-값을-뽑기-위한-메서드---arraygetlength몇번째">내가 원하는 값을 뽑기 위한 메서드 - Array.GetLength(몇번째)</h4>
<p>이 틱택토 맵의 경우 5개짜리가 5줄이니 뭘 써도 상관 없었다. <code>map.GetLength(0)</code> 으로 i값의 한계를 고치니 터지지 않고 무사히 돌아갔다. </p>
<pre><code class="language-cs">            int[,] map = new int[5, 5]
            {
                { 1,0,1,1,0},
                { 1,1,0,1,0},
                { 0,1,1,1,0},
                { 1,1,0,1,1},
                { 0,1,1,1,0}
            };


            for (int i = 0; i &lt; map.GetLength(0); i++)
            {
                for (int j = 0; j &lt; map.GetLength(0); j++)
                {
                    if (map[i, j] == 1)
                    {
                        Console.Write(&quot;■&quot;);
                    }
                    else
                    {
                        Console.Write(&quot;□&quot;);
                    }
                }
                Console.WriteLine();

            }</code></pre>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/79cae8ff-fffa-41fd-b2f4-3164d0c98e9a/image.png" alt=""></p>
<p>-&gt; 아니면 이 문제를 해결하려면 가변배열로 선언하면 된다. C#도 JAVA처럼 <code>int[][]</code> 방식으로 이차원배열을 선언할 수 있는데, 이 방식이 가변배열이다.  </p>
<h3 id="c의-필드는-기본적으로-private이다">C#의 필드는 기본적으로 private이다</h3>
<p>이건 아주 옛날에 항해99에서 자바스프링을 공부할 때 <a href="https://velog.io/@liha_engineer/springbegin2">영준님이 설명해주신 객체지향과 클래스 강의</a>가 기억나는 내용이다. 골자는 대충 이렇다.</p>
<blockquote>
</blockquote>
<p>설계도(클래스)를 숨길 순 없다. 그래서 대신 필드랑 메서드를 숨기는거다.</p>
<p>그래서 JAVA의 기본 접근제어자(생략)는 package-private인데, C#은 그냥 private으로 되어 있는 것 같다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/4dac1973-3d97-4743-829c-16ea2670c9a0/image.png" alt=""></p>
<p><del>환장하겠네.</del> <a href="https://math-development-geometry.tistory.com/5">참고 블로그</a>를 보면 일반적으로는 4개를 쓰는 것 같다. private, internal, protected, public. </p>
<h3 id="틱택토-마개조-하기---입력-값을-받아서-채워넣는-걸로-만들고-싶어요">틱택토 마개조 하기 - 입력 값을 받아서 채워넣는 걸로 만들고 싶어요</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[260222 - 뚝딱뚝딱 C# 문법 wk1]]></title>
            <link>https://velog.io/@liha_engineer/260222</link>
            <guid>https://velog.io/@liha_engineer/260222</guid>
            <pubDate>Sun, 22 Feb 2026 12:41:36 GMT</pubDate>
            <description><![CDATA[<h3 id="자동완성이-끊어졌다면-ctrl--space">자동완성이 끊어졌다면 Ctrl + Space</h3>
<p>비주얼 스튜디오에서 코드 입력 중 다른 걸 클릭해서 자동완성이 끊어지면, Ctrl + Space를 입력하면 다시 출력된다. </p>
<h3 id="제-프로젝트에는-왜-using-system이-없나요---전역-using-때문">제 프로젝트에는 왜 using System이 없나요 - 전역 using 때문</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/cf8aaf88-ca61-409d-b7cf-6f767e6a98bb/image.png" alt=""></p>
<p>프로젝트 &gt; (프로젝트 이름) 속성 클릭 </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/39014f5a-3b53-4a0c-9ac6-0866970280c8/image.png" alt=""></p>
<p>이렇게 전역 using 에 대한 내용이 나온다. 자주 쓰는 using을 미리 VS가 포함 시켜놓은 것. </p>
<h3 id="형변환---아닌-거-알아-그냥-해">형변환 - 아닌 거 알아. 그냥 해</h3>
<p>변수나 리터럴 앞에 그냥 붙여주면 <strong>한시적으로</strong> 형을 바꿔준다.</p>
<h4 id="명시적-형변환---수동으로-바꿔준다">명시적 형변환 - 수동으로 바꿔준다</h4>
<pre><code class="language-cs">int num1 = 10;
long num2 = (long)num1;</code></pre>
<p>이런 식으로 쓴다. </p>
<h4 id="묵시적-형변환---자동으로-바뀐다">묵시적 형변환 - 자동으로 바뀐다</h4>
<pre><code class="language-cs">byte num1 = 10;
int num2 = num1 
</code></pre>
<p>이 경우 자동으로 int로 바꿔준다. int를 float에 넣는 경우도 묵시적 형변환으로 float을 따라간다. 바뀌는 타입이 더 큰 경우 암시적으로 그냥 더 큰 걸로 따라간다 (업캐스팅은 묵시적인 경우가 많다고.)</p>
<h3 id="전위-연산자와-후위-연산자의-차이">전위 연산자와 후위 연산자의 차이</h3>
<p>전위 연산자는 연산할 준비를 이미 하고 변수를 만나는거라, 변수 만나는 순간 바로 연산 질러버림. (int x = 10; 이었다면 ++x; 하면 x는 11)
후위 연산자는 세미콜론으로 끝나면 다음줄에 하겠다는 표시.</p>
<h3 id="연산자-우선순위">연산자 우선순위</h3>
<p>간단하게 보고만 가면 다음과 같다.</p>
<blockquote>
<p><em>(높음)</em> <strong>괄호 &gt; 단항 &gt; 산술 &gt; 시프트 &gt; 관계 &gt; 논리 &gt; 할당</strong> <em>(낮음)</em></p>
</blockquote>
<h3 id="replace는-원본은-두고-복사해와서-바꾼다">replace는 원본은 두고 복사해와서 바꾼다</h3>
<pre><code class="language-cs">string str1 = &quot;Hellwo, World!&quot;;
string newStr = str1.Replace(&quot;World&quot;, &quot;Universe&quot;;
Console.WriteLine(newStr);
Console.WriteLine(str1);</code></pre>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/ac1342f2-217d-4e8d-af18-2ba9df76a4d0/image.png" alt=""></p>
<p>그러면 이렇게 나온다.</p>
<h3 id="stringcomparestr1-str2는-ascii-비교로-1-0--1을-출력한다">string.Compare(str1, str2)는 ASCII 비교로 1, 0, -1을 출력한다</h3>
<p>이게 -1이 나오는 이유는 음수라는 얘기. ASCII에서 &#39;A&#39; = 65, &#39;a&#39; = 97이라 소문자들이 값이 훨씬 크다. <code>str1 = &quot;Hello, World!&quot;</code> 이고 <code>str2 = &quot;hhhhhhh&quot;</code> 이므로, str2의 값이 더 커서 -1이 출력되는 것. </p>
<h3 id="많이-쓰는-포맷팅---stringformat과-변수">많이 쓰는 포맷팅 - string.Format()과 $&quot;{변수}&quot;</h3>
<pre><code class="language-cs">            string name = &quot;LIHA&quot;;
            int age = 27;
            string message = string.Format(&quot;My name is {0} and I&#39;m {1} years old.&quot;, name, age);
            Console.WriteLine(message);
            message = $&quot;Hello! I&#39;m {name} and {age} years old.&quot;;
            Console.WriteLine(message);</code></pre>
<p>위와 같이 쓰면 이렇게 나온다.</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/8a78da2e-e735-413d-a528-67581cc0551b/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[250130 - 우당탕탕 프로젝트 뼈대 갈아엎기 ]]></title>
            <link>https://velog.io/@liha_engineer/250130</link>
            <guid>https://velog.io/@liha_engineer/250130</guid>
            <pubDate>Thu, 29 Jan 2026 16:04:03 GMT</pubDate>
            <description><![CDATA[<h3 id="최종-골자---프론트-razor-pages--백-클래스-라이브러리">최종 골자 - 프론트: Razor Pages / 백: 클래스 라이브러리</h3>
<p>src/
└PinkOtter.IChing.Core -&gt; 클래스 라이브러리 (dll)
└PinkOtter.IChing.Web -&gt; ASP.NET Core 웹앱 (Razor Pages)</p>
<h3 id="클래스-라이브러리는-뭔가요---c은-결국-dll로-빌드하기에">클래스 라이브러리는 뭔가요 - C#은 결국 dll로 빌드하기에</h3>
<p>GPT 할매, Gemini 할매와 함께 셋이서 머리를 맞대고 구현해 나가려고 큰 결심(?)을 하기가 무색하게 첫 번째부터 이해가 되지 않았다. 
일단 비주얼 스튜디오 자체가 낯선 나에게는 솔루션의 하위 개념으로 프로젝트를 생성한다는 것도 상당히 낯설었다. 
그렇게 이리저리 헤매던 차에 백단 프로젝트 생성을 클래스 라이브러리로 만들라는 것. 이 의문에 대한 GPT 할매의 답변은 다음과 같다. </p>
<blockquote>
</blockquote>
<p>웹사이트(웹앱)도 결국은 DLL로 빌드된다.
니가 실행하는 “웹 프로젝트”도 내부적으로는 DLL이 만들어지고, 그 DLL을 dotnet 런타임이 실행시키는 거다. </br>
그리고 클래스 라이브러리(DLL) 는 “웹이냐 아니냐”가 아니라,
그냥 재사용 가능한 코드 묶음(모듈) 이라고 생각하면 된다.</p>
<h3 id="기존-프로젝트-내부에-디렉토리가-있는데-안-보인다면">기존 프로젝트 내부에 디렉토리가 있는데 안 보인다면</h3>
<p>솔루션 탐색기 상단의 &#39;모든 파일 표시&#39; 를 누르면 빈 폴더 모양으로 뜰 것. 
원하는 빈 폴더에 우클릭 하고 &#39;프로젝트에 포함&#39; 을 누르면 된다.</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/ee25d6e7-a80e-46b3-a4c9-648fa3d5c9d7/image.png" alt=""></p>
<h3 id="왜-dll-파일을-찾을-수-없는걸까">왜 dll 파일을 찾을 수 없는걸까</h3>
<blockquote>
</blockquote>
<p>&#39;C:\Users\LIHA\Desktop\pinkotter-iching\src\PinkOtter.IChing.Core\bin\Debug\PinkOtter.IChing.Core.dll&#39; 메타데이터 파일을 찾을 수 없습니다.</p>
<p>라는 에러가 계속 뜨면서 빌드에 실패했다. 원인은 솔루션이 프로젝트를 불러오면서 무언가 참조가 꼬인 것으로 보인다. 
시도해본 방법은 다음과 같다. </p>
<ol>
<li>솔루션에서 제거 후 다시 추가 </li>
<li>솔루션 다시 빌드 시도 (실패) </li>
<li>VS 끄고 해당 경로 가서 bin 폴더랑 obj 폴더 삭제</li>
<li>VS 다시 켜서 솔루션 불러온 후 다시 실행 </li>
</ol>
<p>이 와중에 <code>현재 솔루션에 알수없는 프로젝트 구성 매핑이 있다</code>는 오류 메시지도 떠서 Debug 콤보박스의 구성 관리자를 들어가 보니, 프로젝트 목록에 Web만 있고 Core가 없었다. 
아마 클래스 라이브러리인 Core의 xml 구성이 잘못된 것도 영향이 있을 것 같아 xml을 수정했다. 영향이 있는진 모르겠지만... 왠지 해결되었다. 
Gemini 할매가 준 코드는 다음과 같다. </p>
<pre><code class="language-xml">&lt;Project Sdk=&quot;Microsoft.NET.Sdk&quot;&gt;

    &lt;PropertyGroup&gt;
        &lt;TargetFramework&gt;net8.0&lt;/TargetFramework&gt;
        &lt;ImplicitUsings&gt;enable&lt;/ImplicitUsings&gt;
        &lt;Nullable&gt;enable&lt;/Nullable&gt;
        &lt;GenerateAssemblyInfo&gt;false&lt;/GenerateAssemblyInfo&gt;
    &lt;/PropertyGroup&gt;

&lt;/Project&gt;</code></pre>
<h3 id="read-only라니-그게-무슨-소리요-vs-양반">read-only라니 그게 무슨 소리요 VS 양반</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/7f2dcf9b-545d-428f-a02b-875d08a857d1/image.png" alt=""></p>
<p>이렇게 나오는거 보고 대체 뭐야? 싶었는데 원인은 저 줄의 위치 때문. 
builder.Services. ~ 항목들은 <code>var app = builder.Build();</code> 위에 위치해야 한다고. 
그래서 위에 추가한 서비스들 준비 다 돼서 빌드하겠다는 얘기가 <code>var app = builder.Build();</code> 라서, 그 뒤로는 read-only가 된다고 한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[250116 -Program은 왜 internal class일까]]></title>
            <link>https://velog.io/@liha_engineer/250116</link>
            <guid>https://velog.io/@liha_engineer/250116</guid>
            <pubDate>Thu, 15 Jan 2026 18:16:41 GMT</pubDate>
            <description><![CDATA[<h3 id="class는-알겠는데-internal-class는-뭔가요">class는 알겠는데 internal class는 뭔가요</h3>
<p>.NET Framework로 C# 기초를 하다보니 문득 궁금해진 부분이 있었다. </p>
<pre><code class="language-cs">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InflearnConsoleApp
{

    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(&quot;글자를 찍어봅시다&quot;);
        }
    }
}
</code></pre>
<p>뼈대 코드가 이런 식으로 구성되는 것이다. 그냥 class는 알겠는데 internal class는 뭐란 말인가. <a href="https://jeongeunji1127.tistory.com/25">참고 블로그</a>를 보며 이런 궁금증을 나만 가진 건 아니구나 느낄 수 있었다. 내가 아는 접근제어자는 JAVA에서 나온 것인데 private, default(package-private), protected, public 이었다. 기억을 되살릴 겸 이들의 범위가 어디인지도 적어보자.</p>
<blockquote>
<p><strong>JAVA의 접근제어자 별 사용가능 범위</strong></p>
</blockquote>
<ul>
<li>private - 같은 클래스 내에서만</li>
<li>package-private - 같은 패키지</li>
<li>protected - 같은 패키지 및 다른 패키지 내 상속받은 클래스 </li>
<li>public - Anywhere!</li>
</ul>
<p>그래서 internal은 무슨 접두어일까 궁금했는데, <strong>하나의 어셈블리 단위 내에서만 접근을 허용</strong>한다고 한다. 어셈블리 단위...? 🤔</p>
<blockquote>
<p>어셈블리: 프로그램 기본 단위. 빌드시 생성되는 dll 및 exe 파일</p>
</blockquote>
<p>그래서 internal이 붙은 멤버는 같은 어셈블리 코드에서만 사용할 수 있다고. 동일 어셈블리에서는 public 취급, 다른 어셈블리에서는 private 취급. </p>
<h3 id="전부터-궁금했던-것---그러고보니-dll은-뭔가요">전부터 궁금했던 것 - 그러고보니 dll은 뭔가요</h3>
<p>위에서 <code>using System;</code> 을 하고있기 때문에 <code>Console.WriteLine()</code>을 쓸때 <code>System.Console.~</code> 이라고 쓰지 않아도 되는 것이다. 이때 System은 정확히는 System.dll이라고 한다. 또한 빌드하면 dll과 exe가 생기는데 exe는 실행 파일이고... dll은 뭘까? 여기저기 참고 블로그들을 좀 살펴보았다. 
<a href="https://youngseong.tistory.com/344">참고블로그1</a></p>
<p><strong>동적 링크 라이브러리(Dynamic Link Library)</strong> 파일. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[260112 - Re:zero부터 시작하는 express]]></title>
            <link>https://velog.io/@liha_engineer/260112</link>
            <guid>https://velog.io/@liha_engineer/260112</guid>
            <pubDate>Sun, 11 Jan 2026 19:46:00 GMT</pubDate>
            <description><![CDATA[<h3 id="nodejs-기본-사용-문법도-있다---복잡하고-번거로워-그렇지">Node.js 기본 사용 문법도 있다 - 복잡하고 번거로워 그렇지</h3>
<pre><code class="language-js">const server = http.createServer((req, res) =&gt; {
  console.log(&quot;req.url: &quot;, req.url);

  if (req.url == &quot;/hello&quot;) {
    const helloHTML = fs.readFileSync(&quot;static/hello.html&quot;, &quot;utf-8&quot;);

    res.writeHead(200, { &quot;content-type&quot;: &quot;text/html&quot; });
    res.write(helloHTML);
    res.end();
  } else if (req.url == &quot;/&quot;) {
    const homeHTML = fs.readFileSync(&quot;static/home.html&quot;, &quot;utf-8&quot;);

    res.writeHead(200, { &quot;content-type&quot;: &quot;text/html&quot; });
    res.write(homeHTML);
    res.end();
  } else {
    serveStatic(&quot;static&quot;, req, res);
  }
});</code></pre>
<p>이게 Node.js 기본 문법이다. express나 Nest.js 같은 서버 프레임워크를 쓰지 않고 쌩 Node.js도 이렇게 쓸 수는 있다. 그러나 보통 Node.js가 기술스택이라고 하면 express, Nest를 떠올린다.(가끔 예외로 net 모듈 같은 것도 있긴 하지만)</p>
<pre><code class="language-js">const express = require(&quot;express&quot;)
const app = express()
const PORT = 3000;

app.use(express.static(&quot;public&quot;))

app.get(&quot;/&quot;, (req, res) =&gt; {
    res.send(&quot;&lt;h1&gt; This is root directory! Hello! &lt;/h1&gt;&quot;)
})</code></pre>
<p>express를 사용하면 이렇게 깔끔해진다. </p>
<h3 id="미들웨어라는-비밀병기를-가진-서버-프레임워크-express">미들웨어라는 비밀병기를 가진 서버 프레임워크, express</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/97a39e97-ee98-49d3-ad51-83eef2ef76ad/image.png" alt=""></p>
<p>미들웨어는 기본적으로 이런 식으로 next() 메서드를 통해 다음 미들웨어로 점프한다. 이 간결한 구조가 Node 기본 문법에 비해 편의성이 높아 애용되는 편.</p>
<h3 id="appuse로-정적-파일을-읽어올땐---그냥-경로만-변경해서-접근하면-된다">app.use로 정적 파일을 읽어올땐 - 그냥 경로만 변경해서 접근하면 된다!</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/83192076-e086-401f-86e8-8baf2be51938/image.png" alt=""></p>
<p>이런 식으로 products 폴더에 정적 리소스를 포함하고 app.use를 통해 읽어들이기까지 완료했다. 그러면 루트경로 하에 추가되었을텐데, 어떻게 접근하면 좋을까?
-&gt; 그냥 /image.png 이런 식으로 접근하면 된다!</p>
<h3 id="expressjson을-쓰는-이유-json의-이점-때문">express.json()을 쓰는 이유? JSON의 이점 때문</h3>
<ul>
<li>가독성: 사람이 읽고 이해하기 쉬움</li>
<li>표준화: 대부분의 프로그래밍 언어와 호환, 데이터 교환의 표준 포맷</li>
<li>경량성: 텍스트 기반 구조로 적은 오버헤드, 네트워크 대역폭의 효율적 사용</li>
</ul>
<p>이런 장점을 가지는 JSON을 좀더 편하게 사용하려면, app.js나 index.js에서 <code>app.use(express.json())</code> 을 선언해주어야 한다. 이게 있어야 JSON으로 송수신 하는 데이터에서 파싱을 쉽게 할 수 있기 때문. </p>
<h3 id="expressurlencoded를-이용해-데이터를-안전하게-주고받자">express.urlencoded()를 이용해 데이터를 안전하게 주고받자</h3>
<blockquote>
<p>app.use(express.urlencoded({extended:true}))</p>
</blockquote>
<p>express.urlencoded()를 app.use()로 등록해주면 요청 객체를 req.body에 저장한다. 그러면 서버 코드에서 사용자가 전송한 데이터를 쉽게 사용할 수 있다. </p>
<p>가끔 안에 <code>{extended:true}</code> 이렇게 쓰는 경우가 있는데, 이는 중첩객체 허용여부. true로 놓으면 <code>{user:{name:&#39;John&#39;, age:&#39;30&#39;}, hobbies:[&#39;reading&#39;, &#39;gaming&#39;]}</code> 이렇게 복잡하거나 중첩된 객체도 쓸 수 있다. false로 해놓으면 못 쓰니 이런 구조를 쓰려면 반드시 true로 놓도록 하자.</p>
<h3 id="express는-한-키에-여러-값이-전달되면-배열로-처리한다">express는 한 키에 여러 값이 전달되면 배열로 처리한다</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/e4db96e1-feec-4130-b574-20737d96b620/image.png" alt=""></p>
<p>이렇게 생긴 라우터에 tags라는 키에 여러 값을 준다고 생각해보자 (해시태그 처럼)</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/4a206579-873e-4efd-b0c2-9f0c2bf42b1d/image.png" alt=""></p>
<p>이렇게 배열로 처리되어 표시해준다. </p>
<h3 id="csr과-ssr은-뭐가-다를까">CSR과 SSR은 뭐가 다를까?</h3>
<h4 id="csr의-특징">CSR의 특징</h4>
<blockquote>
<p>동적 생성
초기 로딩 성능
서버 부하 감소
SEO 문제 - 웹 크롤러가 JS를 실행하지 않고 HTML만을 분석, 동적 컨텐츠만을 인식하기 때문
편의성 - React, Vue의 톡톡한 역할</p>
</blockquote>
<ul>
<li>사용자 상호작용이 많고 동적 컨텐츠 변경이 빈번한 싱글 페이지에서는 유용!</li>
</ul>
<h4 id="ssr의-특징">SSR의 특징</h4>
<p>HTML을 서버가 미리 생성해서 클라이언트에게 전달. 이 과정에서 템플릿 엔진 등이 사용된다. </p>
<blockquote>
</blockquote>
<p>빠른 초기 로딩 성능
SEO
서버 부하 증가
개발 복잡성 증가</p>
<h3 id="뷰-엔진과-템플릿-엔진">뷰 엔진과 템플릿 엔진</h3>
<p>뷰 엔진: SSR의 핵심. 서버에서 HTML을 동적으로 생성하여 클라이언트에 전달하는 역할. </p>
<p>템플릿 엔진: 서버에서 처리된 데이터를 웹페이지에 동적으로 삽입하여 사용자에게 보여질 컨텐츠를 생성하는데 사용됨. pug, handlebars, ejs 등이 있음. </p>
<pre><code class="language-js">app.set(&quot;view engine&quot;, &quot;ejs&quot;)
app.set(&quot;views&quot;, &quot;./views&quot;)</code></pre>
<p>이런 식으로 app.set으로 사용 설정을 할 수 있는데, 이때 views 폴더의 경로는 상대경로와 절대경로 모두 설정할 수 있다.</p>
<pre><code class="language-js">app.set(&quot;views&quot;, &quot;./src/views&quot;) //상대경로
app.set(&quot;views&quot;, path.join(__dirname, &quot;src&quot;, &quot;views&quot;)) // 절대경로</code></pre>
<h3 id="appget-과-routerget-은-뭐가-다를까">app.get() 과 router.get() 은 뭐가 다를까?</h3>
<p>app.<del>은 애플리케이션 전체의 라우터와 미들웨어 관리에 사용되고, express 라우터인 router.</del>은 작은 애플리케이션처럼 동작하면서 app객체와 동일한 메서드를 사용하여 라우터를 정의할 수 있다. </p>
<h4 id="express-라우터의-장점">express 라우터의 장점</h4>
<ul>
<li>모듈화 및 구조화</li>
<li>관리의 용이성</li>
<li>성능 및 보안 강화</li>
</ul>
<h3 id="express가-제공하는-응답-처리-방법들">express가 제공하는 응답 처리 방법들</h3>
<blockquote>
</blockquote>
<p>res.send() - 다양한 유형의 응답을 보낼때 쓰는 가장 기본적 응답 유형
res.json() - JSON으로 응답할 때 사용
res.sendFile() - 파일 경로를 인자로 받음. 클라이언트에게 파일 전송
res.status() - http상태코드 반환용
res.setHeader() - http 헤더 설정 시 사용
res.download() - 클라이언트가 파일 다운로드 하도록 함
res.redirect() - 클라이언트를 다른 url로 리다이렉트 </p>
<h3 id="비동기-작업의-오류는-자동으로-catch되지-않는다">비동기 작업의 오류는 자동으로 catch되지 않는다</h3>
<p>굳이 try-catch 블록을 씌워주는 이유이다. setTimeout이나 async-await 구문 등에서는 자동으로 잡아주지 않기 때문에 직접 잡아 다음으로 보내줘야 한다. </p>
<p>하나 더 팁. 에러처리 미들웨어는 특별한 조건이 없다면 가장 가까운 것을 호출한다.</p>
<h3 id="uuid를-require-하려고-했는데-왜-안되지-대-import의-시대">uuid를 require 하려고 했는데 왜 안되지? 대 import의 시대</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/172bc066-dddd-40a4-a6f4-839c09659e2a/image.png" alt=""></p>
<p>역시나 나와 같은 수많은 오류들을 거쳐온 <a href="https://stackoverflow.com/questions/79758051/how-to-use-uuid-with-node-js-v20-when-require-throws-err-require-esm">스택 오버플로우 웨건</a>이 답을 주었다. 결론은 <strong>No longer support for require()</strong> 인것. <code>&quot;type&quot; : &quot;module&quot;</code> 을 package.json에 써넣고 import()를 사용하라는 것이다. </p>
<h3 id="그렇다면-import와-require를-같이-사용할-수는-없을까">그렇다면 import와 require를 같이 사용할 수는 없을까?</h3>
<p><a href="https://yurison.tistory.com/645">참고 블로그</a>를 보고 함께 사용하는 방법을 알 수 있었다. 골자는 다음과 같다.</p>
<blockquote>
</blockquote>
<ol>
<li>package.json에 &quot;type&quot;:&quot;module&quot; 추가하고 저장해서 모듈시스템 사용</li>
<li>아래 import문과 const문 상단에 추가하기
import {createRequire} from &quot;module&quot;
const require = createRequire(import.meta.url)</li>
</ol>
<h4 id="아니-근데-왜-저걸-해도-터지지-결론은-import">아니 근데 왜 저걸 해도 터지지? 결론은 import</h4>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/4f890387-28c8-40ac-af13-4cc2cb99fe28/image.png" alt=""></p>
<p>-&gt; 결론은 대 import의 시대와 같다. index.js에 require로 불러온 js파일이 있었는데 더이상 require를 지원하지 않으니 import로 불러오기 하라는 것이다. type : module을 쓰는 대신 require도 혼용할 수 있도록 import 하고 const로 선언했는데도 이런 오류가 뜬다.</p>
<p>유데미 강의를 들으며 따라하고 있는데 아마 촬영시기와 내가 학습하는 시기의 시차로 인해 강의는 require를 쓰는데 더이상 require를 지원하지 않는 디펜던시가 있어 그런 것 같다. </p>
<p>GPT에게 물어보니 답변은 다음과 같았다.</p>
<blockquote>
</blockquote>
<ul>
<li>import와 require의 혼용은 권장하지 않는다. (실제로 혼용해보려고 애쓰다가 에러남)</li>
<li>require 쓰려고 모듈의 버전을 억지로 낮춰 사용하는 것도 권장하지 않는다</li>
<li>현업에서 require를 쓰는건 맞지만 import로 바꾸기엔 규모가 너무 커서 그냥 쓰는 것이고, 신규 프로젝트는 import를 많이 쓴다</li>
<li>지금 니 프로젝트 구조는 이미 ESM이니까 이왕이면 import로 바꾸는게 낫다</li>
<li>강의때문에 require를 유지하고 싶으면 uuid만 import해서 우회하는 방법도 있다</li>
</ul>
<p>라고 한다. 해서 uuid만 import하는 방식으로 바꿔봤지만, 그랬더니 js파일 require 부분도 걸려있다. require와 import를 병용해볼까도 고민했지만 권장하는 방법이 아니라고 하니 import로 바꿔 정리하고 있다. </p>
<h3 id="require에서는--import에서는-as">require에서는 :, import에서는 as</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/1d087869-1b27-4557-9a6b-a186a0f3fd46/image.png" alt=""></p>
<p>named import 시 별칭을 쓰는 방법이 다르다. require로 불러올때는 콜론으로 구분하는데 import로 불러올때는 as를 써줘야 별칭을 쓸수있다. </p>
<h3 id="내-yarn이-왜-고장났지-yarn-422를-쓰는-방법">내 yarn이 왜 고장났지? yarn 4.2.2를 쓰는 방법</h3>
<p>패키지 매니저로 yarn을 사용하려면 단순히 npm install -g yarn을 쓰고 넘어갈 수도 있다. (이러면 1.22.22) 그러나 yarn은 사실 4.2.2 버전까지 나와있다. 남들은 에러메시지가 떠서 yarn을 업그레이드 하면 해결된다는데, 나는 yarn을 업그레이드 했더니 에러메시지가 떠서 굉장히 고생을 했다. 
(원인은 아마 Node를 22에서 24로 업그레이드 한 탓인 것 같다.)</p>
<p>문제상황: 나는 yarn 4.2.2(yarn berry)를 깔았는데 yarn -v 하면 자꾸 1.22.22가 뜨고, 이 프로젝트의 yarn 버전은 4.2.2인데 너는 1.22.22를 쓰고있다는 에러메시지와 함께 아무것도 할 수 없었다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/baf319d9-af55-40c5-ad7c-794caae58ddf/image.png" alt=""></p>
<pre><code>error This project&#39;s package.json defines &quot;packageManager&quot;: &quot;yarn@4.2.2&quot;. However the current global version of Yarn is 1.22.22.

Presence of the &quot;packageManager&quot; field indicates that the project is meant to be used with Corepack, a tool included by default with all official Node.js distributions starting from 16.9 and 14.19.     
Corepack must currently be enabled by running corepack enable in your terminal. For more information, check out https://yarnpkg.com/corepack.
Installing yarn@4.2.2 in the project...</code></pre><p>아니! <del>환장할 노릇이네</del> 분명히 corepack enable도 하고 corepack use <a href="mailto:yarn@4.4.2">yarn@4.4.2</a>도 했는데 자꾸 1.22.22가 잡히는 것이었다. where yarn 하면 아무 경로도 잡히지 않고...</p>
<p>GPT가 알려준 현 상황과 해결책은 대강 이렇다. </p>
<blockquote>
</blockquote>
<ul>
<li>corepack yarn -v 했을때 4.2.2면 제대로 깔린 건 맞다</li>
<li>다만 yarn -v에서 1.22.22로 나오는건 그 버전이 제대로 지워지지 않았기 때문인 것 같다</li>
<li>Get-Command yarn -All 해서 <code>C:\Users\LIHA\AppData\Roaming\npm\</code> 에 <code>yarn.cmd</code>가 있으면 1.22.22가 환경변수로 여기 남아있을 가능성이 크다</li>
<li><code>C:\Users\LIHA\AppData\Local\Yarn\bin\</code> 이것도 뜬다면 옛날 yarn 설치 흔적이 있으니 거의 확정</li>
<li>그러니 위 경로에 가서 쟤네를 지우는 것이 가장 깔끔하다</li>
</ul>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/5cd9c98c-d791-41d6-a0e9-a882183bcc43/image.png" alt=""></p>
<p>하여 환경변수 경로 가서 yarn 관련 파일들을 모두 날려주니 정상적으로 4.2.2가 출력되었다. </p>
<h3 id="html-5-기본뼈대를-자동-입력하려면-html5를-입력후-엔터하자">HTML 5 기본뼈대를 자동 입력하려면 html:5를 입력후 엔터하자</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/45959f6b-8cc4-4df1-89b8-51bcae10627f/image.png" alt=""></p>
<p>왜 나는 그간 !DOCTYPE 부터 타이핑하고 있었던걸까. 흑흑. 이걸... 이걸 치면 되는 것이었어! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[260106 - Re:zero부터 시작하는 Node.js]]></title>
            <link>https://velog.io/@liha_engineer/260106</link>
            <guid>https://velog.io/@liha_engineer/260106</guid>
            <pubDate>Mon, 05 Jan 2026 15:15:49 GMT</pubDate>
            <description><![CDATA[<h3 id="yarnlock이-생겨야-하는데-왜-자꾸-package-lockjson이-생기는거야">yarn.lock이 생겨야 하는데 왜 자꾸 package-lock.json이 생기는거야?</h3>
<blockquote>
<p>npm install <strong>-g</strong> yarn 을 해준다 &lt;&lt; 여기서 글로벌로 선언 안했을 가능성 高
yarn init -y 를 친다
yarn add express 를 친다</p>
</blockquote>
<p>위 순서대로 했는데도 package-lock.json이 생긴다면 그냥 조용히 삭제해주자. 
아마 npm install yarn 때 생기는 경우가 많을 것 (-g 해줘야 안 생긴다)
지금은 기억하겠지만 기억하지 못할 나중을 위해 적자면, lock 파일이 두개 있어선 안된다. yarn.lock을 쓰든 package-lock.json을 쓰든 한개만 남겨야 한다. 이 둘은 git에 커밋되어야 한다. </p>
<h3 id="tcp---악수만-세-번--udp---입벌려-패킷-들어간다">TCP - 악수만 세 번 / UDP - 입벌려 패킷 들어간다</h3>
<h4 id="tcp의-특징---생일파티-초대장-돌리기">TCP의 특징 - 생일파티 초대장 돌리기</h4>
<ul>
<li>신뢰성</li>
<li>연결 기반</li>
<li>데이터 순서 보장</li>
</ul>
<h4 id="udp의-특징---공원의-물총싸움">UDP의 특징 - 공원의 물총싸움</h4>
<ul>
<li>비연결성</li>
<li>빠른 전송</li>
<li>패킷 순서 미보장, 손실 가능성</li>
</ul>
<h3 id="http는-전송-계층의-tcp-연결-위에서-돌아가는-프로토콜">HTTP는 전송 계층의 TCP 연결 위에서 돌아가는 프로토콜</h3>
<p>현대 웹의 근간. TCP랑은 다르게 7층인 애플리케이션 계층에서 사용된다. 웹 소켓 또한 HTML5에서 등장한 TCP 기반 통신이라 7층에서 돌아간다. 
하지만, 그냥 TCP 통신은? 4층인 전송 계층의 프로토콜. 그러니 헤더가 무겁든 어쩌든 TCP를 이용한 방법이 당연히 더 빠르다. </p>
<h4 id="http의-특징">HTTP의 특징</h4>
<ul>
<li>효율성 -&gt; 필요한 시점에만 연결한다</li>
<li>상태 비저장성 -&gt; Stateless (철수가 늘 먹던걸로. 해도 사장님은 모르는게 HTTP)</li>
</ul>
<h3 id="require모듈-형태의-cjs는-생각보다-아직-현업에-많다고-한다">require(&quot;모듈&quot;) 형태의 CJS는 생각보다 아직 현업에 많다고 한다</h3>
<p>유데미 강의가 require 문을 쓰는 형태라 당황했다. 그러고보니 구매해놓은 다른 Node 강의도 ES5 이하의 CJS 문법을 쓴다. </p>
<h3 id="서버를-띄우려고-했더니-permission-denied---네트워크-드라이버의-문제">서버를 띄우려고 했더니 permission denied - 네트워크 드라이버의 문제</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/78e5fe4a-65dc-4579-8a1c-79c4fd126425/image.png" alt=""></p>
<blockquote>
<p>Error: listen EACCES: permission denied 0.0.0.0:3000</p>
</blockquote>
<p>아니 이게 뭐야. 무슨 permission이 왜 denied야? 
하지만 <a href="https://velog.io/@gusdh2/Next.js-Error-listen-EACCES-permission-denied-0.0.0.03000-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95">참고 블로그</a> 덕분에 무사히 해결했다. 네트워크 드라이브를 멈췄다가 다시 실행해주면 ok</p>
<ol>
<li>cmd를 <strong>관리자 권한</strong>으로 실행한다</li>
<li><code>net stop winnat</code> 을 입력한다</li>
<li><code>net start winnat</code> 을 입력한다</li>
</ol>
<p>이 과정으로 해결.</p>
<h3 id="엉뚱하지만-문득-서버-주소가-궁금했다">엉뚱하지만 문득 서버 주소가 궁금했다</h3>
<p>역시나 고마운 <a href="https://stackoverflow.com/questions/41540093/how-do-you-print-the-address-of-an-http-server-in-node-js">스택 오버플로우 웨건</a>이 해결해 주었다. </p>
<pre><code class="language-js">// Source - https://stackoverflow.com/a/41540536
// Posted by BlackMamba
// Retrieved 2026-01-12, License - CC BY-SA 3.0

var http = require(&#39;http&#39;);
var server = http.createServer(function (req, res) {
  res.writeHead(200, {&#39;Content-Type&#39;: &#39;text/plain&#39;});
  res.end(&#39;Hello World\n&#39;);
}).listen(8080);
console.log(&#39;Server listening:&#39;, `http://${server.address().address}:${server.address().port}`);
</code></pre>
<p>이런식으로 쓰라고 하기에 똑같이 써보니 잘 되었다.</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/6c02240c-01aa-49f6-83bb-6f37ae79f756/image.png" alt=""></p>
<h3 id="커맨드라인에서-http요청을-보내는-명령어-curl">커맨드라인에서 HTTP요청을 보내는 명령어 curl</h3>
<p>이 명령어는 git bash에서 사용해야 하니 터미널 추가 시 git bash를 선택해주자. -v는 요청과 응답 송수신의 상세를 볼 수 있는 명령어이다. </p>
<blockquote>
<p>curl <a href="http://localhost:3000">http://localhost:3000</a> -v</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/98127927-da6b-4cc9-85da-5a8a8d79ab97/image.png" alt=""></p>
<p>이렇게 무사히 송수신 되었음을 볼 수 있다. 저기서 <code>Accept:*/*</code> 아랫줄이 비어있는 이유는 요청 시에 아무 내용도 넣지 않았기 때문이라고. 
아울러 잊고있던 localhost 주소가 127.0.0.1임을 상기했다 (...)</p>
<h3 id="그래서-라우터는-정확히-무엇일까">그래서 라우터는 정확히 무엇일까</h3>
<pre><code class="language-js">server.listen(PORT, () =&gt; {
  console.log(`Server is listening on port ${PORT}`);
});</code></pre>
<p>이렇게 써있는 것을 보고 <code>서버는 3000번 포트에서 HTTP 트래픽 수신을 대기한다</code> 고 한다. 서버 자체는 HTTP 트래픽이 언제 어디서 발생하는지 신경쓰지 않으며, 요청이 오면 정의한 콜백함수를 실행할 뿐이다.  </p>
<p>그래서 요청의 경로에 따라 다른 응답을 보내주려면 개발자가 직접 구현해야 한다. 이것이 라우팅이고, 이렇게 정의된 개별 로직의 단위가 라우터.</p>
<h3 id="mime-type-문서나-데이터의-형식을-나타내는-정보">MIME-TYPE? 문서나 데이터의 형식을 나타내는 정보</h3>
<p>웹 개발에서 이는 상당히 중요하다. 여러 종류의 타입이 있는데 일부를 보자면 다음과 같다.</p>
<blockquote>
</blockquote>
<p>text/html
text/plain
text/css
application/javascript
image/jpeg
image/png
application/pdf
application/json</p>
<p>웹서버에서는 이런 컨텐츠 타입을 분석하여 MIME 타입을 설정하고, HTTP 응답헤더의 컨텐츠 타입 필드에 포함하여 클라이언트에게 전송한다.</p>
<h3 id="정적-데이터가-수백만인데-일일이-if문을-걸-수는-없다---정적-파일-처리-함수를-구현해보자">정적 데이터가 수백만인데 일일이 if문을 걸 수는 없다 - 정적 파일 처리 함수를 구현해보자</h3>
<pre><code class="language-js">const serveStatic = (rootDir, req, res) =&gt; {
  const filePath = path.join(rootDir, req.url);
  fs.readFile(filePath, (err, data) =&gt; {
    if (err) {
      if (err.code === &quot;ENOENT&quot;) {
        res.writeHead(404, { &quot;content-type&quot;: &quot;text/html&quot; });
        res.end(&quot;&lt;h1&gt; 404 Not Found! &lt;/h1&gt;&quot;);
      } else {
        res.writeHead(500, { &quot;content-type&quot;: &quot;text/html&quot; });
        res.end(&quot;&lt;h1&gt; 500 Internal Server Error! &lt;/h1&gt;&quot;);
      }
    } else {
      const extname = path.extname(filePath);
      const content = contentType.getContentType(extname);
      res.writeHead(200, { &quot;content-type&quot;: content });
      res.end(data);
    }
  });
};</code></pre>
<p>우선 이런 식으로 최소한의 뼈대만 구현. </p>
<h3 id="왜-자꾸-터지는걸까-resend가-또-있었기-때문">왜 자꾸 터지는걸까? res.end()가 또 있었기 때문</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/adb486e0-2432-4516-83d7-f0239ccae261/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/ad3b2596-8cc9-457f-91b9-f0e17adffc08/image.png" alt=""></p>
<p>자꾸 이렇게 터지면서 홈페이지가 나오지 않는 것이었다. 메시지는 대강 클라이언트에 이미 응답을 보내고 나서 다시 헤더를 쓸 수 없다는 것 같았다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/9a47dfc8-9c98-49e2-9e70-de927e32dde5/image.png" alt=""></p>
<p>문제의 부분은 여기였다. 이 가장 바깥 res.end()를 지워주니 정상적으로 출력되었다. </p>
<h3 id="powershell에선-touch로-새-파일을-만들-수-없다---ni-new-item을-쓰자">Powershell에선 touch로 새 파일을 만들 수 없다 - ni (new item)을 쓰자</h3>
<p>부트캠프 때 touch로 새 파일을 만드시던 강사님의 모습이 떠올라 우클릭 하지 않고 CLI로 새 파일을 만들어보고 싶었는데, 파워쉘은 물론이고 깃배쉬에서도 touch가 먹히지 않는 것이다. </p>
<p>알고보니 touch는 Linux 명령어라고. Powershell에서는 ni .gitignore 하니 만들어졌다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251223 - KNOU Python (재수강)]]></title>
            <link>https://velog.io/@liha_engineer/251223-KNOU-Python-%EC%9E%AC%EC%88%98%EA%B0%95</link>
            <guid>https://velog.io/@liha_engineer/251223-KNOU-Python-%EC%9E%AC%EC%88%98%EA%B0%95</guid>
            <pubDate>Tue, 23 Dec 2025 12:18:23 GMT</pubDate>
            <description><![CDATA[<h3 id="a받은-과목을-왜-굳이-재수강을-했냐면">A받은 과목을 왜 굳이 재수강을 했냐면</h3>
<p>부트캠프 버프로 잠깐 학점만 잘 받고 아무것도 기억나지 않아 파이썬을 좀 제대로 공부해보고자 A학점인 것을 굳이굳이 재수강을 신청했다. </p>
<p>물론 이상적 결과물은 A+이지만, 학점세탁이 아니더라도 정처기에 나오기도 하고 무엇보다 내가 할줄 아느냐 모르느냐가 더 중요하다고 생각했기 때문. </p>
<h3 id="정보처리기사가-내게-개똥을-주었어">정보처리기사가 내게 개똥을 주었어</h3>
<p>사실 정처기는 잘못이 없다. 공부를 안한 스스로의 탓(...)</p>
<hr>
<h2 id="7강---반복-구조">7강 - 반복 구조</h2>
<h3 id="리스트의-개념을-간단히-정리하고-가자">리스트의 개념을 간단히 정리하고 가자</h3>
<blockquote>
</blockquote>
<p>순서화된 값의 집합체를 저장할 수 있는 데이터 타입</p>
<ul>
<li>단일 식별자로 연속된 저장공간 접근 수단 제공</li>
<li>개별 원소의 값을 수정, 추가, 삭제 가능</li>
<li>원소의 나열을 저장할 수 있는 시퀀스 타입 중 하나<ul>
<li>리스트, 세트, 튜플, 딕셔너리 등...</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<p>Q. 시퀀스 타입이 뭔가요?
A. 데이터 타입 중 하나. 
계수 제어 반복 구조(for문) 에서 특정 반복 횟수와 반복 시 계수의 값을 정하기 위해 사용되는 타입. </p>
<h3 id="파이썬의-리스트는-대괄호만으로-선언-가능">파이썬의 리스트는 대괄호만으로 선언 가능</h3>
<p>좀더 포멀하게는 <code>list([원소 시퀀스])</code> 로 쓸 수 있지만, 그냥 <code>[원소 시퀀스]</code> 라고만 써도 된다. 이 리스트는 다른 정적언어의 배열처럼 인덱스 번호로 직접 접근할 수 있다.</p>
<pre><code class="language-python">rad = 30 // 원뿔의 밑넓이
height_list = [15, 7, 23, 9, 31]</code></pre>
<p>위와 같이 주어져있다고 하면, for문을 통해 <code>height_list</code>의 인덱스 번호를 찍어 돌면서 원뿔의 부피를 구할 수 있을 것. </p>
<p>*<em>파이썬은 이렇게 리스트 쓰기가 간단해서, 다른 언어 배열 쓰듯이 리스트 써서 for문 도는 경우가 많다. *</em></p>
<h3 id="계수-제어-반복은-어려운게-아니다---for문-얘기">계수 제어 반복은 어려운게 아니다 - for문 얘기</h3>
<p>for문을 그럴듯하게 표현하면 계수 제어 반복이다. 숫자(계수)에 따라 반복문이 제어되므로 이렇게 부른다. </p>
<blockquote>
<p>for 계수-제어-변수 in 시퀀스:
(공백) 코드블록</p>
</blockquote>
<p>위와 같은 구조로 이루어진다. 강의 예시는 다음과 같다.</p>
<pre><code class="language-python">hei_list = [1, 4, 14, 26, 31]

for hei in hei_list:
    print(hei)
    // 이렇게 쓰면 알아서 hei_list 끝까지 돌아준다</code></pre>
<h3 id="파이썬의-in-range처음-끝-는-처음-이상-끝-미만이다">파이썬의 in range(처음, 끝) 는 처음 &#39;이상&#39; 끝 &#39;미만&#39;이다</h3>
<p>그래서 1~10을 하고 싶으면 in range(1, 11) 을 쓰면 된다. 아래와 같이 작성한다.</p>
<blockquote>
<p>[기본형]
range(시작값(이상), 끝값(미만), 증분)</p>
</blockquote>
<blockquote>
<p>[예시]
for i in range(1, 11): 
print(i)</p>
</blockquote>
<p>이렇게만 써도 i가 1씩 증가하면서 출력된다. 증분을 3으로 쓰면 +3 한 숫자가 끝값 미만 중 최대수까지 출력된다. </p>
<p><a href="https://www.daleseo.com/python-range/">참고 블로그</a>에 따르면 숫자 하나만 적으면 그 수가 종료지점이 된다고. </p>
<h2 id="9강--함수">9강- 함수</h2>
<h3 id="파이썬은-동시할당과-교환이-가능하다">파이썬은 동시할당과 교환이 가능하다</h3>
<pre><code class="language-python">season, temp = &quot;winter&quot;, -5</code></pre>
<p>이렇게 쓰면 season과 temp에 각각 값이 들어간다. </p>
<p>동시할당을 좀더 자세히 보면 이렇게 생겼다.</p>
<pre><code class="language-python">def rtn_con_vol_surf(r,h):
    if r &gt; 0 and h &gt; 0:
        vol = 1/3 * 3.14 * r ** 2 * h
        surf=3.14 * r ** 2 + 3.14 * r * h
        return vol, surf
    else:
        print(&quot;반지름과 높이 값을 올바르게 입력해주세요&quot;)

vol1, surf1 = rtn_con_vol_surf(50, 100)
print(vol1, &quot;입니다&quot;)
print(surf1, &quot;입니다&quot;)</code></pre>
<p>vol1, surf1 = ~ 저렇게 써놓으면 vol1에 부피값이, surf1에 겉넓이 값이 알아서 계산해서 들어가진다. (함수 자체가 return을 vol, surf로 다중반환 하기때문)</p>
<pre><code class="language-python">uni = 15
add = 693

uni, add = add, uni
</code></pre>
<p>이런 식으로 그냥 자리를 바꿔치는 교환도 가능하다. </p>
<h3 id="함수-내에서-동시할당으로-자리가-바뀌어도-원래-입력값-순서는-바뀌지-않는다">함수 내에서 동시할당으로 자리가 바뀌어도 원래 입력값 순서는 바뀌지 않는다</h3>
<pre><code class="language-python">a = int(input(&quot;첫 번째 숫자 입력: &quot;))
b = int(input(&quot;두 번째 숫자 입력: &quot;))
c = int(input(&quot;세 번째 숫자 입력: &quot;))

def sort3(a, b, c):
    if a &gt; b:
        a, b = b, a
    if a &gt; c:
        a, c = c, a
    if b &gt; c:
        b, c = c, b
    print(a, b, c)

sort3(a, b, c)
print(&quot;함수 수행 이후의 a, b, c 값은: &quot;, a, b, c)</code></pre>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/f4512604-fb72-4991-97ca-fc1f06cfe406/image.png" alt=""></p>
<p>이렇게 나온다. </p>
<h3 id="값에-의한-전달---함수-내에서-값을-새로-정의해도-밖으로-전달되지-않는다">값에 의한 전달 - 함수 내에서 값을 새로 정의해도 밖으로 전달되지 않는다</h3>
<pre><code class="language-python">def rtn_con_vol_surf(r,h):
    if r &gt; 0 and h &gt; 0:
        vol = 1/3 * 3.14 * r ** 2 * h
        surf=3.14 * r ** 2 + 3.14 * r * h
        r, h = 0, 0
        return vol, surf
    else:
        print(&quot;반지름과 높이 값을 올바르게 입력해주세요&quot;)

r= 10
h = 15
print(rtn_con_vol_surf(r,h), &quot;입니다&quot;)
print(r, h)</code></pre>
<p>위 코드에서 맨 밑 print문은 10, 15가 찍힌다. 함수 내에서 r, h = 0, 0 한 것은 전혀 영향을 미치지 않는다. </p>
<h2 id="10강---객체지향">10강 - 객체지향</h2>
<h3 id="데이터-필드라는-것을-나타내기-위해-self을-찍어야-할-때가-있다">데이터 필드라는 것을 나타내기 위해 self.을 찍어야 할 때가 있다</h3>
<pre><code class="language-python">class Cone:
    def __init__(self, r = 20, h = 30):
        self.r = r
        self.h = h

    def get_vol(self):
        vol = 1/3 * 3.14 * r ** 2 * h
        return vol
</code></pre>
<p>이때 get_vol의 vol 공식에서 그냥 r과 h를 쓰면 받는 매개변수도 없는데 계산을 할 수가 없다. </p>
<h3 id="javascript의-백틱처럼-변수를-표현할-수-있는-방법이-있다---f스트링">javascript의 백틱처럼 변수를 표현할 수 있는 방법이 있다 - f스트링</h3>
<p>파이썬의 f string은 쌍따옴표 앞에 f만 써주면 변수를 중괄호로 가져와 그냥 쓸 수 있다.</p>
<pre><code class="language-python">name = &quot;James&quot;
age = 35

f&quot;{name}님 {age}세. 안녕하세요&quot;</code></pre>
<p>이런 식으로. </p>
<hr>
<h3 id="그리고-결과">그리고 결과</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/f75feca7-8be7-4653-b71e-e333794fc8d6/image.png" alt=""></p>
<p>재수강 실패! A0 유지!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251223 - 낯익은 듯 낯선 듯 C# 문법 기초]]></title>
            <link>https://velog.io/@liha_engineer/251223</link>
            <guid>https://velog.io/@liha_engineer/251223</guid>
            <pubDate>Tue, 23 Dec 2025 02:11:28 GMT</pubDate>
            <description><![CDATA[<h3 id="정적-언어-선택에-대한-고민">정적 언어 선택에 대한 고민</h3>
<p>서버 구현을 배워본 것이 자바스크립트 뿐이라 속도와 안정성 때문에 정적 언어에 대한 학습을 고민했다. 시간이 그렇게 여유롭지 않은 상황 상 러닝커브가 조금이라도 낮았으면 했다. </p>
<p>근본인 C와 C++도 있는데 개중 왜 C#이냐면 </p>
<ul>
<li>메인메소드가 공부해봤던 자바와 똑같이 생겨 러닝커브를 조금 덜 수 있을거라는 생각이 들었다. </li>
<li>게임엔진과 호환되는 언어니 조금이라도 도움되지 않을까 싶은 것도 있었고 (이 부분은 사실 명확하지 않음)</li>
<li>이왕이면 한 번 배울 때 여러 분야를 아우르는 언어를 학습하고 싶었다. </li>
</ul>
<h3 id="c에서도-js의-im-name-같은-문법을-쓸-수-있다">C#에서도 JS의 <code>I&#39;m ${name}</code> 같은 문법을 쓸 수 있다</h3>
<pre><code class="language-cs">string name = &quot;John&quot;;
int age = 30;
string message = string.Format(&quot;My name is {0} and I&#39;m {1} years old.&quot;, name, age);
Console.WriteLine(message);
message = $&quot;My name is {name} and I&#39;m {age} years old.&quot;;
Console.WriteLine(message);</code></pre>
<p>이런 식으로 쓸 수 있다. </p>
<h3 id="왜-git-add--이-안되지-남들과는-좀-다른-해결법">왜 git add . 이 안되지? 남들과는 좀 다른 해결법</h3>
<p>상황: 비주얼 스튜디오에서 Ctrl + ` 으로 콘솔을 열고 git add . 을 쳤는데 뭔가 자꾸 <code>Permission denied</code>가 뜨면서 add를 할 수 없었다. </p>
<p>대응1: gitignore 파일이 있었고 그 안에 .vs가 포함되어 있었는데도 무용지물이었다. 
대응2: 많은 다른 사람들이 문제를 해결한 도구 &gt; 텍스트 편집기 &gt; C/C++ 쪽에서 옵션을 만지는 것으로는 해결되지 않았다. </p>
<ul>
<li>이 문제는 <a href="https://www.reddit.com/r/dotnet/comments/1gxr6c8/git_add_error_permission_denied_for_vs_files_need/?tl=ko">고마운 레딧웨건</a>을 통해 해결하였다. </li>
</ul>
<p>추정 원인: .vs가 gitignore에 추가만 되어 있었고 실제 파일 혹은 폴더가 존재하지 않기 때문이었던 것 같음
해결: 터미널에 dotnet new gitignore 치니 해결</p>
<h3 id="나도-튜터님처럼-programcs-파일을-여러-개-두고-싶은데---프로젝트를-추가하면-된다">나도 튜터님처럼 Program.cs 파일을 여러 개 두고 싶은데 -&gt; 프로젝트를 추가하면 된다</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/8c7be05d-768b-4789-bcc4-2bbccf9ad278/image.png" alt=""></p>
<p><strong>솔루션</strong>에 우클릭(프로젝트에 우클릭 하면 안됨) &gt; 추가 &gt; 새 프로젝트를 누르면 이 창이 뜬다. 여기서 C# 콘솔 앱을 누르면 새 프로젝트가 솔루션 밑에 추가된다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/e774488c-4b69-4ae6-b301-a9755e616e6f/image.png" alt=""></p>
<h3 id="코드-전체-정렬은-ctrl--k--f">코드 전체 정렬은 Ctrl + K + F</h3>
<p>VS Code는 텍스트 편집기라 여러 라이브러리나 익스텐션을 설치해야 기능이 동작하지만, 비주얼 스튜디오는 IDE라서 기능이 내장되어 있다. 단축키만 외우면 된다. </p>
<h3 id="다시-만난-디버깅---f9와-f10">다시 만난 디버깅 - F9와 F10</h3>
<p>브레이크 포인트 설정은 F9, 프로시저 단위 실행은 F10</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251218 - 아니, 무슨 assertion이요? ]]></title>
            <link>https://velog.io/@liha_engineer/251218</link>
            <guid>https://velog.io/@liha_engineer/251218</guid>
            <pubDate>Thu, 18 Dec 2025 14:50:23 GMT</pubDate>
            <description><![CDATA[<h3 id="근본의-근본의-근본으로-돌아가다-c언어-입문기">근본의 근본의 근본으로 돌아가다. C언어 입문기</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/4ea66917-6078-444a-8f55-1392c4623f70/image.png" alt=""></p>
<p>독학&amp;입문 수준인 만큼 어렵지 않은 책으로 기초를 떼려고 구매했다. 방통대다 정처기다 사놓고 쌓아두기만 하고 보질 못하다가 이제사 펴보는 책. 정말 쉽고 간단한 내용부터 설명해주는 입문서로 좋다. </p>
<h3 id="나는-나이를-입력하고-싶었던-것-뿐인데---debug-assertion-failed">나는 나이를 입력하고 싶었던 것 뿐인데 - Debug Assertion Failed</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/b9e78b33-9714-490f-bbe8-c46890a3a2d8/image.png" alt=""></p>
<p>열심히 앞선 예제들을 따라하던 도중 어떤 에러 메시지와 조우했다. 양심없이 나이를 14살이라고 한 탓일까? 프로그램이 터지고 말았다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/1604ef62-01cf-4898-ad1b-6d71eabecfb6/image.png" alt=""></p>
<p>그래서, 대체 뭐가 문제인걸까? format parser가 에러를 감지했다고 한다. 
나이를 입력하니 터졌고, 포맷의 문제라면 -&gt; scanf_s에서 받는 것에 뭔가 문제가 있을 확률을 고려해보자.</p>
<pre><code class="language-c">char name[256]; 
printf(&quot;이름이 뭐에요?: &quot;); 
scanf_s(&quot;%s&quot;, name, (unsigned int)sizeof(name)); 

int age; 
printf(&quot;나이는 얼마?: &quot;); 
scanf_s(&quot;%d&quot;, &amp;age); 

float weight; 
printf(&quot;몸무게는 얼마?: &quot;); 
scanf_s(&quot;%.2f&quot;, &amp;weight); 

double height; 
printf(&quot;키는 얼마?: &quot;); 
scanf_s(&quot;%.1lf&quot;, &amp;height);</code></pre>
<p>** scanf_s(&quot;%.2f&quot;, &amp;weight);  ** 라고 쓴 것이 문제였다... 포맷을 지정해주는 건 scanf가 아니라 printf에서 하는건데 착각과 귀찮음의 조화로 코드를 복붙한 탓인지 터지고 말았다. </p>
<p>문제가 된 부분은 <code>%f</code>로 고쳤다. 고치는 김에 아래에 있는 <code>.1lf</code>도 냅두면 터질 게 분명헤 <code>lf</code>로 고쳐줬다. 이후 정상 동작했다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251104 - 드래곤 알을 구분하고 싶어]]></title>
            <link>https://velog.io/@liha_engineer/251104</link>
            <guid>https://velog.io/@liha_engineer/251104</guid>
            <pubDate>Tue, 04 Nov 2025 14:46:55 GMT</pubDate>
            <description><![CDATA[<h3 id="2009년부터-즐겨온-웹게임을-하다-문득-든-생각">2009년부터 즐겨온 웹게임을 하다 문득 든 생각</h3>
<p>드래곤의 동굴에서 알을 가져오는 컨셉의 웹게임이 있다. 알의 모양은 알 수 없고 설명만으로 뭔지 짐작해야 하는데, 문득 이 랜덤한 알들에 커서를 갖다대면 정보를 띄워주는 것을 개발하면 어떨까? 하는 생각이 들었다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/87ced885-2a50-45c2-ba07-fd73cf722798/image.png" alt=""></p>
<p>(알님 알님 제게 정보를 주세요)
어떻게 구현해볼 수 있을지 감이 잡히지 않아 GPT에게 물어보니 크롬 익스텐션을 만들어야 한다고.</p>
<h3 id="manifestjson-크롬-익스텐션에-꼭-필요한-녀석">manifest.json? 크롬 익스텐션에 꼭 필요한 녀석</h3>
<p><a href="https://yghan.tistory.com/89">참고 블로그1</a> <a href="https://youngsimi.tistory.com/entry/%ED%81%AC%EB%A1%AC-%ED%99%95%EC%9E%A5%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-part2-manifast-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0-%EC%8A%A4%ED%86%A0%EC%96%B4-%EB%93%B1%EB%A1%9D%ED%95%98%EA%B8%B0">참고 블로그2</a></p>
<p>크롬 익스텐션에서 꼭 필요한, 중요한 메타데이터를 담아 가장 처음에 로드되는 json 파일이 있다. 사실 전혀 만들 줄 모르다 보니 초반에는 GPT에게 이것저것 만들어달라고 했었는데, 내 손으로 해보고 싶어 참고 블로그들을 차근차근 읽어보고 작성해보려고 한다. </p>
<pre><code class="language-json">{
  &quot;name&quot;: &quot;Getting Started Example&quot;,
  &quot;description&quot;: &quot;Build an Extension!&quot;,
  &quot;version&quot;: &quot;1.0&quot;,
  &quot;manifest_version&quot;: 3,
  &quot;options_page&quot; : &quot;options.html&quot;,
  &quot;background&quot;: {
    &quot;service_worker&quot;: &quot;background.js&quot;
  },
  &quot;permissions&quot;: [&quot;storage&quot;, &quot;activeTab&quot;, &quot;scripting&quot;],
  &quot;action&quot;: {
    &quot;default_popup&quot;: &quot;popup.html&quot;,
    &quot;default_icon&quot;: {
      &quot;16&quot;: &quot;/images/get_started16.png&quot;,
      &quot;32&quot;: &quot;/images/get_started32.png&quot;,
      &quot;48&quot;: &quot;/images/get_started48.png&quot;,
      &quot;128&quot;: &quot;/images/get_started128.png&quot;
    }
  },
  &quot;icons&quot;: {
    &quot;16&quot;: &quot;/images/get_started16.png&quot;,
    &quot;32&quot;: &quot;/images/get_started32.png&quot;,
    &quot;48&quot;: &quot;/images/get_started48.png&quot;,
    &quot;128&quot;: &quot;/images/get_started128.png&quot;
  }
}</code></pre>
<p>참고 블로그 기준으로는 이렇게 써있다. manifest.json 파일 내에서 주로 사용하는 옵션들은 다음과 같다고.</p>
<blockquote>
</blockquote>
<p>manifest_version: 매니페스트 파일 형식의 버전을 지정하는 정보
name: 최대 45자 이내 작성. short_name 옵션도 쓸 수 있는데 그건 12자 이내 작성. 별도로 작성하지 않으면 보통 name 옵션을 따라간다고 한다
permission: 크롬 API를 사용하기 위해 크롬 익스텐션에 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251018 - 좌충우돌 C#서버 띄우기]]></title>
            <link>https://velog.io/@liha_engineer/251018</link>
            <guid>https://velog.io/@liha_engineer/251018</guid>
            <pubDate>Sat, 18 Oct 2025 15:35:20 GMT</pubDate>
            <description><![CDATA[<h3 id="원래-계획은-이게-아니었는데">원래 계획은 이게 아니었는데</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/31456a61-95ec-4180-8102-120e199dc153/image.png" alt=""></p>
<p>그렇다. 나도 꽤 그럴싸한 계획을 갖고 있었다. 이렇게 C#에게 두들겨 맞기 전까진. (?)
친구비를 내가며 GPT에게 상담을 했더니, 웹사이트를 C#으로 띄워보라는 제안을 해 주었다. 
<strong>뜬금없이 C#으로? 아예 C++도 아니고? 왜?</strong> 라는 생각이 들었다. 가벼운 서버면 그냥 Node로 express를 쓰는게 낫지 않나?</p>
<p>그런데 GPT가 꽤 그럴싸한 제안을 해 주었다. **&quot;너 게임서버 하고싶잖아. 그런데 지금은 웹서버밖에 해본 적이 없다며. 그러면 연결다리로 C# 공부하기엔 웹사이트 띄우는 게 제일 좋지.&quot; **</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/8b54251f-5247-498f-94cb-f2265194d868/image.png" alt=""></p>
<p>야 너 대박이다 진짜. 친구비 값 제대로 하는구나...</p>
<h3 id="왜-git-checkout이-안-되지">왜 git checkout이 안 되지?</h3>
<p>한 번도 커밋을 한 적이 없으면 안 된다고 한다. 커밋푸쉬 한번 하고 나니까 거짓말처럼 checkout이 잘 된다. </p>
<h3 id="솔루션이라는-구조가-너무-낯설어요">솔루션이라는 구조가 너무 낯설어요</h3>
<p>솔루션은 프로젝트들을 묶는 큰 단위. 프로젝트들이 책의 챕터라면 솔루션은 책 자체. 그래서 git init은 루트 경로인 솔루션에 되어야 하는 게 맞다. .gitignore도 루트 경로에 만들어줘야 한다고. <a href="https://www.reddit.com/r/csharp/comments/1cmyysa/where_to_init_the_git_in_the_solution/?tl=ko">고마워요 레딧</a></p>
<h3 id="커밋-컨벤션은-무엇을-따르면-좋을까">커밋 컨벤션은 무엇을 따르면 좋을까</h3>
<p>Github Rule은 혼자 작업할 때도 지키는 편. 혼자서도 안 지키는 걸 협업 때 지킬 리가 없다. 
커밋 컨벤션은 부트캠프 시 <a href="https://www.notion.so/Github-Rules-1aafa1cd271381fe802addea4e3838ab">최종 프로젝트 룰</a>을 가져왔다. 이유는 익숙한 컨벤션을 써서 부가적 시간 소모와 프리픽스 혼동을 줄이기 위함.</p>
<table>
<thead>
<tr>
<th>작업 타입</th>
<th>작업 내용</th>
</tr>
</thead>
<tbody><tr>
<td>✨ feat</td>
<td>해당 파일에 새로운 기능이 생김</td>
</tr>
<tr>
<td>🎉 add</td>
<td>없던 파일을 생성, 초기 세팅</td>
</tr>
<tr>
<td>⚒ fix</td>
<td>버그 수정</td>
</tr>
<tr>
<td>♻️ refactor</td>
<td>코드/구조 리팩터링. 파일 이름 변경</td>
</tr>
<tr>
<td>✂ del</td>
<td>파일 삭제</td>
</tr>
<tr>
<td>🍻 test</td>
<td>테스트 코드 작성</td>
</tr>
<tr>
<td>💄 comment</td>
<td>주석 관련 모든 작업 (추가/수정/삭제)</td>
</tr>
<tr>
<td>📝 docs</td>
<td>README 등 문서 작성/수정 시</td>
</tr>
<tr>
<td>🙈 chore</td>
<td>gitignore, package.json 등 프로덕션 코드의 변경이 없는 경우</td>
</tr>
</tbody></table>
<h3 id="어-그러고보니-vs에서는-git을-어떻게-사용하지">어? 그러고보니 VS에서는 git을 어떻게 사용하지?</h3>
<p>이것 또한 <a href="https://www.reddit.com/r/csharp/comments/bl19cx/how_do_you_guys_use_git_with_visual_studio/?tl=ko">레딧</a>이 나를 구원해 주었다. </p>
<h3 id="launchsettingsjson은-의외로-커밋해야-하는-것이었다">launchSettings.json은 의외로 커밋해야 하는 것이었다</h3>
<p>고마워요 <a href="https://stackoverflow.com/questions/47377058/should-i-ignore-the-launchsettings-json-file-from-being-committed-in-git">스택 오버플로우 웨건!</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251011 - 갑자기 떠오른 육효 사이트의 꿈(?)]]></title>
            <link>https://velog.io/@liha_engineer/251011</link>
            <guid>https://velog.io/@liha_engineer/251011</guid>
            <pubDate>Sat, 11 Oct 2025 09:22:10 GMT</pubDate>
            <description><![CDATA[<h3 id="취미였던-점보기에-대하여">취미였던 점보기에 대하여</h3>
<p>친척 중 무당이 계셨지만 20대 중반까지 사주팔자 같은 것에는 전혀 관심이 없었던 나. 그러나 어느순간 사주에 꽂혀 몇 년 공부를 하고 지금은 취미로 점사를 보는 중.</p>
<p>그러나, 누가 요즘 산통을 들고다닌단 말인가. 요새는 카니타로처럼 온라인 페이지에서 카드를 뽑을 수 있는 경우도 많으니.</p>
<p>기존에 이용하던 방식은 늘 난수발생기를 돌리고 괘의 해설을 찾는 불편이 있었다. 대단한 프로젝트가 아니어도 좋으니, 일단 나 자신을 위한 육효 사이트가 있다면 좋을 것 같았다. </p>
<p>타로 사주 사이트는 이미 많기도 하고 달력의 복잡함도 있고 하여, 최근 자주 이용하는 육효로 하기로 결정. 육효도 세응 잡고 동효 설정하고 하면 복잡하지만, 그런 육효 이론은 나도 모르니 정말 단순하고 간단하게 카테고리 별로 나눌 예정. </p>
<h3 id="어떤-기술-스택으로-만들어볼까">어떤 기술 스택으로 만들어볼까</h3>
<p>일단 지금 할 줄 아는 것은 Node밖에 없으니 Node 서버로 만들자. 웹에는 이만한 것이 없다는 생각을 하며... 아 스프링 공부도 다시 해야 하는데. (?)</p>
<p>나는 Express.js만 써왔는데, 반드시 익스프레스를 써야할까? 다른 서버 프레임워크도 있을텐데, 내가 이 프로젝트에서 익스프레스를 써야하는 이유와 그렇지 않은 이유가 있다면 뭘까? </p>
<p>Koa.js, Hapi.js, Nest.js, LoopBack 등 여러 프레임워크가 있다. 보통 Express의 라이벌(?)로 인식되는 것은 Nest.js 인 것 같다. 참고 사이트들을 토대로 둘의 특징을 한번 정리해보자.</p>
<p><a href="https://developer.mozilla.org/ko/docs/Learn_web_development/Extensions/Server-side/Express_Nodejs">MDN 공식문서 - Express(Node.js)</a>
<a href="https://wikidocs.net/148195">위키독스 - Express가 좋을까 NestJS가 좋을까?</a>
<a href="https://fathory.tistory.com/206">참고 블로그1 - Node.js 백엔드 프레임워크 종류와 특징</a>
<a href="https://velog.io/@kakasoo/Express%EB%A7%8C-%ED%95%98%EB%8B%A4%EA%B0%80-Nest%EB%A5%BC-%ED%95%98%EA%B3%A0-%EB%8A%90%EB%82%80-%EC%A0%90">참고 블로그2</a>
<a href="https://rhgustmfrh.tistory.com/227">참고 블로그3</a></p>
<blockquote>
</blockquote>
<p>Express의 특징</p>
<ul>
<li>MDN 공식 추천 프레임워크 </li>
<li>가볍게 테스트용 서버를 띄울 수 있다</li>
<li>단순하고 자유도 높음. 하지만 그때문에 라이브러리를 위해 발품 팔아야함</li>
<li>타입스크립트는 추가설정을 통해 사용가능</li>
<li>커뮤니티가 크다 (언어 생태계가 넓다)</li>
</ul>
<blockquote>
</blockquote>
<p>NestJS의 특징 </p>
<ul>
<li>타입스크립트용 오픈소스 서버 프레임워크</li>
<li>미들웨어, IoC(제어의 역전), CQRS 등 많은 기능이 포함됨. 
자바 스프링을 많이 차용하여 스타일이 비슷함</li>
<li>Express 기반으로 만들어져 req, res 등의 객체 사용 가능 </li>
<li>타입스크립트를 상정하고 만든 것이라 TS 기본 지원</li>
<li>다만 핵심 개념에 TS 특화 내용들이 들어가기 때문에 TS 모르면 러닝커브 높음 </li>
</ul>
<p>파이썬에 비유하자면 Express는 Flask, Nest는 Django 라고 한다. </p>
<blockquote>
</blockquote>
<p>결정: Express
현재는 러닝커브에 많은 시간을 쏟을 여유가 없고, 
단순하고 높은 자유도가 필요하며, 
큰 생태계에서 빠르게 정보를 입수해야 하는 상황이기 때문</p>
<h3 id="nestjs-조사-중-의문---타입스크립트는-왜-필요한걸까">NestJS 조사 중 의문 - 타입스크립트는 왜 필요한걸까?</h3>
<p>예전에 항해 노드 매니저님께서도 Node를 하려면 타입스크립트는 필수라고 하시며 책을 추천해 주셨다. 그런데 왜 필수인걸까? 
예전 항해 동기분이 타입스크립트는 자바스크립트의 자유분방함이 문제가 되어 자바에서 타입을 차용하여 안전성을 도모한 언어라고 하셨었다. </p>
<p><a href="https://develog-yeon.tistory.com/35">참고 블로그 - 타입스크립트는 왜 쓰는걸까?</a></p>
<p>우선 버그 예방의 목적이 가장 크다고 한다. 자바스크립트처럼 무타입 언어는 런타임 시에 자료형이 결정되기 때문에 모르는 새에 형변환이 되어있는 경우가 꽤 된다. 타입스크립트는 컴파일 단계를 거치기 때문에 에러가 있으면 미리 알 수 있는 것이 장점. </p>
<h3 id="express를-쓰기로-결정했으면-초기-설정을-해보자">Express를 쓰기로 결정했으면 초기 설정을 해보자</h3>
<blockquote>
</blockquote>
<ol>
<li>npm install -g yarn</li>
<li>yarn init (다 쓰기 귀찮으면 -y/--yes)</li>
<li>yarn add express</li>
<li>package.json에 &quot;type&quot; : &quot;module&quot; 추가</li>
<li>아래 코드를 자신의 실행파일(나는 app.js) 에 작성</li>
<li>작성 다 했으면 터미널에 node app.js 입력</li>
<li>3000번 포트가 이미 열려있다면 taskkill /f /im node.exe 입력
(Mac은 killall node)</li>
</ol>
<pre><code class="language-js">import express from &#39;express&#39;;

const app = express();
const PORT = 3000;

app.get(&#39;/&#39;, (req, res) =&gt; {
  res.send(&#39;Hello World!&#39;);
});

app.listen(PORT, () =&gt; {
  console.log(PORT, &#39;port is listening...&#39;);
});
</code></pre>
<ul>
<li>강사님처럼 이모지가 표시되게 하고 싶은데 맥이 아니라 안되나?</li>
<li><blockquote>
<p>아니다. yarn (아무 명령어. init, add, 생략 등) --emoji 라고 하면 된다. </p>
</blockquote>
</li>
</ul>
<h3 id="es6-문법의-es는-엘라스틱-서치가-아니다---ecma-script-module">ES6 문법의 ES는 엘라스틱 서치가 아니다 - ECMA Script Module</h3>
<p>항해때 스프링을 하면서 내배캠을 하기 전까지 ES5 ES6가 엘라스틱 서치에 버전이 붙은 줄 알았다. ESM(ECMA Script Module)에 버전이 붙은 것. 
ESM은 최신 Javascript에서 지원하는 모듈 시스템. 모든 Javascript 환경에서 통합적인 인터페이스를 제공하기 위해 시작된 체계라고 한다. </p>
<p>CommonJS와는 다르게 정적으로 모듈을 가져오며 비동기적 모듈 로딩과 순환 종속을 처리한다고 한다.</p>
<blockquote>
</blockquote>
<p>정적 모듈 로딩, 동적 모듈 로딩, 순환 종속에 대해 공부해볼 것</p>
<p>ES6와 CJS의 차이 중 하나는 require문은 아무데나 붙을 수 있지만 import문은 맨 위에 위치해야 한다는 점이다. </p>
<h3 id="express에서-router의-일반적인-구조">Express에서 Router의 일반적인 구조</h3>
<p>라우터의 기본 골자는 다음과 같다. </p>
<blockquote>
</blockquote>
<p>router.METHOD(PATH, HANDLER);</p>
<p>이게 대체 뭔 소리냐? 하면 예시로 보자.</p>
<blockquote>
</blockquote>
<p>router.get(&#39;/&#39;, console.log(&#39;Hello Express!&#39;));</p>
<p>METHOD에는 get, post, put, delete, update 등...
PATH는 출력할 JS파일의 상대경로. 
HANDLER는 라우트가 일치할 때 실행되는 함수.</p>
<p>만든 라우터를 엔드포인트에서 사용하려면 app.use()를 쓰자. 
나의 경우는 일단 home.router.js를 만들고 homeRouter 라는 이름으로 import 해와서 다음과 같이 썼다.</p>
<blockquote>
</blockquote>
<p>const app = express();
app.use(&#39;/api&#39;, [homeRouter]);</p>
<h3 id="하다보니-생긴-고민---프론트는-뭘로-만들어야-할까-react-vs-vue">하다보니 생긴 고민 - 프론트는 뭘로 만들어야 할까? React vs Vue</h3>
<p>수료했던 교육기관에서는 프론트엔드에게 리액트를 가르쳤지만, <a href="https://brunch.co.kr/@skykamja24/573">이 참고 블로그</a>의 내용을 읽어봤을 때는 리액트는 Redux를 별도로 필요로 하고, 상탯값 변경 등에 대한 유연성이 상당히 떨어진다는 평이 있다. 애초에 리액트는 프레임워크가 아니라 라이브러리라고. 다만 모든 것이 자바스크립트 문법이기 때문에 별도로 문법을 배울 필요가 없다는 것이 장점. </p>
<p>Vue는 구조가 HTML과 아주 유사하지만 전용 문법을 어느정도 익혀야 한다는 주의점이 있다. 뷰도 프레임워크와 라이브러리 그 사이 어딘가에 있는 것 같지만 일단은 프레임워크로 분류된다. </p>
<p>지금의 나에게는 러닝커브나 추가 리소스 투입이 가능한 적은 프레임워크가 필요하다. 가능한 바닐라 HTML과 형태가 비슷하면 좋겠지만, 아니어도 내가 손볼 수만 있으면 된다는 주의. 프론트 프레임워크는 둘 다 나름대로 매력적인 것 같아 조금 고민.</p>
<p><a href="https://blog.coinsect.io/posts/why-i-prefer-vue-over-react">내가 React보다 Vue를 좋아하는 이유</a> 라는 블로그 글을 보면, 리액트가 가장 어렵기 때문에 취업을 위해서라면 리액트를 추천한다고 한다. 내가 추구하는 목적과는 부합하지 않아 Vue로 결정. <a href="https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Frameworks_libraries/Vue_getting_started">MDN 공식문서</a>에서 소개되었다는 것 또한 고려 요소. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251009 - 강타입과 약타입, 정적타입과 동적타입]]></title>
            <link>https://velog.io/@liha_engineer/251009</link>
            <guid>https://velog.io/@liha_engineer/251009</guid>
            <pubDate>Thu, 09 Oct 2025 14:15:47 GMT</pubDate>
            <description><![CDATA[<h3 id="type-safety-라는-건-뭘까">Type-safety 라는 건 뭘까?</h3>
<p>프로그래밍 언어의 구성요소인 타입. 데이터 집합과 연산 집합을 합친 개념. 단순히 1, 2, 3으로 끝나지 않고 이들끼리 연산도 가능해야 하는게 타입. 연산의 <strong>안전성 보장</strong>을 위해 쓰인다... </p>
<p><strong>안전성 보장?</strong> 그냥 자료형을 선언하면 강타입으로 보장되고, 아니면 약타입인 게 아니었나? (아니었나 보다)
의외로 타입 안전성은 수학적 설명으로 표현할 수 있었다. </p>
<blockquote>
</blockquote>
<p>함수 f의 타입이 f(x) A -&gt; B 라면,
모든 a∈A에 대해 f(a)∈B여야 한다
(이때 A, B는 타입) <br></p>
<ul>
<li>타입 안전(Type safe): 프로그램 내 모든 연산 및 함수에 대해 타입 안전성을 만족하는 프로그램</li>
</ul>
<p>강타입 약타입은 <strong>타입 안전성 측면</strong>에서의 프로그래밍 언어 분류라고 한다. </p>
<blockquote>
</blockquote>
<ul>
<li>강타입 언어: 타입 오류를 모두 검출하는 언어</li>
<li>약타입 언어: 타입 오류를 검출하지만 일부는 허용하는 언어. <strong>C언어가 약타입.</strong></li>
<li>무타입 언어: 타입 선언문이 없고 어떤 대상의 타입이 계속 변경될 수 있는 언어. Python 등</li>
</ul>
<h3 id="강타입약타입-언어와-정적타입동적타입-언어는-다르다">강타입/약타입 언어와 정적타입/동적타입 언어는 다르다</h3>
<p>C, C++, C# 등의 언어가 프로그래밍 언어론 기준으로는 강타입으로 분류되지 않았다. 
(JAVA는 타입 캐스팅 기능만 제외하면 강타입으로 간주한다고.)
내가 지금까지 강타입이라고 생각했던 언어는 사실 <strong>정적타입</strong> 언어들이었다. 
그렇다면 정적타입/동적타입 언어는 뭐고 어떤 특성을 가질까? <a href="https://algorfati.tistory.com/112">참고 블로그</a> 에서 좋은 자료를 가져왔다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/31607c00-13bd-4a31-b02a-5c671db60c5a/image.png" alt=""></p>
<blockquote>
</blockquote>
<ul>
<li>정적타입: 컴파일 시 변수 타입 결정. 코드에 자료형 명시 필요. 
ex) C, C++, C#, JAVA
장점: 타입에러 문제를 컴파일시 해결 가능해서 안정성 높음, 속도 빠름
단점: 타입 제한으로 유연성 낮음 </li>
</ul>
<blockquote>
</blockquote>
<ul>
<li>동적타입: 런타임 시 자료형이 결정되는 언어. 자료형 명시 필요 X.
ex) 자바스크립트, 파이썬, 루비
장점: 타입제한이 없어 유연성 높음, 효율적
단점: 속도 느림, 타입 리스크를 런타임에 감당해야 함. 오탈자로 인한 리스크도...</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[251007 - (UNIX시스템) find도 쓰고 chmod도 쓰고싶을 땐]]></title>
            <link>https://velog.io/@liha_engineer/251007</link>
            <guid>https://velog.io/@liha_engineer/251007</guid>
            <pubDate>Tue, 07 Oct 2025 13:19:43 GMT</pubDate>
            <description><![CDATA[<h3 id="파일도-찾고싶고-권한도-변경하고-싶다고">파일도 찾고싶고 권한도 변경하고 싶다고?</h3>
<blockquote>
</blockquote>
<p>현재 작업 디렉토리(서브 디렉토리 포함)에 존재하는 정규 파일 중 이름이 &#39;.json&#39;으로 끝나는 모든 파일을 찾아 접근권한을 644로 변경하고 파일의 절대경로를 터미널에 출력하는 명령을 작성할 것</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/5291948c-fa08-48e0-b5b0-1660b0cbef50/image.png" alt=""></p>
<h4 id="-뭐라는-거야">???? 뭐라는 거야?</h4>
<p>find로는 찾고 chmod로는 수정할 수 있는데, 저걸 한꺼번에 하는 명령을 작성하라고?</p>
<h3 id="놀랍게도-이걸-한-행으로-쓸-수-있다---find를-사용하자">놀랍게도 이걸 한 행으로 쓸 수 있다 - find를 사용하자</h3>
<p>find를 쓰고 -exec로 chmod를 사용하면, find문에 걸린 조건에 부합하는 각 검색 결과(만약 12개라면 12개 각각)에 대해 -exec 이후의 액션을 실행할 수 있다. 
그러므로 내가 할 것을 정리하면 다음과 같다. 흔히 말하는 바이브 코딩 식으로 써보자.</p>
<blockquote>
</blockquote>
<p>find (유형이 파일) (.json으로 끝나는 것) (출력해줘) -exec chmod (서브 디렉토리까지) (권한 644로 바꿔줘) {} ;</p>
<pre><code class="language-shell">find -type f -name \*.json -print -exec chmod -R 644 {} \;</code></pre>
<p>이런 형태의 find문으로 꾸려봤다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/971abbe9-62f9-48d7-b964-718d43dea0de/image.png" alt=""></p>
<p>무사히 출력된다. 
그런데 여기서 잠깐. <strong>이 파일들의 권한이 정말 644로 변경된 게 맞을까?</strong>
나는 의심쟁이니까 -perm 644로 확인해봐야지.</p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/77f44f2f-0d91-4313-af17-2355b784ba4d/image.png" alt=""></p>
<p>무사히 설정된 것이 맞다. 흡-족.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[251003 - 처음 써보는 Rocky Linux ]]></title>
            <link>https://velog.io/@liha_engineer/251003</link>
            <guid>https://velog.io/@liha_engineer/251003</guid>
            <pubDate>Fri, 03 Oct 2025 09:30:26 GMT</pubDate>
            <description><![CDATA[<h3 id="처음엔-보였는데-지금은-메뉴가-보이지-않아요---시작맥은-super-키를-누르자">처음엔 보였는데 지금은 메뉴가 보이지 않아요 - 시작(맥은 super) 키를 누르자</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/354a63dd-6f76-45ae-89a3-926b9ee07889/image.png" alt="">
배쉬를 써야하는데 메뉴가 보이지 않는다. 화면을 드래그해도 나오지 않아 검색을 해봤더니 시작 키를 누르면 된다고 한다. </p>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/93a131a1-5e2e-45a0-960e-d2d36c2ad16c/image.png" alt=""></p>
<p>찾았다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[250925 - 게임개발자를 위한 C++문법 wk1]]></title>
            <link>https://velog.io/@liha_engineer/250925-%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-C%EB%AC%B8%EB%B2%95-wk1</link>
            <guid>https://velog.io/@liha_engineer/250925-%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-C%EB%AC%B8%EB%B2%95-wk1</guid>
            <pubDate>Thu, 25 Sep 2025 14:28:42 GMT</pubDate>
            <description><![CDATA[<h3 id="기본-내장-헤더는--내가-만든-헤더는">기본 내장 헤더는 &lt;&gt;, 내가 만든 헤더는 &quot;&quot;</h3>
<p>그래서 iostream은 <code>#include &lt;iostream&gt;</code> 인 것. </p>
<h3 id="시작점진입점은-main함수">시작점/진입점은 main함수</h3>
<p>메인함수가 가장 먼저 호출된다. </p>
<h3 id="변수의-타입에-따라-차지하는-메모리의-크기가-다르다---왜-다를까">변수의 타입에 따라 차지하는 메모리의 크기가 다르다 - 왜 다를까?</h3>
<p>컴퓨터를 놓을 공간과 콜라 한 캔을 놓을 공간이 다르듯, 보통 공간이 많이 필요한 타입과 적게 필요한 타입에게 다 같은 공간을 주는 것은 오히려 불합리. 메모리는 유한한 자원이기 때문에 가능한 효율적으로 사용해야 한다. </p>
<p>부동소수점 표시는 float가 7~8자리, double이 15자리까지 보장해서 정밀도가 높다. 그러니 웬만하면 그냥 double을 쓰는 것이 좋다. </p>
<h3 id="과-은-다르다는-건-알지만">=과 ==은 다르다는 건 알지만...</h3>
<p>그래서 정확히 보자면 =은 대입, ==은 <strong>비교</strong>. if문 같은데 넣어서 쓸 수 있고, console.log로 찍을 수도 있다. </p>
<h3 id="전위연산과-후위연산은-그래서-정확히-어떻게-다를까">전위연산과 후위연산은, 그래서 정확히 어떻게 다를까?</h3>
<p><img src="https://velog.velcdn.com/images/liha_engineer/post/18e0b875-17d5-4e19-99b7-8a6875828d86/image.png" alt=""></p>
<p>이미지를 참고해보자. 
후위연산의 경우 <code>int b = a++;</code> 이라고 쓰면 얼핏 봤을 때 &#39;a를 더한 다음에 b에 넣는 건 똑같잖아? 둘이 왜 다른거야?&#39; 라는 생각이 들 수 있다. *<em>그러나 이 문장(?)은 엄밀히는 a와 ++을 따로 떼서 봐야한다. a를 b에다 대입한 다음에 +1을 하겠다는 것. *</em></p>
<h3 id="내용이-문자-한-개여도-쌍따옴표라면-문자열이다">내용이 문자 한 개여도, 쌍따옴표라면 &#39;문자열&#39;이다.</h3>
<p>&#39;a&#39;와 &quot;a&quot;는 다르다. </p>
<h3 id="야호">야호!</h3>
]]></description>
        </item>
    </channel>
</rss>