<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>u_u.log</title>
        <link>https://velog.io/</link>
        <description>남을 위해(나를 위해) 글을 쓰는 Velog </description>
        <lastBuildDate>Wed, 12 Jun 2024 06:21:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>u_u.log</title>
            <url>https://velog.velcdn.com/images/u_u/profile/a30bd28a-794c-4fe4-88d4-904a3fb91c42/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. u_u.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/u_u" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[React] useId]]></title>
            <link>https://velog.io/@u_u/React-useId</link>
            <guid>https://velog.io/@u_u/React-useId</guid>
            <pubDate>Wed, 12 Jun 2024 06:21:50 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>고유 ID를 생성하기 위한 React Hook</p>
</blockquote>
<h3 id="장점">장점</h3>
<blockquote>
<p>input 같은 Form요소에 접근성 관련 속성을 제공할 때 유용하다.</p>
</blockquote>
<ul>
<li>useId()로 생성한 객체 한 개를 가지고 라벨과 Form요소에 매칭을 시켜줘 라벨을 클릭했을 때 해당 Form요소가 활성화 시키게 할 수 있다.</li>
</ul>
<pre><code>function App() {
    const id = useId();
    console.log(id) // :r0:

    return(
        &lt;div&gt;
            &lt;label htmlFor=&quot;name&quot;&gt;이름&lt;/label&gt;
            &lt;input id=&quot;name&quot;/&gt;
        &lt;/div&gt;
    );
}</code></pre><pre><code>function App() {
    const id = useId();
    console.log(id) // :r0:

    return(
        &lt;div&gt;
            &lt;label htmlFor={`${id}-name`&gt;이름&lt;/label&gt;
            &lt;input id={`${id}-name`} /&gt;
            &lt;br /&gt;
            &lt;label htmlFor={`${id}-age`&gt;나이&lt;/label&gt;
            &lt;input id={`${id}-age`}/&gt;
        &lt;/div&gt;
    );
}</code></pre><ul>
<li>쌍점<ul>
<li>useId를 통해서 만든 id는 <code>:</code>을 포함하고 있기 때문에 querySelector가 잘 인식하지 못한다.
그래서 에러가 생긴다.</li>
<li>React는 DOM요소에 접근하기 위해 ref값을 사용하고 있다. -&gt; 굳이 querySelector를 사용할 필요가 없다.</li>
<li>React를 사용해서 개발을 할 때 querySelector 사용을 지양한다. -&gt; useId를 통해서 React에 맞게 사용하기를 바라기? 때문이다.</li>
</ul>
</li>
<li>안정성<ul>
<li>예를 들어 <code>Math.Random()</code>을 사용해서 id를 사용할 경우 id값이 매번 바뀌기 때문에 스크린리더를 사용하는 분들은 불편함을 호소한다.</li>
<li>컴포넌트 렌더링이 발생해도 id값이 유지되기 때문에 안정적이다</li>
<li>SSR 컴포넌트의 경우 서버에서 렌더링 된 결과물과 클라이언트에서 렌더링 된 결과물이 다른 경우가 존재한다.</li>
<li>useId()를 사용할 경우 안정적인 id값을 생성한다.
  -&gt; 단, 서버와 클라이언트에서 컴포넌트 트리가 동일해야한다.</li>
</ul>
</li>
</ul>
<h3 id="reference">Reference</h3>
<p><a href="https://ko.react.dev/reference/react/useId">React useId()</a>
<a href="https://youtu.be/y0vhpilNSKo?feature=shared">별코딩 Youtube</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JWT] 로그인 인증 및 토큰 관리에 대해서]]></title>
            <link>https://velog.io/@u_u/JWT-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%ED%86%A0%ED%81%B0-%EA%B4%80%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</link>
            <guid>https://velog.io/@u_u/JWT-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%9A%8C%EC%9B%90%EA%B0%80%EC%9E%85-%ED%86%A0%ED%81%B0-%EA%B4%80%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</guid>
            <pubDate>Sun, 10 Mar 2024 09:15:14 GMT</pubDate>
            <description><![CDATA[<h1 id="서론">서론</h1>
<p>팀 스파르타 회사의 프로덕트 캠프 2기를 진행하면서 느낀 점들을 바탕으로 보안에 대해서도 중요하다고 생각하여 이 글을 작성합니다.</p>
<p>먼저 간략하게 과정을 소개하자면,</p>
<blockquote>
<p>ZERO TO ONE, 12주 간 현업과 동일한 팀 구성으로 진행하고, 실제 사용자를 모집하여 창업까지!</p>
</blockquote>
<p>라는 목표로 PO, Designer, FE, BE 각 1명씩 총 4명 한 팀으로 진행하였습니다.</p>
<p>이에 따라서 MVP 배포 이후 사용자를 모집하고 실제 유저들이 유입이 되는 상황에서 문득 지난 뉴스들이 스쳐 지나갔습니다.</p>
<blockquote>
<p>모 회사에서 얼마동안 개인정보가 유출이 돼 수만명의 개인정보가 유출되었다! 
어느회사 서비스의 어떤 파일이 보안취약점이 발견돼 신속한 대응을 해야한다!
라는 뉴스가 심심치 않게 종종 들렸었습니다.</p>
</blockquote>
<p>이런 이유로 저 또한 심지어 아직 상용서비스화 된 것도 아닌 서비스에서 회원가입한 고객들에게 피해가 가면 안되겠다라는 생각으로 기존 로그인 인증 방식을 수정해야할 필요성을 느꼈습니다.</p>
<h2 id="jwt-란">JWT 란</h2>
<blockquote>
<p>JWT : JSON Web Token</p>
</blockquote>
<p>JSON 형태의 객체 정보를 암호화하여 웹 인증에 사용할 수 있는 토큰.</p>
<p>구성으로는 Header, Payload, Signature로 <code>aaaaa.bbbbb.ccccc</code>와 같은 형태를 띄고 있다.</p>
<h3 id="header">Header</h3>
<p>헤더에는 토큰 타입, 토큰을 암호화하는 방식이 담겨있습니다.</p>
<pre><code>{
  &quot;alg&quot;: &quot;HS256&quot;,
  &quot;typ&quot;: &quot;JWT&quot;
}</code></pre><p>예시로 이 JSON은 Base64Url로 인코딩되어 헤더를 구성합니다</p>
<h3 id="payload">Payload</h3>
<p>페이로드는 Claim이라는 사용자에 대한 프로퍼티나 속성을 담고 있습니다.
그리고 claim에는 3가지 타입이 존재하는데, <code>registered, public, and private</code> 타입이 존재합니다.</p>
<p>claim 방식은 요청받는 서버입장에서 페이로드 값을 통해 사용자에 대한 정보를 다른 곳에서 더 가져올 필요가 없다는 것이다.</p>
<h4 id="registered-claim">registered claim</h4>
<p>registered claim은 유용하고 상호 운용 가능한 클레임 집합을 제공하기 위해 필수는 아니지만 권장되는 미리 정의된 클레임 집합입니다.
예시로 iss (발행자), exp (만료 시간), sub (주제), aud (청중) 등이 있는데 3글자로 구성되어 있습니다.</p>
<h4 id="public-claim">public claim</h4>
<p>public claim은 JWT를 사용하는 사람들이 원하는 대로 정의할 수 있습니다. 그러나 충돌을 방지하려면 IANA JSON 웹 토큰 레지스트리 에 정의하거나충돌 방지 네임스페이스를 포함하는 URI로 정의해야 합니다.</p>
<h4 id="private-claim">private claim</h4>
<p>private claim은 사용에 동의한 당사자 간에 정보를 공유하기 위해 생성된 맞춤 클레임으로, 등록되거나 공개 된 클레임이 아닙니다.</p>
<pre><code>{
  &quot;sub&quot;: &quot;1234567890&quot;,
  &quot;name&quot;: &quot;John Doe&quot;,
  &quot;admin&quot;: true
}</code></pre><p>예시로 이 정보는 마찬가지로 Base64Url로 인코딩되어 페이로드를 구성합니다.</p>
<blockquote>
<p><em>NOTE</em> : 헤더나 페이로드는 단순히 Base64Url로 인코딩 되어 있기 때문에 개인정보와 같은 보안에 민감한 정보는 담지 않는 것이 좋다.</p>
</blockquote>
<p>추가적으로 그렇다면 토큰의 장점이 세션과 다르게 DB와 같이 다른 곳에서 정보를 확인하는 절차를 거치지 않는다는 것이 있는데, 결국 사용자 정보를 조회해야 하는 경우 마찬가지로 DB에 접근해야하지 않는가? 라는 질문을 할 수 있을 것이다.</p>
<p>물론 그런 경우에는 내 생각에는 필요한 것이라고 생각한다. 하지만 로그인한 유저에게만 보여줄 수 있는 페이지의 경우 해당 토큰만 가지고 라우팅을 컨트롤할 수 있기 때문에 조금 더 부하를 줄일 수 있지 않을까 생각한다.</p>
<h3 id="signature">Signature</h3>
<p>Signature는 인코딩된 헤더와 페이로드 그리고 시크릿 키를 통해 암호화하여 저장하여 해당 시크릿 키(대칭 키)를 통해 토큰이 위변조 되었는지 확인할 수 있다.</p>
<pre><code>HMACSHA256(
  base64UrlEncode(header) + &quot;.&quot; +
  base64UrlEncode(payload),
  secret)</code></pre><h3 id="특징">특징</h3>
<ol>
<li>jwt방식은 특정 경우에 state-less할 수 있다.
 -&gt; 내 경우에 Refresh Token을 DB에 저장하여, Access Token을 발급할 때 사용하여 state-ful, Access Token의 경우 서버와 통신에만 사용하기 때문에 이 경우에는 state-less하다.</li>
<li>토큰만 사용하여 사용자 인증을 진행할 수 있다. 
 -&gt; 추가적인 서버/DB에 접근할 필요가 없어 서버의 부하를 줄일 수 있다.</li>
<li>일부 서버에서 8KB의 제한이 있을 수 있기 때문에 가급적 크기를 작게 해야한다.
 -&gt; 불필요한 데이터를 넣지 않아야한다.</li>
<li>세션 방식은 탈취된 경우 세션을 만료시켜 추가적인 피해를 막을 수 있지만, 토큰 방식은 탈취된 토큰을 만료시킬 방법이 없다. -&gt; 주기적인 갱신이 필요하다. -&gt; 안정성은 높아지지만 지속적인 자원을 소모하게 된다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/u_u/post/c72f640c-2b98-4312-888c-251ca3b7d05e/image.png" alt=""></p>
<p>JWT 공식 사이트에서 제공해주는 다이어그램으로 JWT 발급, 인증 방식에 대해서 보여주고 있습니다.</p>
<h1 id="본론">본론</h1>
<h3 id="기존-방식">기존 방식</h3>
<p>단순히 JWT 방식을 사용하여 프론트에선 Access Token, Refresh Token을 쿠키에 저장하여 Access Token 하나만 사용하고 백엔드에선 토큰을 DB에 저장하여 비교하는 <code>토큰을 사용한 세션 방식</code>을 사용해왔습니다.</p>
<p>하지만 사용자가 하나 둘 늘어남에 따라 지난 날 보안과 관련하여 뉴스에 개인정보유출에 대해서 보도가 되었던게 생각이 났습니다.</p>
<p>그래서 개인정보보호를 위해 인증에 대해서 보안을 향상시켜야 할 필요성을 느끼게 되었고 더욱 알아보기로 하였습니다.</p>
<h3 id="개선하려는-방식">개선하려는 방식</h3>
<p>Access Token과 Refresh Token을 용도에 맞게 사용한다.
-&gt; Access Token을 인가를 위한 용도로, Refresh Token은 Access Token을 재발급 하는 용도로 사용한다.</p>
<p>그리고 보관하는 방식을 쿠키에 담아두는게 아닌 Access Token을 메모리에,  Refresh Token은 쿠키에 저장한다.</p>
<p>또한 옵션으로 httponly, secure, samesite등을 설정하여 추가적으로 보안을 향상시킨다.</p>
<h3 id="이유">이유</h3>
<p>이렇게 하는 이유는 메모리에 Access Token을 저장할 경우 휘발되는 성격을 활용해 보안을 향상할 수 있다고 생각한다.
그리고 쿠키에 Refresh Token을 저장하는 이유는 통신할 때 쿠키에 담긴 Refresh Token을 자동으로 보내 만료 여부와 오염 여부를 확인하여 재발급을 진행하기 위해 이러한 방식을 사용하려고 한다.</p>
<h3 id="과정">과정</h3>
<p>Access Token을 메모리에 저장하려는 과정에서 사용하던 상태관리 라이브러리를 통해 저장하려고 하였으나, 저장이 되지 않아 결국 local storage에 Access token을 저장하고, 쿠키에만 Refresh token을 저장하였다.</p>
<h3 id="결과">결과</h3>
<p>Refresh Token의 생명주기에 따라 미리 silent fresh 로직을 추가해 사용자가 모르게 Access Token을 재발급하도록 하여 상황에 따라 Access Token, Refresh Token을 재발급하여 사용할 수 있게 하였다, 만약 새로고침이나 모종의 이유로 인해 해당 로직이 재수행이 안될 경우 Axios interceptor를 사용하여 Access Token의 만료 여부를 확인하여 재발급한 토큰을 가져와 통신을 이어가도록 진행하여 UX를 개선하였다.</p>
<h3 id="결론">결론</h3>
<p>작성한 시점이 많은 시간이 지난 후여서 미흡한 부분이 많지만 이후 다시 토큰을 사용하는 로직을 만들어야할 경우 이 경험을 바탕으로 더욱 공부하고 보완하여 개발할 수 있도록 해야겠다.</p>
<h3 id="출처">출처</h3>
<p><a href="https://jwt.io/introduction">JWT 공식사이트</a>
<a href="https://velog.io/@yaytomato/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%90%EC%84%9C-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0">프론트에서-안전하게-로그인-처리하기</a>
<a href="https://12bme.tistory.com/130">https://12bme.tistory.com/130</a>
<a href="https://puleugo.tistory.com/138">https://puleugo.tistory.com/138</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 동기/비동기 작업, 이벤트 루프에 대해서]]></title>
            <link>https://velog.io/@u_u/%EB%8F%99%EA%B8%B0%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</link>
            <guid>https://velog.io/@u_u/%EB%8F%99%EA%B8%B0%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C</guid>
            <pubDate>Mon, 29 Jan 2024 09:00:53 GMT</pubDate>
            <description><![CDATA[<h2 id="서론">서론</h2>
<p>프로젝트를 진행하다가 문득 자바스크립트의 동작 원리가 궁금했다. </p>
<blockquote>
<p>자바스크립트는 싱글스레드 언어인데 비동기 처리를 어떻게 하는거지?</p>
</blockquote>
<p>여기서 궁금증이 출발하여 같이 일하는 벡엔드 동료와 얘기를 해보는데 백그라운드 스레드가 비동기를 처리한다는 얘기를 들었다. 그렇다면 백그라운드 스레드는 어디에 있는거지? 싱글스레드인 자바스크립트가 다른 스레드를 더 사용할 순 없고... 명확한 팩트인 <code>자바스크립트는 싱글스레드 언어이다</code>를 바탕으로 추론을 진행하였지만 논의끝에 도달한 결론이 틀렸기 때문에 자세하게 알아보고자 한다. </p>
<h2 id="본론">본론</h2>
<blockquote>
<p>자바스크립트는 <code>싱글스레드</code> 언어이다.</p>
</blockquote>
<p>먼저 문장을 이해하려면 단어를 이해해야 하기 때문에 스레드가 무엇인지 생각해보자.</p>
<p><code>스레드</code>는 프로그램을 실행했을 때 프로세스가 진행되는데 이때 프로세스에서 사용되는 <code>작업의 최소단위</code>를 스레드라고 한다.</p>
<p>그러면 자바스크립트는 프로그램이 실행됐을 때 하나의 스레드를 사용하여 프로그램을 동작한다고 이해할 수 있다.</p>
<p>그렇다면, 단순하게 생각해본다면 작업을 하나로만 한다고 이해했을 때 순차적으로 하나 시작하면 하나 마무리하는 방식인가?라고 고민할 수 있을 것이다.</p>
<pre><code class="language-JS">  let count = 0;
  function foo() {
    console.log(&#39;foo&#39;, count++);
    setTimeout(() =&gt; console.log(&#39;setTimeout&#39;, count), 0);
    bar();
  }
  function bar() {
    console.log(&#39;bar&#39;, count++);
  }

  console.log(&#39;start&#39;);
  foo()
  bar()
  console.log(&#39;end&#39;)

/** output
start
foo 0
bar 1
bar 2
end
setTimeout 3
*/</code></pre>
<p>위 코드를 실행했을 때 출력 값은 저렇게 <code>star</code>, <code>end</code> 이후에 <code>setTimeout 3</code> 이라고 출력이 되는데,</p>
<p>앞서 언급한 방식대로 이해했더라면 아래처럼 출력되어야 하지 않을까? 생각해볼 수 있다.</p>
<pre><code class="language-JS">/** output
start
foo 0
setTimeout 1
bar 2
bar 3
end
*/</code></pre>
<p>결과값을 보면 setTimeout 안에 있는 console.log 함수가 설정한 시간 후에 따로 출력되는 모습을 알 수 있는데 어떻게 된 걸까?</p>
<h3 id="어떻게-비동기-처리를-하나요">어떻게 비동기 처리를 하나요?</h3>
<blockquote>
<p>결론부터 말하자면 자바스크립트를 실행했을 때 <code>런타임 환경</code>에서 비동기 로직들을 따로 처리해주는 것이다.</p>
</blockquote>
<p>setTimeout이라는 함수가 런타임 환경에서 실행하고 있기 때문에 비동기적으로 코드가 실행되는 것이다.</p>
<p>자바스크립트를 실행했을 때 그 언어를 실행시켜주는 환경이 있을 것인데, 런타임 환경이라고 부른다. 런타임 환경은 <code>Browser</code>(주로 크롬 사파리와 같은) 또는 <code>Node.js</code>가 있다.</p>
<p>크롬을 예를 들자면 프로그램이 브라우저 상에서 실행 됐을 때 <code>Chrome V8</code> 엔진을 이용해 코드를 실행하고 크롬 브라우저에서 DOM 관리, 이벤트 처리, 네트워크 통신 등을 담당한다.</p>
<blockquote>
<p>약간 더 깊게 들어가보자</p>
</blockquote>
<h3 id="자바스크립트의-동작원리">자바스크립트의 동작원리</h3>
<p><img src="https://velog.velcdn.com/images/u_u/post/4fffcd56-a123-4880-856d-3933c05ab45b/image.png" alt=""></p>
<p>자바스크립트의 동작원리를 살펴보면 <code>스택</code> 하나를 가지고 저장되어 있는 일들을 한 번에 하나씩만 처리할 수 있다. 여기서 중요한 규칙은 메시지 큐의 작업은 항상 콜스택이 비었을 때 실행된다는 점이다.</p>
<ul>
<li>Stack: 함수를 호출했을 때 콜스택이 쌓이는 스택 영역</li>
<li>Queue: 런타임이 처리해야할 일들을 줄 세우는 메시지(태스크, 콜백) 큐</li>
<li>Heap: 객체들을 저장하기 위한 메모리 영역 힙</li>
</ul>
<blockquote>
<p>setTimeout 같은 타이머 함수는 설정한 시간 후 콜백을 바로 실행하지 않고 메시지 큐로 보내기 때문에 실행 시간이 정확히 보장되지 않는다</p>
</blockquote>
<h4 id="event-loop">Event Loop</h4>
<p>그리고 위 그림에서 보면 <code>Event Loop</code>라는게 있는데 매우 중요한 요소이다. Event Loop는 stack이 텅 비었을 때(main 코드가 다 실행된 후) 비로소 큐에 있는 로직들을 처리한다.</p>
<h4 id="event-loop-특징">Event Loop 특징</h4>
<p>이벤트 루프의 특징 중에 다음 메세지를 실행하기 이전에 기존 메세지의 실행을 완료한다는 특징이 있다.</p>
<p>이와 같은 특징 덕분에 JS는 공유자원에 대해서 뮤택스와 세마포어와 같은 선점의 기능을 제공하지 않아 동작의 추론이 쉽지만, 단점으로 메시지를 처리할 때 너무 오래 걸리면 웹 애플리케이션이 클릭이나 스크롤과 같은 사용자 상호작용을 처리할 수 없다는 점이 있다.</p>
<p>그래서 예를 들어 브라우저는 &quot;스크립트 응답 없음&quot; 대화상자를 표시해서 이 문제를 완화할 수 있고, 따라서 우리는 메시지 처리를 가볍게 유지하고, 가능하다면 하나의 메시지를 여러 개로 나누는게 현명할 것이다.</p>
<blockquote>
<p>메인 스레드와 이벤트 루프에 한해서는 동시성이 없다고 할 수 있지만 런타임 환경 덕분에 동시성이 있다고 할 수 있다.</p>
</blockquote>
<h2 id="결론">결론</h2>
<blockquote>
<p>따라서 자바스크립트는 <code>싱글스레드 언어</code>라고 하는 것이다.</p>
</blockquote>
<p>글이 잘 읽히지 않는다면, Blocking-Non Blocking &amp; Synchronous-Asynchronous, 동시성과 병렬성에 대해서 이해하고 출처를 참고해보면 좋을 것 같다.</p>
<h2 id="tmi">TMI</h2>
<p>프로젝트를 진행하며 많이 배우기도 하고 느낀점도 많았지만 많이 함축해서 생각을 말해보자면, 기술적인 부분에서 크게 와닿았던 것은 <code>기초가 탄탄해야 한다</code>는 것이었다. 코드를 작성할 때 왜 그렇게 작성했는지 분명히 알아야하고, 프레임워크나 라이브러리를 사용하지 않고 바닐라 JS로 작성할 수 있도록 해야 어느 환경에서든 살아남고 그만큼 능력있는 개발자라고 인정받을 수 있지 않을까 싶다.</p>
<h4 id="기술-발전-속도가-매우-빠른-현재-도태되지-않기-위해-변하지-않는-것들에-집중해서-적응력과-습득력이-뛰어난-개발자가-되도록-하자">기술 발전 속도가 매우 빠른 현재 도태되지 않기 위해 변하지 않는 것들에 집중해서 적응력과 습득력이 뛰어난 개발자가 되도록 하자.</h4>
<blockquote>
<p>살아남았다는 것은 강하다는 것</p>
</blockquote>
<h3 id="출처">출처</h3>
<p><a href="https://medium.com/@lifthus531/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B9%8A%EC%9D%80-%EC%9D%B4%ED%95%B4-dd4fd47d8917">자바스크립트 동작 원리에 대한 깊은 이해</a>
<a href="https://medium.com/@lifthus531/%EB%8F%99%EC%8B%9C%EC%84%B1%EA%B3%BC-%EB%B3%91%EB%A0%AC%EC%84%B1%EC%9D%98-%EC%B0%A8%EC%9D%B4-52f9716c3be4">동시성과 병렬성의 차이</a>
<a href="https://medium.com/@vdongbin/javascript-%EC%9E%91%EB%8F%99%EC%9B%90%EB%A6%AC-single-thread-event-loop-asynchronous-e47e07b24d1c">Javascript 동작원리 (Single thread, Event loop, Asynchronous)</a>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Event_loop">MDN Event Loop</a>
<a href="https://www.youtube.com/watch?v=v67LloZ1ieI">유튜브 코딩애플 자바스크립트 동작원리</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] TypeScript]]></title>
            <link>https://velog.io/@u_u/TS-TypeScript</link>
            <guid>https://velog.io/@u_u/TS-TypeScript</guid>
            <pubDate>Mon, 09 Oct 2023 13:37:58 GMT</pubDate>
            <description><![CDATA[<h1 id="typescript">TypeScript</h1>
<blockquote>
<p>TypeScript = Language</p>
</blockquote>
<ul>
<li>자바스크립트의 슈퍼셋</li>
<li>프로그래밍 언어</li>
<li>컴파일 언어 (JS : 인터프리터 언어)</li>
<li>전통적인 컴파일 언어와 다른 점이 많아서 &#39;Transpile&#39; 이라는 용어를 사용하기도 한다.</li>
<li>컴파일 하는 과정에서 중요하게 여기는 것이 <code>Type</code>. 컴파일 단계에서 <code>타입</code>을 확인하며 진행</li>
</ul>
<h3 id="정적-타입-언어-vs-동적-타입-언어">정적 타입 언어 VS 동적 타입 언어</h3>
<p>정적 타입 언어는 미리 타입을 정해놓고 시작하는 언어</p>
<p>기존의 자바스크립트로 프로그래밍을 할 때에 덩어리가 컸을 때 에러를 잡기 어려움이 발생 잡더라도, 동시 다발적으로 추가 에러가 발생 따라서 정적 타입 언어의 장점을 모아보자 해서 만든 것이 <code>타입스크립트</code></p>
<p>동적 타입 언어가 가지고 있는 단점을 극복하기 위해 테스트 코드 사용
-&gt; 테스트 커버리지를 올리는 일이 가면 갈수록 힘들어짐.</p>
<p>정적 타입 언어들이 지향하는게 테스트 커버리지를 일정 부분 타입 체킹을 하면서 막아준다는 의미를 갖고 있다.</p>
<h3 id="traditional-compiled-language">Traditional Compiled Language</h3>
<p><code>Source Code</code> (컴파일)-&gt; <code>Object Code</code> (링킹)-&gt; 실행 파일</p>
<blockquote>
<p>타입스크립트 문법으로 작성한 소스 코드를 컴파일해준 컴파일이 타입스크립트 컴파일러, 결과물이 자바스크립트이다.</p>
</blockquote>
<p>따라서 타입스크립트에는 링킹 과정이 없다.</p>
<p>출처 : <a href="https://www.inflearn.com/course/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%BD%94%EB%A6%AC%EC%95%84-1705-%EA%B8%B0%EC%B4%88-%EC%84%B8%EB%AF%B8%EB%82%98/">인프런 타입스크립트 코리아 : 기초 세미나</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 백준 2178 JS]]></title>
            <link>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-2178-JS</link>
            <guid>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-2178-JS</guid>
            <pubDate>Mon, 25 Sep 2023 08:48:22 GMT</pubDate>
            <description><![CDATA[<h2 id="백준--2178--js--bfs">백준 / 2178 / JS / BFS</h2>
<p><a href="https://www.acmicpc.net/problem/2178">https://www.acmicpc.net/problem/2178</a></p>
<blockquote>
<p>문제</p>
</blockquote>
<p>N×M크기의 배열로 표현되는 미로가 있다.</p>
<p>1    0    1    1    1    1
1    0    1    0    1    0
1    0    1    0    1    1
1    1    1    0    1    1
미로에서 1은 이동할 수 있는 칸을 나타내고, 0은 이동할 수 없는 칸을 나타낸다. 이러한 미로가 주어졌을 때, (1, 1)에서 출발하여 (N, M)의 위치로 이동할 때 지나야 하는 최소의 칸 수를 구하는 프로그램을 작성하시오. 한 칸에서 다른 칸으로 이동할 때, 서로 인접한 칸으로만 이동할 수 있다.</p>
<p>위의 예에서는 15칸을 지나야 (N, M)의 위치로 이동할 수 있다. 칸을 셀 때에는 시작 위치와 도착 위치도 포함한다.</p>
<blockquote>
<p>입력</p>
</blockquote>
<p>첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.</p>
<blockquote>
<p>출력</p>
</blockquote>
<p>첫째 줄에 지나야 하는 최소의 칸 수를 출력한다. 항상 도착위치로 이동할 수 있는 경우만 입력으로 주어진다.</p>
<blockquote>
<p>풀이</p>
</blockquote>
<p>0,0 위치에서 n,m 위치로 최소경로로 도달할 때 값을 구하기 위해 다음 위치는 현재 위치에서 1을 더한 값이 되기 때문에 다음 위치에 현재 위치까지 이동한 값을 더하면서 최종 위치의 값을 탐색을 마치고 출력한다.</p>
<pre><code class="language-JS">let input = require(&#39;fs&#39;)
  .readFileSync(__dirname + &#39;/input.txt&#39;, { encoding: &#39;utf-8&#39; })
  .split(&#39;\n&#39;);
const [n, m] = input.shift().split(&#39; &#39;).map(Number);
const graph = input.map((e) =&gt; e.split(&#39;&#39;).map(Number));
const visited = Array.from(Array(n), () =&gt; Array(m).fill(false));
const dy = [-1, 1, 0, 0];
const dx = [0, 0, -1, 1];

const bfs = (y, x) =&gt; {
  let queue = [[y, x]];
  while (queue.length) {
    const [cy, cx] = queue.shift();
    for (let i = 0; i &lt; 4; i++) {
      const ny = dy[i] + cy;
      const nx = dx[i] + cx;
      if (ny &gt;= 0 &amp;&amp; ny &lt; n &amp;&amp; nx &gt;= 0 &amp;&amp; nx &lt; m) {
        if (!visited[ny][nx] &amp;&amp; graph[ny][nx]) {
          visited[ny][nx] = true;
          // 핵심 : bfs로 탐색하면서 다음 위치의 값은 현재 위치에서 1을 더한 값이 되기 때문에
          // 다음 위치는 현재 위치의 값을 더한 값이 되게 하였다.
          graph[ny][nx] += graph[cy][cx];
          queue.push([ny, nx]);
        }
      }
    }
  }
};

bfs(0, 0);
// 최종 위치에 도달헀을때가 결국 0, 0 에서 시작해서 도착지점까지 1씩 더한 값이 되기때문에 최솟값이 된다.
console.log(graph[n - 1][m - 1]);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 백준 4963 JS]]></title>
            <link>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-4963-JS</link>
            <guid>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-4963-JS</guid>
            <pubDate>Fri, 22 Sep 2023 14:50:43 GMT</pubDate>
            <description><![CDATA[<h2 id="백준--4963--js--bfs">백준 / 4963 / JS / BFS</h2>
<p><a href="https://www.acmicpc.net/problem/4963">https://www.acmicpc.net/problem/4963</a></p>
<blockquote>
<p>문제</p>
</blockquote>
<p>정사각형으로 이루어져 있는 섬과 바다 지도가 주어진다. 섬의 개수를 세는 프로그램을 작성하시오.</p>
<p>한 정사각형과 가로, 세로 또는 대각선으로 연결되어 있는 사각형은 걸어갈 수 있는 사각형이다. </p>
<p>두 정사각형이 같은 섬에 있으려면, 한 정사각형에서 다른 정사각형으로 걸어서 갈 수 있는 경로가 있어야 한다. 지도는 바다로 둘러싸여 있으며, 지도 밖으로 나갈 수 없다.</p>
<blockquote>
<p>입력</p>
</blockquote>
<p>입력은 여러 개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 지도의 너비 w와 높이 h가 주어진다. w와 h는 50보다 작거나 같은 양의 정수이다.</p>
<p>둘째 줄부터 h개 줄에는 지도가 주어진다. 1은 땅, 0은 바다이다.</p>
<p>입력의 마지막 줄에는 0이 두 개 주어진다.</p>
<blockquote>
<p>출력</p>
</blockquote>
<p>각 테스트 케이스에 대해서, 섬의 개수를 출력한다.</p>
<blockquote>
<p>풀이</p>
</blockquote>
<p>기본적인 BFS 탐색이나 대각선이 포함되기 때문에 방문할 때 이중 for문을 사용하여 해당 좌표의 주변을 다 탐색한다.</p>
<pre><code class="language-JS">let input = require(&#39;fs&#39;)
  .readFileSync(__dirname + &#39;/input.txt&#39;, { encoding: &#39;utf-8&#39; })
  .split(&#39;\n&#39;);
let w = 1;
let h = 1;
let visited = [];
let land = [];
let answer = 0;
const dy = [-1, 1, 0, 0];
const dx = [0, 0, -1, 1];

const bfs = (y, x) =&gt; {
  const queue = [];
  queue.push([y, x]);
  while (queue.length !== 0) {
    const [cy, cx] = queue.shift();
    // 핵심 : 대각선도 연결된 섬이기 때문에 다음 섬으로 가기위한 방향을 정할 때 이중 for문을 사용해 대각선도 체크한다.
    for (let i = 0; i &lt; 4; i++) {
      for (let j = 0; j &lt; 4; j++) {
        ny = dy[i] + cy;
        nx = dx[j] + cx;
        // BFS 탐색 하듯이 queue가 빌 때 까지 반복하며 연결된 섬을 찾는다.
        // 방향이 탐색범위를 넘지 않는지 파악하고 해당 섬을 방문표시를 하며 queue에 삽입한다.
        if (ny &gt;= 0 &amp;&amp; ny &lt; h &amp;&amp; nx &gt;= 0 &amp;&amp; nx &lt; w) {
          if (!visited[ny][nx] &amp;&amp; land[ny][nx] === 1) {
            visited[ny][nx] = true;
            queue.push([ny, nx]);
          }
        }
      }
    }
  }
  answer++; // queue를 다 탐색했을 경우 answer에 연결된 섬의 개수를 추가한다.
};

while (true) {
  [w, h] = input.shift().split(&#39; &#39;).map(Number);
  if (w === 0 &amp;&amp; h === 0) {
    break;
  }
  visited = Array.from(Array(h), () =&gt; Array(w).fill(false));
  answer = 0;
  for (let i = 0; i &lt; h; i++) {
    land[i] = input.shift().split(&#39; &#39;).map(Number);
  }
  for (let i = 0; i &lt; h; i++) {
    for (let j = 0; j &lt; w; j++) {
      if (!visited[i][j] &amp;&amp; land[i][j]) {
        visited[i][j] = true;
        bfs(i, j);
      }
    }
  }
  console.log(answer);
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] ES6 화살표 함수]]></title>
            <link>https://velog.io/@u_u/JS-ES6-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@u_u/JS-ES6-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98</guid>
            <pubDate>Fri, 22 Sep 2023 11:02:14 GMT</pubDate>
            <description><![CDATA[<h1 id="arrow-function">Arrow Function</h1>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">출처 : MDN</a></p>
<ul>
<li><p>this, arguments나 super에 대한 자체 바인딩이 없고, methods로 사용해서는 안됩니다.</p>
</li>
<li><p>new.target키워드가 없습니다.</p>
</li>
<li><p>생성자(Constructor)로 사용할 수 없습니다.</p>
</li>
<li><p>일반적으로 스코프를 지정할 때 사용하는 call, apply, bind methods를 이용할 수 없습니다.</p>
</li>
<li><p>yield를 화살표 함수 내부에서 사용할 수 없습니다.</p>
</li>
</ul>
<blockquote>
<p>Example</p>
</blockquote>
<pre><code class="language-JS">const materials = [&#39;Hydrogen&#39;, &#39;Helium&#39;, &#39;Lithium&#39;, &#39;Beryllium&#39;];

console.log(materials.map((material) =&gt; material.length));
// Expected output: Array [8, 6, 7, 9]</code></pre>
<blockquote>
<p>기본 구문</p>
</blockquote>
<pre><code class="language-JS">    (param1, param2, …, paramN) =&gt; { statements }
    (param1, param2, …, paramN) =&gt; expression
    // 다음과 동일함:  =&gt; { return expression; }

    // 매개변수가 하나뿐인 경우 괄호는 선택사항:
    (singleParam) =&gt; { statements }
    singleParam =&gt; { statements }

    // 매개변수가 없는 함수는 괄호가 필요:
    () =&gt; { statements }</code></pre>
<blockquote>
<p>상세 구문</p>
</blockquote>
<pre><code class="language-JS">    var elements = [
      &#39;Hydrogen&#39;,
      &#39;Helium&#39;,
      &#39;Lithium&#39;,
      &#39;Beryllium&#39;
    ];

    // 이 문장은 배열을 반환함: [8, 6, 7, 9]
    elements.map(function(element) {
      return element.length;
    });

    // 위의 일반적인 함수 표현은 아래 화살표 함수로 쓸 수 있다.
    elements.map((element) =&gt; {
      return element.length;
    }); // [8, 6, 7, 9]

    // 파라미터가 하나만 있을 때는 주변 괄호를 생략할 수 있다.
    elements.map(element =&gt; {
      return element.length;
    }); // [8, 6, 7, 9]

    // 화살표 함수의 유일한 문장이 &#39;return&#39;일 때 &#39;return&#39;과
    // 중괄호({})를 생략할 수 있다.
    elements.map(element =&gt; element.length); // [8, 6, 7, 9]

    // 이 경우 length 속성만 필요하므로 destructuring 매개변수를 사용할 수 있다.
    // &#39;length&#39;는 우리가 얻고자 하는 속성에 해당하는 반면,
    // lengthFooBArX&#39;는 변경 가능한 변수의 이름일 뿐이므로
    // 원하는 유효한 변수명으로 변경할 수 있다.
    elements.map(({ length: lengthFooBArX }) =&gt; lengthFooBArX); // [8, 6, 7, 9]

    // destructuring 파라미터 할당도 아래와 같이 작성할 수 있습니다.
    // 이 예에서 정의한 객체내의 &#39;length&#39;에 값을 지정하지 않은 점에 주목하세요. 대신, &quot;length&quot; 변수의
    // 리터럴 이름은 우리가 해당 객체에서 꺼내오고 싶은 속성이름 자체로 사용됩니다.
    elements.map(({ length }) =&gt; length); // [8, 6, 7, 9]</code></pre>
<h2 id="바인딩-되지-않은-this">바인딩 되지 않은 <code>this</code></h2>
<p>화살표 함수가 나오기 전까지는, 모든 새로운 함수는, 어떻게 그 함수가 호출되는지에 따라 자신의 this 값을 정의했습니다:
<code>객체 지향 스타일에 어울리지 않음.</code></p>
<pre><code class="language-JS">function Person() {
  // Person() 생성자는 `this`를 자신의 인스턴스로 정의.
  this.age = 0;

  setInterval(function growUp() {
    // 비엄격 모드에서, growUp() 함수는 `this`를
    // 전역 객체로 정의하고, 이는 Person() 생성자에
    // 정의된 `this`와 다름.
    this.age++;
    consoel.log(this.age) // 1초당 NaN 출력
  }, 1000);
}

var p = new Person();
</code></pre>
<p>ECMAScript 3/5 에서는, 이 문제를 this 값을 폐쇄될 수 있는 (비전역) 변수에 할당하여 해결했습니다.</p>
<pre><code class="language-JS">function Person() {
  var that = this; // 비전역 변수에 this 할당
  that.age = 0;

  setInterval(function growUp() {
    // 콜백은  `that` 변수를 참조하고 이것은 값이 기대한 객체이다.
    that.age++;
  }, 1000);
}
</code></pre>
<p>화살표 함수는 자신의 this가 없습니다. 대신 화살표 함수를 둘러싸는 *렉시컬 범위(lexical scope)의 this가 사용됩니다; 화살표 함수는 일반 변수 조회 규칙(normal variable lookup rules)을 따릅니다. 때문에 현재 범위에서 존재하지 않는 this를 찾을 때, 화살표 함수는 바로 바깥 범위에서 this를 찾는것으로 검색을 끝내게 됩니다.</p>
<p>따라서 다음 코드에서 setInterval에 전달 된 함수 내부의 this는 setInterval을 포함한 function의 this와 동일한 값을 갖습니다.</p>
<ul>
<li>렉시컬 범위 : 렉시컬 범위는 함수의 실행 시 범위를 함수 정의 단계의 범위로 참조하는 특성이다.</li>
</ul>
<blockquote>
<p>요약 : 화살표 함수가 나오기 이전에는 새로운 지역변수를 할당하고 this 바인딩했다면 이후 화살표 함수 내 렉시컬 범위에 따라 this를 찾아 간단하게 지정.</p>
</blockquote>
<pre><code class="language-JS">function Person() {
  this.age = 0;

  setInterval(() =&gt; {
    this.age++; // |this|는 Person 객체를 참조
    console.log(this.age); // 1, 2, 3, 4 , ...N
  }, 1000);
}

var p = new Person();

setTimeout(() =&gt; {
  console.log(&#39;10초 뒤 age : &#39;, p.age); // 10초 뒤 age : 9
}, 10000); // 10000밀리초(10초) 뒤에 실행
</code></pre>
<h3 id="call-또는-apply를-통한-피호출"><code>call</code> 또는 <code>apply</code>를 통한 피호출</h3>
<p>화살표 함수에서는 this 가 바인딩되지 않았기 때문에, call() 또는 apply() 메서드는 인자만 전달 할 수 있습니다. this는 무시됩니다.</p>
<ul>
<li>화살표 함수 f는 자체적으로 this를 바인딩하지 않고, 외부 스코프에서 this 값을 상속받습니다. 즉, f 내부에서의 this는 addThruCall 메서드가 속한 adder 객체를 가리킵니다.</li>
<li>따라서 f.call(b, a)를 호출해도 f 내부의 this는 adder 객체를 가리키므로, this.base는 여전히 1로 설정되며, 결과적으로 1 + 1이 계산되어 2가 반환됩니다.</li>
</ul>
<blockquote>
<p>요약 : 화살표 함수는 자체적으로 this를 바인딩하지 않고 외부 스코프의 this 값을 상속받기 때문에 f 내부에서의 this는 add 메서드와 addThruCall 메서드가 속한 adder 객체를 가리키게 됩니다.</p>
</blockquote>
<pre><code class="language-JS">var adder = {
  base: 1,

  add: function (a) {
    var f = (v) =&gt; v + this.base;
    return f(a);
  },

  addThruCall: function (a) {
    var f = (v) =&gt; v + this.base; // 1 + 1
    // var f = (v) =&gt; v + this.base + &#39; v &#39; + v + &#39; this.base &#39; + this.base; 2 + 1
    var b = {
      base: 2,
    };

    return f.call(b, a);
  },
};

console.log(adder.add(1)); // 이는 2가 콘솔에 출력될 것임
console.log(adder.addThruCall(1)); // 이도 2가 콘솔에 출력될 것임
</code></pre>
<h2 id="바인딩-되지-않은-arguments">바인딩 되지 않은 <code>arguments</code></h2>
<p>화살표 함수는 arguments 객체를 바인드 하지 않습니다. 때문에, arguments는 그저 둘러싸는 범위(scope) 내 이름에 대한 참조입니다.</p>
<pre><code class="language-JS">var arguments = [1, 2, 3];
var arr = () =&gt; arguments[0];

console.log(arr()); // 1

function foo(n) {
  var f = () =&gt; arguments[0] + n; // foo&#39;s implicit arguments binding. arguments[0] is n
  console.log(&#39;argu : &#39;, arguments[0]);
  console.log(&#39;n : &#39;, n);
  return f();
}

console.log(foo(1)); // 2 = argu : 1 , n : 1
console.log(foo(2)); // 4 = argu : 2 , n : 2</code></pre>
<h2 id="기본-사용법">기본 사용법</h2>
<pre><code class="language-JS">//  empty 화살표 함수는 undefined를 반환
let empty = () =&gt; {};

(() =&gt; &quot;foobar&quot;)();
// &quot;foobar&quot; 반환
// (this is an Immediately Invoked Function Expression

var simple = (a) =&gt; (a &gt; 15 ? 15 : a);
simple(16); // 15
simple(10); // 10

let max = (a, b) =&gt; (a &gt; b ? a : b);

// Easy array filtering, mapping, ...

var arr = [5, 6, 13, 0, 1, 18, 23];

var sum = arr.reduce((a, b) =&gt; a + b);
// 66

var even = arr.filter((v) =&gt; v % 2 == 0);
// [6, 0, 18]

var double = arr.map((v) =&gt; v * 2);
// [10, 12, 26, 0, 2, 36, 46]

// 더 간결한 promise 체인
promise
  .then((a) =&gt; {
    // ...
  })
  .then((b) =&gt; {
    // ...
  });

// 매개변수가 없는 경우에도 더 읽기 쉬움
setTimeout(() =&gt; {
  console.log(&quot;I happen sooner&quot;);
  setTimeout(() =&gt; {
    // deeper code
    console.log(&quot;I happen later&quot;);
  }, 1);
}, 1);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 백준 2121 JS]]></title>
            <link>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-2121-JS</link>
            <guid>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-2121-JS</guid>
            <pubDate>Thu, 21 Sep 2023 15:22:26 GMT</pubDate>
            <description><![CDATA[<h2 id="백준--2121--js--map">백준 / 2121 / JS / Map</h2>
<p><a href="https://www.acmicpc.net/problem/2121">https://www.acmicpc.net/problem/2121</a></p>
<blockquote>
<p>문제</p>
</blockquote>
<p>네 사람이서 2차원 평면상의 N개의 점을 이용해서 할 수 있는 놀이가 있다. 바로 각 사람이 1개씩의 점을 적절히 선택해서 변이 x축 혹은 y축에 평행한 직사각형을 만드는 일이다. 물론 그냥 만들면 재미가 없기 때문에 가로의 길이가 A 세로의 길이가 B인 직사각형을 몇 가지나 만들 수 있는지 알아보기로 했다.</p>
<p>예를 들어 점이 A(0, 0), B(2, 0), C(0, 3), D(2, 3), E(4, 0), F(4, 3)의 6개가 있고, 만들고 싶은 직사각형이 가로가 2, 세로가 3인 직사각형이라면 (A, B, C, D), (B, D, E, F)의 두 가지 경우가 가능하다. 모든 경우의 수를 구해보자.</p>
<blockquote>
<p>입력</p>
</blockquote>
<p>첫 줄에 점들의 개수 N(5 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에 만들고 싶은 직사각형의 가로 길이 A(1 ≤ A ≤ 1,000)와 세로 길이 B(1 ≤ B ≤ 1,000)가 주어진다. 다음 N줄에 걸쳐서 점들의 좌표가 정수로 주어진다. 이 값의 범위는 -1,000,000,000이상 1,000,000,000이하이다. N개 점들의 좌표는 각각 다르다.</p>
<blockquote>
<p>출력</p>
</blockquote>
<p>첫 줄에 가능한 모든 경우의 수를 출력한다. 경우의 수는 231-1보다 작거나 같다.</p>
<blockquote>
<p>풀이</p>
</blockquote>
<p>입력 값들이 다 양의 방향으로 증가하기 때문에 2차원 좌표로 봤을 때 1, 3, 4사분면의 좌표값은 확인할 필요가 없다. 따라서 가로, 새로 값을 입력 받은 좌표에 대입하여 해당 좌표가 있을 경우를 확인하여 모든 조건에 부합할 경우 <code>answer</code>의 값을 증가시켰다.</p>
<p>백틱을 사용해서 검색하기보다 <code>[x, y]</code>와 같은 배열로 Set에 저장하고 탐색하려고 하니 조건이 맞지 않았다. Map, Set에 대해서 더 공부해봐야겠다.</p>
<pre><code class="language-JS">let input = require(&#39;fs&#39;)
  .readFileSync(__dirname + &#39;/input.txt&#39;, { encoding: &#39;utf-8&#39; })
  .split(&#39;\n&#39;);

const n = parseInt(input.shift());
const [row, col] = input.shift().split(&#39; &#39;).map(Number);
let points = new Map();
let answer = 0;
input.forEach((e) =&gt; {
  const [x, y] = e.split(&#39; &#39;).map(Number);
  points.set(`${x}, ${y}`, 1);
});

for (const item of input) {
  const [x, y] = item.split(&#39; &#39;).map(Number);
  if (!points.has(`${x + row}, ${y}`)) continue;
  if (!points.has(`${x}, ${y + col}`)) continue;
  if (!points.has(`${x + row}, ${y + col}`)) continue;
  answer++;
}

console.log(answer);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 백준 6417 JS]]></title>
            <link>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-6417-JS</link>
            <guid>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-6417-JS</guid>
            <pubDate>Wed, 20 Sep 2023 10:24:19 GMT</pubDate>
            <description><![CDATA[<h2 id="백준--6417--js--brute-force">백준 / 6417 / JS / Brute-force</h2>
<p><a href="https://www.acmicpc.net/problem/6417">https://www.acmicpc.net/problem/6417</a></p>
<blockquote>
<p>문제</p>
</blockquote>
<p>1926년 10월 9일의 신문엔 미국의 유명 극작가 벤 윌리암스의 짤막한 문제 하나가 실렸다. 전문은 다음과 같다.
다섯 명의 남자가 무인도에 갇혔다. 그들은 표류 첫 날, 하루 종일 힘을 합쳐 코코넛을 모았다.
그날 밤 첫 사람이 일어나 코코넛을 세어보니 하나를 빼면 정확히 5등분을 할 수 있었다.
그래서 지나가던 원숭이에게 코코넛 하나를 주고 나머지를 5등분하여 자기 몫의 한 무더기를 숨겨 두고 잠들었다.
그리고 바로 그 직후, 두 번째 사람이 일어나 코코넛을 세어보니 하나를 빼면 정확히 5등분을 할 수 있었다.
그래서 지나가던 원숭이에게 코코넛 하나를 주고 나머지를 5등분하여 자기 몫의 한 무더기를 숨겨 두고 잠들었다.
그 바로 다음 세 번째 사람도, 네 번째 사람도, 다섯 번째 사람도 같은 일을 했다.
이제 잠에서 깬 다섯 명이 남은 코코넛을 세어 보니 정확히 5등분을 할 수 있었다.
그래서 그들은 남은 코코넛을 5등분하여 한 묶음씩 가졌다.
이때, 그들이 처음 모은 코코넛은 모두 몇 개였을까?
문제의 답은 사실 무수히 많다. 하지만 그 중 가장 작은 수는 3121개이다.
하지만 이 문제는 우리가 풀 문제가 아니다.
우리는 코코넛 이야기를 반대로 생각해보기로 하자.
처음 모은 코코넛이 N개였고, 위의 규칙대로 K명의 사람들이 코코넛을 다들 나누어 가지는 데 성공했다면, 이때 K는 최대 몇이 될 수 있을까?</p>
<blockquote>
<p>입력</p>
</blockquote>
<p>입력은 여러 테스트 케이스로 이루어져 있다.
각 테스트 케이스의 첫 줄엔 문제의 N이 주어지며, N이 -1일 경우 입력의 종료를 의미한다.</p>
<blockquote>
<p>출력</p>
</blockquote>
<p>각 N에 따라 한 줄에, K가 존재할 경우 &quot;N coconuts, max(K) people and 1 monkey&quot; 를,
어떤 K도 코코넛을 규칙대로 나눌 수 없을 경우 &quot;N coconuts, no solution&quot;을 출력한다.</p>
<blockquote>
<p>풀이</p>
</blockquote>
<p>처음 문제를 읽고 K를 찾기 위해 단순 반복을 하면 시간 초과가 뜨지 않을까 싶었다
1&lt;= N &lt;= 1,000,000, O(n)
2&lt;= K &lt;= 1,000,000 (대충 생각하기에 N보다 작을 때 까지) O(n)
총 O(N^2)이 나오지 않을까 싶었지만 반복문 종료 조건이 많은 필터링을 거쳐지기 때문에 시간초과가 뜨진 않은 것 같다.</p>
<pre><code class="language-JS">let input = require(&#39;fs&#39;)
  .readFileSync(__dirname + &#39;/input.txt&#39;, { encoding: &#39;utf-8&#39; })
  .split(&#39;\n&#39;);
let n = input.shift();
let k = 2;
let answer = []; // k값들을 저장할 배열
while (true) {
  if (n === &#39;-1&#39;) {
    // 종료 조건
    break;
  }
  let coconut = parseInt(n);
  while (k &lt; coconut) {
    // k가 최대값이 되기 위해 coconut보다 작을 때 까지 탐색
    for (let i = 0; i &lt; k; i++) {
      coconut -= 1; // 원숭이에게 한 개
      coconut -= coconut / k; // 내 몫을 제외하고 나머지
      if ((coconut - 1) % k !== 0) {
        // 나누어지는지 확인
        if (i === k - 1) {
          answer.push(k);
        }
        break;
      }
    }
    k++; // 재탐색을 위한 초기화
    coconut = parseInt(n);
  }
  if (answer.length !== 0) {
    // k값이 있을때 없을 때 구분
    console.log(
      n,
      &#39;coconuts,&#39;,
      answer[answer.length - 1],
      &#39;people and 1 monkey&#39;
    );
  } else {
    console.log(n, &#39;coconuts, no solution&#39;);
  }
  answer = []; // 초기화
  k = 2;
  n = input.shift();
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 백준 10845 JS]]></title>
            <link>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-10845-JS</link>
            <guid>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-10845-JS</guid>
            <pubDate>Wed, 20 Sep 2023 08:06:06 GMT</pubDate>
            <description><![CDATA[<h2 id="백준--10845--js--queue">백준 / 10845 / JS / Queue</h2>
<p><a href="https://www.acmicpc.net/problem/10845">https://www.acmicpc.net/problem/10845</a></p>
<blockquote>
<p>문제</p>
</blockquote>
<p>정수를 저장하는 큐를 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.</p>
<p>명령은 총 여섯 가지이다.</p>
<p>push X: 정수 X를 큐에 넣는 연산이다.
pop: 큐에서 가장 앞에 있는 정수를 빼고, 그 수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
size: 큐에 들어있는 정수의 개수를 출력한다.
empty: 큐가 비어있으면 1, 아니면 0을 출력한다.
front: 큐의 가장 앞에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.
back: 큐의 가장 뒤에 있는 정수를 출력한다. 만약 큐에 들어있는 정수가 없는 경우에는 -1을 출력한다.</p>
<blockquote>
<p>입력</p>
</blockquote>
<p>첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.</p>
<blockquote>
<p>출력</p>
</blockquote>
<p>출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.</p>
<blockquote>
<p>풀이</p>
</blockquote>
<p>Queue를 단순히 <code>shift()</code>와 <code>push()</code> <code>pop()</code>을 사용하는게 아닌 직접 queue를 구현해보았다.
FIFO의 형태의 Queue를 위해 단순 연결 리스트로 구현했다.</p>
<pre><code class="language-JS">/**
 * 연결 리스트로 구현
 * value와 다음 노드를 가리킬 next
 */
class Node {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

/**
 * queue의 head와 tail로 리스트의 구조를 정의
 * size를 통해 queue의 길이를 저장
 */
class Queue {
  constructor() {
    this.head = null;
    this.tail = null;
    this.size = 0;
  }
  /**
   * value를 받아 새로운 노드 생성
   * queue가 비었을 경우 head와 tail에 해당 노드 저장
   * 아닐 경우, queue의 tail을 갱신하고 size 증가
   * @param {value} value
   */
  enqueue(value) {
    const newNode = new Node(value);

    if (!this.head) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      this.tail.next = newNode;
      this.tail = newNode;
    }

    this.size++;
  }
  /**
   * queue가 비었을 경우 -1반환
   * 아닐 경우, head의 노드를 삭제하기 위해 저장 및 head를 head.next값으로 변경
   * 만약 리스트가 하나의 노드만 존재했다면 tail에 null값을 갱신, size 감소
   * @returns 삭제할 노드
   */
  dequeue() {
    if (!this.head) {
      return -1;
    }

    const removeNode = this.head;
    this.head = this.head.next;
    if (!this.head) {
      this.tail = null;
    }

    this.size--;

    return removeNode.value;
  }

  len() {
    return this.size;
  }

  isEmpty() {
    if (this.size === 0) {
      return 1;
    }
    return 0;
  }

  ishead() {
    if (this.size === 0) {
      return -1;
    }
    return this.head.value;
  }

  isBack() {
    if (this.size === 0) {
      return -1;
    }
    return this.tail.value;
  }
}

let input = require(&#39;fs&#39;)
  .readFileSync(__dirname + &#39;/input.txt&#39;, { encoding: &#39;utf-8&#39; })
  .split(&#39;\n&#39;);
let n = parseInt(input.shift());
const q = new Queue();
const answer = [];
for (let i = 0; i &lt; n; i++) {
  const [order, value] = input.shift().split(&#39; &#39;);

  if (order === &#39;push&#39;) {
    q.enqueue(value);
  } else if (order === &#39;pop&#39;) {
    answer.push(q.dequeue());
  } else if (order === &#39;size&#39;) {
    answer.push(q.len());
  } else if (order === &#39;empty&#39;) {
    answer.push(q.isEmpty());
  } else if (order === &#39;head&#39;) {
    answer.push(q.ishead());
  } else {
    answer.push(q.isBack());
  }
}
console.log(answer.join(&#39;\n&#39;));
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[BOJ] 백준 1062 JS]]></title>
            <link>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-1062-JS</link>
            <guid>https://velog.io/@u_u/BOJ-%EB%B0%B1%EC%A4%80-1062-JS</guid>
            <pubDate>Tue, 19 Sep 2023 07:16:08 GMT</pubDate>
            <description><![CDATA[<h2 id="백준--1062--js--dfs">백준 / 1062 / JS / DFS</h2>
<p><a href="https://www.acmicpc.net/problem/1062">https://www.acmicpc.net/problem/1062</a></p>
<blockquote>
<p>문제</p>
</blockquote>
<p>남극에 사는 김지민 선생님은 학생들이 되도록이면 많은 단어를 읽을 수 있도록 하려고 한다. 그러나 지구온난화로 인해 얼음이 녹아서 곧 학교가 무너지기 때문에, 김지민은 K개의 글자를 가르칠 시간 밖에 없다. 김지민이 가르치고 난 후에는, 학생들은 그 K개의 글자로만 이루어진 단어만을 읽을 수 있다. 김지민은 어떤 K개의 글자를 가르쳐야 학생들이 읽을 수 있는 단어의 개수가 최대가 되는지 고민에 빠졌다.</p>
<p>남극언어의 모든 단어는 &quot;anta&quot;로 시작되고, &quot;tica&quot;로 끝난다. 남극언어에 단어는 N개 밖에 없다고 가정한다. 학생들이 읽을 수 있는 단어의 최댓값을 구하는 프로그램을 작성하시오.</p>
<blockquote>
<p>입력</p>
</blockquote>
<p>첫째 줄에 단어의 개수 N과 K가 주어진다. N은 50보다 작거나 같은 자연수이고, K는 26보다 작거나 같은 자연수 또는 0이다. 둘째 줄부터 N개의 줄에 남극 언어의 단어가 주어진다. 단어는 영어 소문자로만 이루어져 있고, 길이가 8보다 크거나 같고, 15보다 작거나 같다. 모든 단어는 중복되지 않는다.</p>
<blockquote>
<p>출력</p>
</blockquote>
<p>첫째 줄에 김지민이 K개의 글자를 가르칠 때, 학생들이 읽을 수 있는 단어 개수의 최댓값을 출력한다.</p>
<blockquote>
<p>풀이</p>
</blockquote>
<pre><code class="language-JS">let input = require(&#39;fs&#39;)
  .readFileSync(__dirname + &#39;/input.txt&#39;, {
    encoding: &#39;utf-8&#39;,
  })
  .split(&#39;\n&#39;);

let [N, K] = input[0].split(&#39; &#39;).map(Number);
let wordsList = input.slice(1, N + 1); // 받은 문자열 저장
let alphabetArr = new Array(26).fill(0); // 전체 알파벳 배열 저장 0, 1로 배웠는지 안배웠는지 여부 판단
let readCount = K - 5; // a, c, i, n, t는 기본적으로 배워야하기 때문에 K - 5
let answer = 0; // 정답

if (readCount &lt; 0) {
  // 기본 단어를 배울 수 없는 경우기 때문에 0 반환
  console.log(0);
  return;
}

// 각각 a,c,i,n,t
alphabetArr[0] = 1;
alphabetArr[2] = 1;
alphabetArr[8] = 1;
alphabetArr[13] = 1;
alphabetArr[19] = 1;

let dfs = (index, readCount) =&gt; {
  if (readCount &lt; 0) {
    // 종료조건
    return;
  }

  if (readCount === 0) {
    // 배울 수 있는 알파벳을 다 배웠을 때
    let count = 0;
    for (let i = 0; i &lt; N; i++) {
      // 입력받은 문자열에 접근하여 해당 알파벳들로 완성된 단어가 있는지 확인
      let flag = true; // 완성된 단어인지 확인하기 위한 flag
      for (let j = 0; j &lt; wordsList[i].length; j++) {
        if (alphabetArr[wordsList[i][j].charCodeAt() - 97] === 0) {
          // 문자열의 알파벳들을 확인하여 배웠는지 체크
          flag = false; // 안배웠던 단어라면 완성되지 않았기 때문에 false로 주고
          break; // for문 탈출
        }
      }
      if (flag) count++;
    }
    answer = Math.max(answer, count); // 매 순간 가장 큰 값을 갖기 위해 확인
  }

  for (let i = index; i &lt; 26; i++) {
    // 알파벳 배열의 전체를 방문
    if (alphabetArr[i] === 0) {
      // 만약 아직 안배웠다면
      alphabetArr[i] = 1; // 배우고
      dfs(i, readCount - 1); // 재탐색, 배웠기 때문에 count 감소
      alphabetArr[i] = 0; // 탐색 완료했기 때문에 0으로 초기화
    }
  }
};

dfs(0, readCount);

console.log(answer);
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[크래프톤 정글] 나만무 회고]]></title>
            <link>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-%EB%82%98%EB%A7%8C%EB%AC%B4-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-%EB%82%98%EB%A7%8C%EB%AC%B4-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Sun, 20 Aug 2023 05:00:17 GMT</pubDate>
            <description><![CDATA[<h1 id="회고">회고</h1>
<p>기대하고 걱정하던 나만의 무기 만들기 프로젝트가 시작되었다.
설렘 반 걱정 반 정글의 끝이 다가옴을 실감하며 우당탕탕 좌충우돌 나만의 무기 만들기 프로젝트 회고 시작!</p>
<blockquote>
<p>_ 회고라고 읽고 기억 되살리기라 말한다... ㅜㅜ_ 😭</p>
</blockquote>
<h3 id="0주차---팀-정하기">0주차 - 팀 정하기</h3>
<p>그 동안의 정글 생활을 하며 매주 팀이 바뀌며 적어도 한 명씩 같이 팀을 한 경험이 있을 것이다. (하지만 나는 24명중 6명정도..? 같은 팀을 안해봤다 운빨 ㅠㅠㅠ)</p>
<p>나는 같은 팀으로 나만무를 진행하고 싶은 사람들과 팀을 꾸리기 위해 지원했었다.
근데 정말 내가 팀으로 하고 싶은 사람들과 다 같이 *<em>같은 팀을 하게 되어 너무 기쁘고 즐거웠다!! *</em></p>
<p>밤새 선호도를 어떻게 작성해서 제출해야할지 수없이 고민하고 다른 팀장들이 선호도를 어떻게 제출할 지 예상하고 거기에 대응해서 내가 작성해야할지 고민했던 그 수고가 절대!! 헛되지 않았다는게 너무 기분이 좋았다. (적중률 또한 좋았다.)</p>
<h3 id="1주차---아이디어-정하기">1주차 - 아이디어 정하기</h3>
<p>후,, 기쁜 마음으로 팀원들과 회식을 하고 크래프톤 측에서 주선해주는 멘토님과 인사를 나누고 매주 멘토링 일정을 정하고 앞으로 나만무 기간을 어떻게 보낼지 얘기했다.</p>
<h3 id="2주차---아이디어-다시-정하기">2주차 - 아이디어 다시 정하기</h3>
<p>아찔하다. 정신이 아득해진다. 아이디어를 정했지만 처음 배워보는 Three.js, React 등 전공자이지만 금쪽이이자 말하는 감자인 나는 아는게 많이 없었고 그만큼 몸으로 떼워야한다.</p>
<p>부랴부랴 <a href="https://www.inflearn.com/course/3d-%EC%9D%B8%ED%84%B0%EB%9E%99%ED%8B%B0%EB%B8%8C-%EC%9B%B9#reviews">인강</a>을 4일? 5일만에 수강하고 바로 개발을 진행하였다.</p>
<h3 id="3주차---의장님-방문">3주차 - 의장님 방문</h3>
<p><img src="blob:https://velog.io/121b626a-d468-4686-9ab1-7e7000980ae3" alt="업로드중.."></p>
<blockquote>
<p>해줄 말이 없네요.</p>
</blockquote>
<p>그렇다 의장님이 진행된 프로젝트를 보고 피드백을 주신 내용이다. 심장이 쿵 내려앉았다. 그런데 다시보니 그럴만 했다. ppt의 내용은 무지개 빛 그림을 상상했지만 실상 보여진 프로젝트는.... 너무 처참했다 물론 기능을 우선적으로 본다 해도 나와있는건 소켓으로 연결한 채팅과 player. 그리고 오브젝트들에 그림자도 적용이 안된 모습. 캐릭터들이 애니메이션이 적용 안된 모습 참.. 여전히 다시 봐도 아찔 그 잡채.</p>
<h3 id="4주차---최종발표-전-주">4주차 - 최종발표 전 주</h3>
<blockquote>
<p>사람은 하나에 깊게 몰입하고 거기에 정신이 붙들려있으면 주변이 보이질 않는다.</p>
</blockquote>
<p>프론트인 나와 내 팀원은 똑같은 화면을 계속 보고 개발을 진행하다 보니 객관적인 평을 내리기 어려웠던 것 같다. 백엔드 팀원들이 심사숙고해서 우리 상의좀 해보자 하여 프로젝트의 방향성에 대해서 논의하였고, 진행 방향은 그대로이지만 화면 구성에 대해서 수정을 하게 되었다.</p>
<h3 id="5주차---최종발표-주">5주차 - 최종발표 주</h3>
<p>남은 기간은 약 1주일 처리해야할 기능과 뷰는 산더미, 캐릭터를 만들고 캐릭터 애니메이션을 만들고 적용시키고, 그 외 더욱 많은 디테일들 할 수 있을까? 라는 고민은 사치였다 그런 생각할 시간에 개발을 진행하고 어떻게 구현할 수 있을까 빠르게 고민하고 결정하고 진행해야했다.</p>
<h3 id="최종-발표">최종 발표</h3>
<p><a href="https://www.youtube.com/watch?v=qGpa3J9rgqI&amp;t=322s">발표 시연 영상</a></p>
<p>난생 처음 에러가 떴다. 그동안 시연하고 발표할 때 한번도 뜨지 않았던 에러가 최종 발표에서. 커흡헠컥 숨이 턱 막힌다.</p>
<blockquote>
<p>싸늘하다. 가슴에 비수가 날아와 꽂힌다. </p>
</blockquote>
<p>이 문제점과 같은 경우는 처음 발견한 에러여서 문제가 뭘까하고 영상을 다시 봐보면서 생각해본 결과 세션 스토리지로 로그인 정보를 갖고 있는데, 세션에 있는 값이 유효하지 않다면서 뜬 에러였다. 기존에 런시켰던 웹페이지를 끄지않고 새로 런을 해서 로그인 값이 미스매치되어 뜬 에러이지 않을까 조심스럽게 추측해본다..</p>
<p>이렇게 한바탕 소동이 지나가고 다시 발표를 이어나갔다. 에러가 뜬게 아쉽긴 하지만 그래도 거의 단 1주일만에 엄청나게 큰 변화를 일으키며 개선해나갔고 완성도 측면에서도 많이 흡족한 프로젝트 진행이었다고 생각한다. 당연히 여러가지 더 추가하고 싶은 것들은 많았지만 아쉬움을 뒤로한 채 마무리를 지었다.</p>
<h3 id="발표-이후">발표 이후</h3>
<p>짜릿했던 최종 발표회가 끝나고 우리는 Poly world의 애착을 갖고 더욱 디벨롭하기로 하였다. 기존에 우리가 AWS에게서 지원받기로 했던 2,000달러가 있는데, 어떤 이유에서인지 계정이 지속적으로 정지를 받았고 결국 2,000달러 지원을 못받은 채로 개인 서버로 이용하였다. </p>
<blockquote>
<h4 id="aws-중요이슈">AWS 중요이슈</h4>
</blockquote>
<p>꼭 AWS를 이용할 때에는 개인적인 프로젝트는 거의 프리티어로 해결 가능하니 지원받을거란 생각에 가장 비싼 요금제로 진행했다가 요금 폭탄을 받은 나는 통장 하나를 버려야 하는 지경에 이르렀다. 만약 이 글을 보시는 정글과정을 겪는 분들께서는 이런 실수를 하지 않으실 바랍니다.</p>
<blockquote>
<p>2,000달러... </p>
</blockquote>
<p>다시 돌아와서 기숙사를 나가는 날까지 일단 신청해보고 안된다면 내 개인서버를 이용하기로 하고 이제 정글 생활을 마무리하는 과정만 남았다.</p>
<h3 id="수료식">수료식</h3>
<p>수료식은 간단했다. 기존에 입소식을 진행했던 곳에서 조촐하게 진행되었고 그동안 고생많았다 하시면서 끝인사를 전해주셨다.</p>
<h3 id="소감">소감</h3>
<p>아마 내 인생에서 잊지못할 개발 경험이 아닐까 싶다. 대부분의 누구나 그렇듯 평범하게 성적에 맞춰 게임을 좋아해서 컴퓨터공학부에 진학했던 내가 개발자로서 방향성을 갖고 진행한 첫 발걸음이 아닌가 싶다. 앞으로 내가 개발자로서 어떤 과정을 겪게 될지 모르겠지만 이 과정을 항상 생각하며 배우고 느꼈던 점들을 바탕으로 나의 성장을 지켜봐야겠다. 김현수 코치님이 항상 자랑스럽게 외치시던 구호를 말하며 글을 마무리 하겠다. 모두</p>
<h2 id="정글-💪">정글! 💪</h2>
<p>정글 2기 레드반 친구들과 마지막 나만무 프로젝트를 진행한 Poly World 팀원들 너무 고맙고 항상 잘되길 바랄께 모두 취뽀하자!</p>
<p>매섭게 피드백해주시고 때로는 인생선배로써 경험담을 풀어주신 <strong>김정한</strong> 원장님과,
아빠같이 항상 곁에서 응원해주시고 그 누구보다 정글생들의 성공을 바라시며 도와주신 <strong>김현수</strong> 코치님,
수줍음이 많으시고 어색해하셨지만 담담하게 설명해주시고 개선방향을 제시해주시던 <strong>백승현</strong> 코치님, 
그리고 특히 정글생들에게 없어선 안되셨을 매번 친절하게 도움을 주신 <strong>박일룡</strong>님, <strong>조현나</strong>님께 매우 깊은 감사 인사를 드리고 싶었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] React]]></title>
            <link>https://velog.io/@u_u/React</link>
            <guid>https://velog.io/@u_u/React</guid>
            <pubDate>Fri, 07 Jul 2023 11:12:51 GMT</pubDate>
            <description><![CDATA[<h1 id="react-무엇일까">React..? 무엇일까</h1>
<blockquote>
<p>자바스크립트 라이브러리로 사용자 인터페이스를 만드는데 사용된다.</p>
</blockquote>
<p>ex) Netflix : 많은 상호작용을 하며, 화면 전환도 빠르고, 무엇인가를 로딩하느라 기다릴 필요도 없다.</p>
<h3 id="장점">장점</h3>
<ul>
<li>클라이언트 사이드의 자바스크립트 라이브러리</li>
<li>최신의 반응형 사용자 인터페이스 구축 가능</li>
</ul>
<h4 id="es6-자바스크립트-핵심-기능">ES6 자바스크립트 핵심 기능</h4>
<p><a href="https://velog.io/@u_u/JS-ES6-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98">JS 화살표 함수</a></p>
<h3 id="출처">출처</h3>
<p><a href="https://www.udemy.com/course/best-react/">Udemy 강의</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSAPP] Chapter08.]]></title>
            <link>https://velog.io/@u_u/CSAPP-Chapter08</link>
            <guid>https://velog.io/@u_u/CSAPP-Chapter08</guid>
            <pubDate>Mon, 19 Jun 2023 06:26:40 GMT</pubDate>
            <description><![CDATA[<h1 id="csapp-8장">CSAPP 8장</h1>
<blockquote>
<p><strong>제어흐름 (Control Flow)</strong></p>
</blockquote>
<p>일반적인 컴퓨터는 프로그램이 시작하면 명령어들이 순차적으로 진행이 되고 끝나게 한다.
이러한 과정 속에서 CPU는 명령어를 한 번에 한 개씩 수행할 수 있는데 CPU의 Control Flow라고 한다.</p>
<ul>
<li>Control Flow가 바뀌는 상황
일반적으로 &quot;점진적인&quot;순서로 인스트럭션이 메모리에 나란히 있지 않은 경우 발생하는데, jump, call과 같은 명령어를 사용할 때 발생한다.</li>
</ul>
<p>프로그램은 디스크로부터 데이터를 요청하며, 그 후에 데이터가 준비되었다는 통지를 받을 때까지 <strong>잠든 상태에 들어간다</strong> <code>Sleep list</code> 자식 프로세스를 생성하는 <strong>부모 프로세스는 자신의 자식이 종료할 때</strong> 통지를 받아야 한다.
-&gt; 자식 프로세스가 종료될 때까지 부모 프로세스는 대기상태</p>
<ul>
<li>예외적인 제어흐름(Exceptional Control Flow)</li>
</ul>
<p><code>ECF</code>은 컴퓨터 시스템의 모든 수준에서 발생한다. 예를 들어,
<strong>하드웨어 수준</strong>에서 검출되는 이벤트들은 예외 핸들러로 제어흐름을 발생시킨다.
<strong>운영체제 커널수준</strong>의 문맥전환(Context Switching)을 통해서 사용자 프로세스에서 다른 프로세스로 제어가 이동한다.
<strong>응용수준</strong>에서 프로세스는 시그널을 수신하는 곳에 있는 시그널 핸들러로 제어를 급격히 이동하는 다른 프로세스로 시그널을 보낼 수 있다.
ex) Running 중인 프로그램에 <strong>ctrl + c</strong> 종료 발생</p>
<p><strong>Application</strong>은 <code>system call</code>이라고 알려진 ECF의 한 가지 형태를 사용해서 운영체제로부터 서비스를 요청한다.
ex) 데이터를 디스크에 쓰거나, 네트워크에서 데이터를 읽거나, 새로운 프로세스를 만들거나, 현재 프로세스를 종료시키는 일</p>
<p><code>ECF</code>는 컴퓨터 시스템에서 동시성을 구현하는 기본 메커니즘이다.
ex) 응용프로그램의 실행을 가로채는 예외처리 핸들러, 실행을 가로채는 시그널 핸들러</p>
<blockquote>
<p>Application이 운영체제와 상호작용 하는 것들은 모두 <code>ECF</code>를 중심으로 돌아간다.</p>
</blockquote>
<p><a href="https://velog.io/@u_u/CS-Interrupt-System-call">interrupt, System call 참고</a></p>
<h2 id="81-예외상황">8.1 예외상황</h2>
<p>예외상황은 어떤 프로세서 상태의 변화에 대한 대응으로, 제어흐름의 갑작스런 변화이다.</p>
<p><img src="https://velog.velcdn.com/images/u_u/post/d9adb4b4-bf19-4c19-b213-d54b5a999b8a/image.png" alt=""></p>
<p>프로세서는 현재 어떤 명령어를 실행하고 있을 때 상태 변화가 일어나는데, 상태 변화는 <strong>이벤트</strong>라고 알려져있다.
이벤트는 가상메모리 페이지 오류, 산술 오버플로우, divide by zero와 같은 경우는 현재 인스트럭션과 관련이 있지만, 시스템 타이머가 정지하거나, I/O요청이 안료되는 경우는 그렇지 않다.</p>
<p>그림과 같이 예외가 발생할 경우 세가지 중의 한 가지가 발생한다.</p>
<ol>
<li><strong>핸들러는 제어를 현재 인스트럭션으로 돌려준다.</strong> 이 인스트럭션은 이벤트가 발생했을 때 실행되고 있던 인스트럭션을 말한다.</li>
<li><strong>핸들러는 제어를 다음 인스트럭션으로 돌려주는데</strong>, 이인스트럭션은 예외상황이 발생하지 않았더라면 다음에 실행되었을 인스트럭션이다.</li>
<li><strong>핸들러는 중단된 프로그램을 종료한다.</strong></li>
</ol>
<h3 id="811-예외처리">8.1.1 예외처리</h3>
<h3 id="812-예외의-종류">8.1.2 예외의 종류</h3>
<blockquote>
<p>4가지 : 인터럽트, 트랩(트랩과 시스템 콜), 오류, 중단</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/u_u/post/90a0bc24-9915-4c5b-a6c3-c6dff281617d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/u_u/post/1bcf090f-bb22-4a06-8fa8-fcd5647dc153/image.png" alt="">
인터럽트, 트랩과 시스템 콜</p>
<ul>
<li><p>인터럽트 (interrupt)
프로세서 외부에 있는 입출력 디바이스로부터의 시그널의 결과로 비동기적으로 발생한다.</p>
</li>
<li><p>트랩 (trap)과 시스템 콜 (system call)
트랩은 의도적인 예외상황으로 어떤 인스트럭션을 실행한 결과로 발생한다.
트랩의 <strong>가장 중요한 사용</strong>은 <code>시스템 콜</code>이라고 알려진 <strong>사용자 프로그램과 커널 사이</strong>의 프로시저와 유사한 인터페이스를 제공하는 것이다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/u_u/post/3f20d837-a9cf-46d2-a70d-af374a36c397/image.png" alt="">
오류, 중단</p>
<ul>
<li>오류 (fault와 error는 다르다.)
오류는 핸들러가 <strong>정정할 수 있는 가능성</strong>이 있는 에러 조건으로부터 발생한다. 오류가 정정할 수 있다면 원인 인스트럭션으로 돌아가서 재실행 시킨다.
만약 그렇지 않다면 abort루틴으로 리턴해서 응용프로그램을 종료시킨다.</li>
<li>중단
중단은 DRAM이나 SRAM이 고장날 때 발생하는 패리티 에러와 하드웨어 같은 복구할 수 없는 치명적인 에러에서 발생한다. 중단 핸들러는 바로 종료하는 중단루틴으로 넘겨준다.</li>
</ul>
<blockquote>
<p>인스트럭션은 컴퓨터에서 실행되는 명령어들을 나타내며 프로세서에게 수행해야할 작업을 지시한다. 프로세서(CPU)는 인스트럭션을 해석하고 실행하는 역할을 수행하는데, 트랩은 프로세서의 실행 결과(인스트럭션-&gt;프로세서)로 인해 발생하며, 커널 내부 및 인터럽트 처리 루틴으로 제어를 전달한다. 시스템 콜은 커널모드에서 돌아가며 프로세스가 운영체제의 서비스를 요청하기 위해 사용하는 인터페이스이다.</p>
</blockquote>
<h2 id="82-프로세스">8.2 프로세스</h2>
<blockquote>
<p>프로세서의 고전적인 정의는 실행 프로그램의 인스턴스이다.</p>
</blockquote>
<p>시스템 내의 각 프로그램은 어떤 프로세스의 문맥(context)에서 돌아간다.
문맥은 프로그램이 정확하게 돌아가기 위해서 필요한 상태로 구성된다.
ex) 메모리에 저장된 프로그램 코드와 데이터, 스택, 범용 레지스터의 내용 등등</p>
<p>프로세스가 application에 제공하는 주요 추상화 2가지</p>
<ul>
<li>우리의 프로개름이 프로세서를 혼자서 사용한다는 착각을 제공하는 <strong>독립적 논리 제어 흐름</strong></li>
<li>우리의 프로개름이 혼자서 메모리 시스템을 가진다는 착각을 제공하는 <strong>사적 주소공간</strong></li>
</ul>
<h3 id="821-논리적인-제어흐름">8.2.1 논리적인 제어흐름</h3>
<p>프로세스는 시스템에 서로 다른 여러 프로그램들이 동시적으로 동작하고 있지만, 프로세서를 혼자서 사용한다는 착각을 느끼게 한다.
인스트럭션들에게 일련의 프로그램 카운터(PC) 값들이 대응된다는 것을 관찰할 수 있는데 이러한 PC값들의 배열을 <code>논리적 제어흐름</code>, <code>논리흐름</code>이라고 부른다.
<img src="https://velog.velcdn.com/images/u_u/post/f5a8e185-4633-449c-aab2-2a5fe4a53631/image.png" alt="">
각 수직 방향의 시간 막대는 프로세스에 대한 논리적 제어흐름의 부분을 나타낸다.</p>
<blockquote>
<p>하나의 프로세서를 사용해서 여러 프로세스들이 교대로 돌아간다.</p>
</blockquote>
<p>이 프로세서의 하나의 물리적 제어흐름은 각 프로세스에 대해서 한 개씩 세 개의 <strong>논리흐름</strong>으로 나누어진다.
각 프로세스는 자신의 흐름의 일부분을 실행하고 나서 다른 프로세스들로 순서를 바꾸어 실행하는 동안 선점된다.</p>
<h3 id="822-동시성-흐름">8.2.2 동시성 흐름</h3>
<p>논리흐름은 여러가지 다른 형태를 갖는다
ex) 예외 핸들러, 프로세스, 시그널 핸들러 등등</p>
<p>자신의 실행시간이 다른 흐름과 겹치는 논리흐름을 <code>동시성 흐름</code>이라고 부르며, <strong>이 두 흐름은 동시에 실행한다고 말한다.</strong>
ex) 위 그림에서 (A, B), (A, C)가 그렇다.</p>
<p>프로세스가 다른 프로세스들과 교대로 실행된다는 개념은 <code>멀티태스킹</code>이라고 말하고 <code>타임슬라이싱</code> 이라고도 부른다.
ex) 위 그림에서 A는 두 개의 타임 슬라이스로 구성된다.</p>
<p>만약 두 흐름이 시간상으로 중첩되면, 동일한 프로세서에서 돌아가고 있더라도 이들은 <strong>동시적이다</strong> 라고 할 수 있다. 하지만 서로 다른 프로세서 코어나 컴퓨터에서 동시에 돌아가고 있다면, <code>병렬흐름</code>이다.</p>
<h3 id="823-사적-주소공간">8.2.3 사적 주소공간</h3>
<p>프로세스는 각 프로그램에 자신의 시스템의 주소공간을 혼자서 사용한다는 착각을 불러 일으킨다. 프로세스는 각 프로그램에 자신만의 사적 주소공간을 제공한다.
-&gt; 이 공간의 특정 주소에 연결된 메모리의 한 개의 바이트가 <strong>일반적으로 다른 프로세스에 의해서 읽히거나 쓰일 수 없다는 의미</strong>로 이 공간은 사적이다.</p>
<p><img src="https://velog.velcdn.com/images/u_u/post/bdf512e1-13cd-4417-ba48-79c0fed06b59/image.png" alt=""></p>
<h3 id="824-사용자-및-커널-모드">8.2.4 사용자 및 커널 모드</h3>
<p>모드 비트</p>
<p>프로세스가 사용자 모드에서 커널 모드로 진입하는 유일한 방법은 인터럽트, 오류, 트랩 시스템 콜 같은 예외를 통해서이다.</p>
<h3 id="825-문맥전환context-switching">8.2.5 문맥전환(Context Switching)</h3>
<ol>
<li>현재 실행중인 프로세스의 상태 저장 : 현재 프로세스의 상태 저장</li>
<li>다음 실행할 프로세스의 상태 복원 : 스케줄링에 따라 실행할 프로세스를 선택하고 저장된 상태를 복원한다. 중단된 지점에서 실행을 계속 할 수 있도록한다.</li>
<li>제어권 이전 : 선택된 프로세스에세 프로세서의 제어권이 이전된다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/u_u/post/ac80fa42-fde8-48f7-af95-8deec095d9ca/image.png" alt=""></p>
<p>두 개의 프로세스 A, B에 대해서 문맥전환이 일어나는 그림</p>
<blockquote>
<p>프로세스 A는 read 시스템 콜을 실행해서 커널에 트랩을 걸 때까지는 사용자 모드로 돌고 있다. 커널의 트랩 핸들러는 디스크 컨트롤러에게 DMA 전송을 요청하며, 디스크 컨트롤러가 데이터를 디스크에서 메모리로 전송을 완료한 후에 프로세서에 인터럽트를 걸도록 디스크를 제어한다.</p>
</blockquote>
<p>그래서 중간에 아무것도 안하는 대신에 커널은 프로세스 A에서 B로 문맥전환을 수행한다. 커널은 전환 이전에 프로세스 A를 대신해서 사용자 모드에서 인스트럭션들을 실행하고 있었다는 점을 주의해야 한다.(즉, 별도의 커널 프로세스는 없다.)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[크래프톤 정글] pintOS Week03]]></title>
            <link>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-pintOS-Week03</link>
            <guid>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-pintOS-Week03</guid>
            <pubDate>Tue, 13 Jun 2023 11:36:46 GMT</pubDate>
            <description><![CDATA[<h1 id="virtual-memory">Virtual Memory</h1>
<h2 id="용어설명">용어설명</h2>
<h3 id="pages">Pages</h3>
<blockquote>
<p>가상 페이지라고도 불리는 “페이지”는, 4,096 바이트(페이지 크기)의 길이를 가지는 가상 메모리의 연속된 영역입니다. 페이지는 반드시 페이지에 정렬(page-aligned)되어 있어야 합니다. 즉, 각 페이지는 페이지 크기(4KiB)로 균등하게 나누어지는 가상 주소에서 시작해야 한다는 말입니다. 그러므로 64비트 가상주소의 마지막 12비트는 페이지 오프셋(또는 그냥 “오프셋”)입니다. 후술하겠지만, 상위 비트들은 페이지 테이블의 인덱스를 표시하기 위해 쓰입니다. 64비트 시스템은 4단계 페이지 테이블을 사용하는데, 아래 그림과 같은 가상주소를 만들어줍니다 :</p>
</blockquote>
<pre><code>63          48 47            39 38            30 29            21 20         12 11         0
+-------------+----------------+----------------+----------------+-------------+------------+
| Sign Extend |    Page-Map    | Page-Directory | Page-directory |  Page-Table |    Page    |
|             | Level-4 Offset |    Pointer     |     Offset     |   Offset    |   Offset   |
+-------------+----------------+----------------+----------------+-------------+------------+
              |                |                |                |             |            |
              +------- 9 ------+------- 9 ------+------- 9 ------+----- 9 -----+---- 12 ----+
                                          Virtual Address
</code></pre><h3 id="frames">Frames</h3>
<blockquote>
<p>물리 프레임 또는 페이지 프레임이라고도 불리는 프레임은, 물리 메모리 상의 연속적인 영역입니다. 페이지와 동일하게, 프레임은 페이지사이즈여야 하고 페이지 크기에 정렬되어 있어야 합니다. 그러므로 64비트 물리주소는 프레임 넘버와 프레임 오프셋(또는 그냥 오프셋)으로 나누어질 수 있습니다. 아래 그림처럼 말입니다 :</p>
</blockquote>
<pre><code>                          12 11         0
    +-----------------------+-----------+
    |      Frame Number     |   Offset  |
    +-----------------------+-----------+
              Physical Address</code></pre><blockquote>
<p>x86-64 시스템은 물리주소에 있는 메모리에 직접적으로 접근하는 방법을 제공하지 않습니다. Pintos는 커널 가상 메모리를 물리 메모리에 직접 매핑하는 방식을 통해서 이 문제를 해결합니다 - 커널 가상메모리의 첫 페이지는 물리메모리의 첫 프레임에 매핑되어 있고, 두번째 페이지는 두번째 프레임에 매핑되어 있고, 그 이후도 이와 같은 방법으로 매핑되어 있습니다. 그러므로 커널 가상메모리를 통하면 프레임들에 접근할 수 있습니다.</p>
</blockquote>
<h3 id="page-tables">Page Tables</h3>
<blockquote>
<p>페이지 테이블은 CPU가 가상주소를 물리주소로, 즉 페이지를 프레임으로 변환하기 위해 사용하는 자료구조입니다. 페이지 테이블 포맷은 x86-64 아키텍쳐에 의해 결정되었습니다. Pintos는 threads/mmu.c안에 페이지 테이블을 관리하는 코드를 제공합니다.</p>
</blockquote>
<blockquote>
<p>아래 도표는 페이지와 프레임 사이의 관계를 나타냅니다. 왼쪽에 보이는 가상주소는 페이지 넘버와 오프셋을 포함하고 있습니다. 페이지 테이블은 페이지 넘버를 프레임 넘버로 변환하며, 프레임 넘버는 오른쪽에 보이는 것처럼 물리주소를 획득하기 위한 미수정된 오프셋과 결합되어 있습니다.</p>
</blockquote>
<pre><code>                           +----------+
          .---------------&gt;|Page Table|-----------.
         /                 +----------+           |
        |   12 11 0                               V  12 11 0
    +---------+----+                         +---------+----+
    | Page Nr | Ofs|                         |Frame Nr | Ofs|
    +---------+----+                         +---------+----+
     Virt Addr   |                            Phys Addr    ^
                  \_______________________________________/
</code></pre><h3 id="swap-slots">Swap Slots</h3>
<blockquote>
<p>스왑 슬롯은 스왑 파티션 내의 디스크 공간에 있는 페이지 크기의 영역입니다. 하드웨어적 제한들로 인해 배치가 강제되는 것(정렬)이 프레임에서보단 슬롯에서 더 유연한 편이지만, 정렬한다고 해서 별다른 부정적인 영향이 생기는 건 아니기 때문에 스왑 슬롯은 페이지 크기에 정렬하는 것이 좋습니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/u_u/post/bc54a831-9361-42db-8e6d-dd6ef1833ae7/image.jpeg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Interrupt, System call]]></title>
            <link>https://velog.io/@u_u/CS-Interrupt-System-call</link>
            <guid>https://velog.io/@u_u/CS-Interrupt-System-call</guid>
            <pubDate>Sun, 04 Jun 2023 07:29:50 GMT</pubDate>
            <description><![CDATA[<h1 id="user-mode--kernel-mode">User mode &amp; Kernel mode</h1>
<p><code>User mode</code> - 우리가 개발하는 프로그램은 일반적으로 <code>User mode</code>에서 실행
<code>User mode -&gt; Kernel mode</code> - 프로그램 실행 중에 인터럽트가 발생하거나 시스템 콜을 호출하게 되면 커널 모드로 전환</p>
<p><code>Kernel mode</code> - 프로그램의 현재 CPU 상태를 저장한다. 커널이 인터럽트나 시스템 콜을 직접 처리 즉, CPU에서 커널 코드가 실행 됌
처리가 완료되면 중단됐던 프로그램의 CPU 상태를 복원
어떤 경우에는 중단됐던 프로그램이 바로 실행되지 않고 나중에 실행될 수 있다.</p>
<p><code>Kernel mode -&gt; User mode</code> 다시 통제권을 프로그램에게 반환
<code>User mode</code> - 프로그램이 이어서 실행</p>
<blockquote>
<p>Kernel - 운영체제의 핵심 시스템의 전반을 관리/감독하는 역할 하드웨어와 관련된 작업을 직접 수행</p>
</blockquote>
<h3 id="why-kernel-mode">Why? Kernel mode</h3>
<p>시스템을 보호하기 위해 - 프로그램이 하드웨어에 대한 무분별한 사용을 막기 위해</p>
<h1 id="interrupt">Interrupt</h1>
<blockquote>
<p>시스템에서 발생한 다양한 종류의 이벤트, 그런 이벤트를 알리는 메커니즘</p>
</blockquote>
<p style="font-size:14px">ex) 전원에 문제가 생겼을 때, I/O 작업이 완료됐을 때, 시간이 다 됐을 때, 0으로 나눴을 때, 잘못된 메모리 공간에 접근을 시도할 때</p>

<p>인터럽트가 발생하면 CPU에서는 &quot;즉각적으로&quot; 인터럽트 처리를 위해 커널 코드를 커널 모드에서 실행</p>
<h1 id="system-call">System call</h1>
<blockquote>
<p>프로그램이 OS커널이 제공하는 서비스를 이용하고 싶을 때 시스템 콜을 통해 실행</p>
</blockquote>
<p style="font-size:14px">ex) 프로세스/스레드 관련, 파일 I/0 관련, 소켓 관련, 장치(device) 관련, 프로세스 통신 관련</p>

<p>시스템 콜은 프로세스가 운영체제의 서비스를 요청하기 위해 사용하는 인터페이스이다.</p>
<p>시스템 콜이 발생하면 해당 커널 코드가 커널 모드에서 실행</p>
<p>하드웨어 혹은 시스템 관련 기능은 어떤 프로그램이라도 반드시 시스템 콜을 통해서만 사용 가능</p>
<p><img src="https://velog.velcdn.com/images/u_u/post/ba6676fc-a808-47e9-89b5-352ae11ed893/image.png" alt=""></p>
<h4 id="하지만-우리는-직접-os에-시스템-콜을-하지-않는다-하지만-파일-네트워크-io-프로세스스레드-관련-작업을-할-수-있다"><strong>하지만 우리는 직접 OS에 시스템 콜을 하지 않는다, 하지만 파일, 네트워크 I/O 프로세스/스레드 관련 작업을 할 수 있다.</strong></h4>
<blockquote>
<p>우리가 사용하는 프로그래밍 언어들이 시스템 콜을 포장(wrapping)하여 간접적으로 사용할 수 있도록 제공했기 때문이다.</p>
</blockquote>
<p><a href="https://www.youtube.com/watch?v=v30ilCpITnY">출처 : Youtube 쉬운코드</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[크래프톤 정글] pintOS Week02]]></title>
            <link>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-pintOS-Week02</link>
            <guid>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-pintOS-Week02</guid>
            <pubDate>Sat, 03 Jun 2023 13:27:53 GMT</pubDate>
            <description><![CDATA[<h1 id="user-programs">User programs</h1>
<blockquote>
<p>궁금한 것</p>
</blockquote>
<ol>
<li>페이지가 해제될 때, 페이지의 모든 바이트들은 0xcc 로 클리어되어 디버깅을 도와줍니다.</li>
</ol>
<p><a href="https://velog.io/@u_u/CSAPP-Chapter08">CSAPP 8장</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[크래프톤 정글] pintOS Week01]]></title>
            <link>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-pintOS-Week01</link>
            <guid>https://velog.io/@u_u/%ED%81%AC%EB%9E%98%ED%94%84%ED%86%A4-%EC%A0%95%EA%B8%80-pintOS-Week01</guid>
            <pubDate>Sat, 27 May 2023 13:16:33 GMT</pubDate>
            <description><![CDATA[<h1 id="pintos">pintOS</h1>
<h2 id="week01">Week01</h2>
<blockquote>
<p>체크포인트 : <a href="https://velog.io/@qweadzs/CS-%EC%9D%B8%ED%84%B0%EB%9F%BD%ED%8A%B8interupt">interrupt</a></p>
</blockquote>
<ol>
<li>쓰레드 상태 (무엇이 있는지, 어떤 함수 또는 인터럽트등이 불려지면 어떤 상태로 전환되는지)</li>
<li>스케줄링이 무엇인지? (1의 함수들 호출과 스케줄링 관계 설명)</li>
<li>컨택스트 스위칭이란? + PCB</li>
<li>동기화 수단 (무엇이 있는지, 각각을 비교) - semaphore, lock, monitor (mutex)</li>
<li>프로세스와 쓰레드의 차이점</li>
<li>atomic이란?</li>
<li>스케줄링 알고리즘 (fifo, rr, ...)</li>
<li>프로세스는 무엇을 가상화하고 있나요? (토요일 권영진교수님 특강에서 아주 쉽게 설명해주실것 같네요)</li>
</ol>
<blockquote>
<p>김현수 코치님 :
&quot;면접관님이 운영체제에 대해서 이런 범위에서 질문을 하실텐데요.
개념적인 내용에 대해서 잘 대답하고
추가로 “그것들의 내부 구현은 이렇게 되어있습니다” 라고 설명한다면
<strong>기본기가 충실하면서, 경쟁력 있는 신입으로 보이지 않을까요?</strong>&quot;</p>
</blockquote>
<h3 id="alarm-clock">Alarm Clock</h3>
<h3 id="priority-scheduler">Priority Scheduler</h3>
<blockquote>
<p>Modify pintOS scheduler for priority scheduling</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Mutex & Semaphore]]></title>
            <link>https://velog.io/@u_u/CS-Mutex-Semaphore</link>
            <guid>https://velog.io/@u_u/CS-Mutex-Semaphore</guid>
            <pubDate>Sat, 27 May 2023 13:01:33 GMT</pubDate>
            <description><![CDATA[<h1 id="mutex--semaphore">Mutex &amp; Semaphore</h1>
<h2 id="교착상태">교착상태</h2>
<p><img src="https://velog.velcdn.com/images/u_u/post/8dff3761-87fc-4121-adb4-366d5cb8fc4f/image.png" alt=""></p>
<blockquote>
<p>2가지 이상의 작업이 상대방이 끝나기까지 기다리는 상태</p>
</blockquote>
<p>연필과 종이 각각을 갖고 있으면 필기를 할 수 없다
-&gt; 서로의 자원을 놓아줄 생각은 없고 자원 요청을 무한정 대기하고 있는 상태 : <strong>교착상태</strong></p>
<p>연필과 종이 : <strong>공유자원</strong>
공유자원이 속해있어 교착상태가 발생할 수 있는 영역 : <strong>임계영역</strong></p>
<h3 id="교착상태가-만족하려면">교착상태가 만족하려면</h3>
<p><code>상호 배제</code>, <code>점유 대기</code>, <code>비선점</code>, <code>순환 대기</code>
-&gt; 이 4가지 조건 중 하나라도 만족하지 않으면 교착상태가 발생한다.</p>
<h1 id="상호-배제">상호 배제</h1>
<blockquote>
<p>프로세스들이 필요로 하는 자원에 대한 배타적 통제권을 요구하는 것.</p>
</blockquote>
<p>하나의 프로세스가 공유자원을 사용할 때 다른 프로세스가 동일한 공유자원에 접근할 수 없게 통제하는 것.</p>
<p><img src="https://velog.velcdn.com/images/u_u/post/e7f59a7c-14ee-4c30-ab88-1959c96321e3/image.png" alt=""></p>
<h1 id="mutex-mutual--exclusion">Mutex (Mutual + Exclusion)</h1>
<blockquote>
<p>여러 스레드를 실행하는 환경에서 자원에 대한 접근에 제한을 강제하기 위한 동기화 매커니즘</p>
</blockquote>
<h3 id="ex-손님스레드과-식당임계영역">ex) 손님(스레드)과 식당(임계영역)</h3>
<p>식당은 하나의 손님만 받을 수 있고, 손님이 있을 때는 가게의 문을 걸어잠그고 (Lock 방식) 한 명의 손님만 집중한다.
기존 손님이 식사를 마치고 나올 때 까지 다음 손님은 기다려야 한다.</p>
<p>대기하는 방식을 두가지 알 수 있다. (대기실, 식당 입구)</p>
<ol>
<li><p>Mutex는 대기 큐를 생성해두고 임계영역에 스레드가 있을 경우 다른 스레드가 공유자원을 사용하려고 하면 스레드를 blocking 하고 대기 큐에 sleep시킨다.</p>
</li>
<li><p>SpinLock</p>
</li>
</ol>
<blockquote>
<p>식당에 손님이 있고 입구는 lock이 걸린 상태에서 다른 손님이 식당 입구에서 자리가 있는지 계속 기다리는 방식</p>
</blockquote>
<p>기다리고는 있지만 계속해서 물어보는 행동을 Busy-waiting이라고 한다.</p>
<p>이 경우 종업원은 손님의 물음에 계속 대답해야하기 때문에 다른 업무처리를 할 수 없다. -&gt; 비효율적</p>
<p>언제 사용하면 좋을까?</p>
<blockquote>
<p>대기실까지 이동하는 시간보다 식당에 진입하게 될 시간이 더 짧은가?
= 컨텍스트 스위칭 시간이 더 짧은가?</p>
</blockquote>
<blockquote>
<p>직원이 여러 명 있는 식당인가?
= 멀티 코어 프로세스 인가?</p>
</blockquote>
<h1 id="semaphore">Semaphore</h1>
<blockquote>
<p>멀티프로그래밍 환경에서 다수의 프로세스나 스레드의 여러 개의 공유 자원에 대한 접근을 제한하는 방법으로 사용된다.</p>
</blockquote>
<p><strong>Mutex와 다르게 멀티 스레드가 동시에 접근할 수 있다.</strong></p>
<p>수용 가능한 수만큼 숫자를 표시하고 없을 경우 0을 표시한다.</p>
<p>어느 순간에 숫자를 갱신해야 하는가? 
-&gt; 들어올 때, 나갈 때 / P(wait), V(signal)을 사용한다.
(Atomic operation이라고 생각하면 된다.)</p>
<p>들어올 때 P를 입력하고, 나갈 때 V를 입력하고 숫자를 갱신. </p>
<p>Sleep waiting
대기 큐에서 잠자고 있다가 사용 가능한 큐가 생기면 잠자고 있던 스레드를 깨우는 방식</p>
<p>busy waiting
사용 가능한 자원이 생길 때 까지 계속 검사</p>
<p><img src="https://velog.velcdn.com/images/u_u/post/adea6f5f-41f7-47cf-88aa-ab984d750892/image.png" alt=""></p>
<p>++ Mutex는 0, 1로 이뤄진 세마포어라고 할 수 있다.</p>
<p><a href="https://velog.io/@soopsaram/Kernel-Mutex%EC%99%80-Spinlock-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0">Velog 출처</a>
<a href="https://www.youtube.com/watch?v=oazGbhBCOfU&amp;t=27s">우아한테크 10분 테코톡</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSAPP] Chapter 11.]]></title>
            <link>https://velog.io/@u_u/CSAPP-Chapter-11</link>
            <guid>https://velog.io/@u_u/CSAPP-Chapter-11</guid>
            <pubDate>Mon, 22 May 2023 07:44:53 GMT</pubDate>
            <description><![CDATA[<h1 id="네트워크-프로그래밍">네트워크 프로그래밍</h1>
<blockquote>
<p>모든 네트워크 어플리케이션은 <strong>동일한 프로그래밍 모델</strong>을 기초로 하고, 비슷한 논리 구조로 동일한 인터페이스를 사용한다.</p>
</blockquote>
<h2 id="111-클라이언트-서버-프로그래밍-모델">11.1 클라이언트-서버 프로그래밍 모델</h2>
<blockquote>
<p>모든 네트워크 어플리케이션은 클라이언트-서버 모델을 기초로 하고 있으며, 한 개의 서버 프로세스와 한 개 이상의 클라이언트 프로세스로 구성된다.</p>
</blockquote>
<ul>
<li>서버는 일부 리소스를 관리하고, 리소스를 조작하여 클라이언트를 위한 서비스를 제공한다.</li>
<li>FTP(File Transfer Protocol) 서버는 클라이언트를 위해 저정하고 읽어오는 디스크 파일들을 관리한다. <p style="font-size:15px; color:;">ex) Filezilla - 서버에 연결하여 서버에 존재하는 파일에 접근하여 관리한다.</p></li>
<li>클라이언트-서버 모델에서 근본적인 연산은 트랜잭션이다.</li>
</ul>
<img src="https://velog.velcdn.com/images/u_u/post/b5d3efbe-ff80-4a9e-8e3a-5e17338f4e5a/image.png" alt="클라이언트-서버 트랜잭션">

<ol>
<li>클라이언트가 서버에 요청을 보낸다 (트랜잭션 개시).</li>
<li>서버는 요청을 받고 자원들을 조작한다.<p style="font-size:15px; color:;">ex) 웹 서버가 브라우저로부터 요청을 받을 때, 디스크 파일을 읽는다.</p></li>
<li>서버는 response를 클라리언트를 보내고, 다음 요청을 기다린다.<p style="font-size:15px; color:;">ex) 웹 서버는 이 파일을 다시 클라이언트로 보낸다.</p></li>
<li>클라이언트는 응답을 받고 이것을 처리한다.<p style="font-size:15px; color:;">ex) 웹 브라우저가 서버로부터 페이지 한 개를 받은 후 스크린에 출력한다.</p>

</li>
</ol>
<p>클라이언트-서버는 <strong>프로세스</strong>이며, 호스트가 아니다.</p>
<h2 id="112-네트워크">11.2 네트워크</h2>
<blockquote>
<p>추가정보 internet 과 Internet의 차이 : internet은 일반적인 internet 개념을 나타내고, Internet은 특정 구현, 즉 IP Internet을 의미한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/u_u/post/99297dc3-5722-4e8d-8aed-9f18b3663d57/image.png" alt=""></p>
<p style="font-size:13px; color:; text-align:center">네트워크 호스트의 하드웨어 구성</p>


<ul>
<li>호스트(컴퓨터라고 해석하면 편하다)에게 네트워크는 단지 또 다른 I/O 디바이스이며, 그림처럼 데이터를 위한 소스와 싱크로 서비스한다.</li>
<li>네트워크에서 수신한 데이터는 I/O와 메모리 버스를 거쳐서 어댑터에서 메모리로, 대개 DMA 전송으로 복사된다.</li>
<li>물리적으로 네트워크는 기하학적 위치로 구성된 <code>계층구조 시스템</code>이다.</li>
<li>하위수준은 <code>LAN(Local Area Network)</code>로 빌딩이나 캠퍼스에 설치된다. 장 대중적인 LAN 기술은 <strong>이더넷(Ethernet)</strong> 이며 Xerox PARC에서 개발되었다.</li>
</ul>
<img src="https://velog.velcdn.com/images/u_u/post/64d4755a-decf-4d23-94d4-96e7b77481dd/image.png" width="500" height="200" align="center">

<ul>
<li><code>이더넷 세그먼트</code>는 <strong>호스트와 허브</strong>로 구성된다, 대개 방이나 빌딩 층과 같이 작은 지역에 설치한다.<p style="font-size:15px; color:;">ex) 군 부대 또는 집 출입문 또는 층마다 설치되어 있는 단자함st</p></li>
<li>이더넷 어댑터는 <strong>호스트의 어댑터, 허브의 포트</strong>에 연결된다</li>
<li>이더넷 어댑터는 어댑터의 비휘발성 메모리에 저장된 전체적으로 고유한 48비트 주소를 가진다.</li>
<li>호스트는 <code>프레임 (Frame)</code>이라고 부르는 비트들을 이더넷 세그먼트의 다른 호스트에 보낼 수 있다.</li>
<li><code>프레임</code>은 출발지와 목적지, 프레임의 길이를 식별할 수 있는 고정된 헤더 비트를 가지며, 그 뒤에 데이터(payload) 비트가 이어진다.</li>
<li>모든 호스트는 이 프레임을 볼 수 있지만 <strong>목적지 호스트만이 읽을 수 있다.</strong></li>
</ul>
<p><strong><p style="font-size:15px">이더넷 어댑터는 이더넷 네트워크를 이용하기위한 하드웨어 장치, MAC Address는 이더넷 네트워크에서 장치를 식별하기 위한 고유 주소.</p></strong> </p>
<p><img src="https://velog.velcdn.com/images/u_u/post/94ba6a38-3ef3-401d-af63-2e8fc989bbdb/image.png" alt=""></p>
<ul>
<li>브릿지형 이더넷으로 전체 빌딩이나 캠퍼스 규모로 설치 할 수 있다.</li>
<li>브릿지가 허브보다 더 큰 전선의 대역폭을 갖고 있다.</li>
<li>계층구조의 상부에 LAN들을 연결해주는 <code>라우터(router)</code>가 존재한다.</li>
<li>라우터는 Point-to-Point 연결이 가능하며 WAN(Wide Area Network)라고 한다.</li>
</ul>
<blockquote>
<p>Q. internet의 주요한 특성은 LAN과 WAN들로 이뤄져 있다는 것인데, 그렇다면 각 호스트는 물리적으로 연결되어져 있지 않는 비호환적인 네트워크를 지나 어떻게 목적지 호스트에 데이터를 전송할 수 있을까?</p>
</blockquote>
<p>A. 해답은 네트워크 간의 차이를 줄여 주는 호스트와 라우터에서 돌고 있는 <code>프로토콜 소프트웨어의 계층</code>이다. 이 소프트웨어는 <strong>어떻게 호스트들과 라우터들이 데이터를 전송하기 위해서 협력하는지를 결정하는 프로토콜을 구현</strong>한 것이다.</p>
<ol>
<li>명명법 (Naming scheme) : 서로 다른 LAN 기술은 주소를 호스트에 할당하는 서로 다른 비호환성을 갖는 방법을 사용한다. 호스트는 자신을 유일하게 식별하는 internet 주소 최소한 한 개가 할당된다. (IP address)</li>
<li>전달기법 (Delivery Mechanism) : 서로 다른 네트워킹 기술은 서로 다른 비호환성을 갖는 비트 인코딩 방법과 프레임 내에 이들을 패키징 하는 방법을 갖고 있다. IP는 데이터 비트 <code>패킷</code>을 통해 패키징한다.
<code>패킷</code>은 <strong>패킷 헤더</strong>와 출발지 호스트가 보내려는 데이터 비트를 포함하는 <strong>데이터</strong>로 구성된다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/u_u/post/3ae4a040-caf5-40c3-a701-6386f74515bd/image.png" alt=""></p>
<p style="font-size:15px; color:#AA">다시 보는 단어장 </p>

<p><code>Frame</code> : 출발지와 목적지, 프레임 길이를 식별할 수 있는 헤더와 데이터를 갖고있다.</p>
<ol>
<li>호스트 A의 클라이언트는 클라이언트의 가상 주소공간에서 커널 버퍼로 데이터를 복사하는 시스템 콜을 호출한다.</li>
<li><code>internet H + FH1 = LAN1 Frame</code> internet 헤더에는 목적지 주소의 헤더로 지정된다. FH1은 라우터로 주소가 지정된다. 호스트 A는 프레임을 어댑터로 전달하고 FH1의 데이터가 internet <code>패킷</code>이며, 이렇게 패키징하는 것을 <code>캡슐화</code>라고 한다.</li>
<li>LAN1 어댑터는 프레임을 네트워크로 복사한다.</li>
<li>프레임이 라우터에 도달하면, 라우터의 LAN1 어댑터는 프로토콜 소프트웨어로 전달한다.</li>
<li>이 단계에서는 라우터가 internet 패킷 헤더에서 목적지 internet 주소를 가져와 라우팅 테이블의 인덱스로 사용하여 패킷을 전달할 위치를 결정합니다. 이 과정에서 라우터는 FH1을 벗겨내고 FH2를 붙여 어댑터로 전달한다.</li>
<li>라우터의 LAN2 어댑터는 이 프레임을 네트워크로 복사한다.</li>
<li>프레임이 호스트 B에 도착하면 어댑터는 이것을 프로토콜 소프트웨어로 넘긴다.</li>
<li>마지막으로 호스트 B의 프로토콜 소프트웨어는 패킷 헤더와 프레임 헤더를 벗겨내고, 프로토콜 소프트웨어는 이 데이터를 서버가 시스템 콜로 호출할 때 서버의 가상 주소공간으로 복사한다.</li>
</ol>
<blockquote>
<p>대부분의 모든 header에는 데이터 크기, 출발지와 목적지 주소를 갖고 있다.</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>