<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>IT's time to study</title>
        <link>https://velog.io/</link>
        <description>블로그 이전 👉 https://hyungjinhan.github.io/</description>
        <lastBuildDate>Sun, 12 Mar 2023 20:42:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. IT's time to study. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hyungjin_han" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[나만의 모음집]]></title>
            <link>https://velog.io/@hyungjin_han/working</link>
            <guid>https://velog.io/@hyungjin_han/working</guid>
            <pubDate>Sun, 12 Mar 2023 20:42:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>그냥 갑자기 생각나서 끄적여보는 다양한 모음집</p>
<p>의식의 흐름대로 작성하는 모든 링크 총 집합</p>
<p>생각나거나 내키는대로 바로바로 업데이트 예정이며, 당장 사용하기 위함</p>
</blockquote>
<h1 id="1-노동요-🎶">1. 노동요 🎶</h1>
<blockquote>
<p>유튜브를 풀로 틀어놓고 작업을 하기 때문에 마음에 드는 유튜버나 노래 모음 영상 링크 모음</p>
</blockquote>
<h2 id="1-1-해외">1-1. 해외</h2>
<blockquote>
<p>특정한 가수, 아예 인기 음악 모음 등 다양하게 종류별로 모아놓은 걸 정리한 것</p>
</blockquote>
<h3 id="노래-모음">노래 모음</h3>
<ul>
<li><a href="https://youtube.com/playlist?list=PLqSXTNqsyZvtOEg0_wtFg1ide3-DQ9o12" target="_blank">해외노래 Playlist</a></li>
</ul>
<h3 id="가수-모음">가수 모음</h3>
<ul>
<li><p><a href="https://youtube.com/playlist?list=PLqSXTNqsyZvtPlH8VbJsgGwngH4nxp7Xl" target="_blank">해외가수 Playlist</a></p>
</li>
<li><p><strong>Jagwar Twin</strong></p>
<ul>
<li><a href="https://youtube.com/playlist?list=PLYtV41JnQFraoY8Bu5l4PH23rhdsh6X1D" target="_blank">Jagwar Twin Playlist</a></li>
</ul>
</li>
</ul>
<h3 id="ost-모음">OST 모음</h3>
<ul>
<li><a href="https://youtube.com/playlist?list=PLqSXTNqsyZvsWGaf30_8VBNXyy7-3ZsVH" target="_blank">해외 OST Playlist</a></li>
</ul>
<h2 id="1-2-국내">1-2. 국내</h2>
<blockquote>
<p>사실 국내는 노래 모음보다는 가수 모음을 주로 노동요로 사용</p>
</blockquote>
<h3 id="가수-모음-1">가수 모음</h3>
<ul>
<li><p><a href="https://youtube.com/playlist?list=PLqSXTNqsyZvvsbwCfwtmWBMlzlpX_6_8s" target="_blank">국내가수 Playlist</a></p>
</li>
<li><p><strong>LEGIT GOONS (리짓군즈)</strong></p>
<ul>
<li><a href="https://youtube.com/playlist?list=PLqSXTNqsyZvvCgNs5NwjpXN_TxAc2B3dW" target="_blank">LEGIT GOONS (리짓군즈) Playlist</a></li>
</ul>
</li>
</ul>
<h2 id="1-3-기타">1-3. 기타</h2>
<blockquote>
<p>장르, 국적 불문 거의 다 모여있다고 생각되는 플레이리스트를 정리</p>
</blockquote>
<h3 id="주다사-플레이리스트">주다사 플레이리스트</h3>
<ul>
<li><a href="https://youtube.com/playlist?list=PLObtqksmKx30uYB1zIQvYE0UJI6o0OheE" target="_blank">주다사 플레이리스트</a></li>
</ul>
<hr>
<h1 id="2-노동용-💻">2. 노동용 💻</h1>
<blockquote>
<p>유튜브 들어가서 직접 플레이리스트를 들어가는 것이 귀찮아서 만드는 프로젝트 모음집</p>
</blockquote>
<h2 id="2-1-공부용-리스트">2-1. 공부용 리스트</h2>
<blockquote>
<p>실제로 프로젝트 진행을 하면서 공부할 수 있는 것들을 모아둔 나의 코딩 공부 모음집 </p>
</blockquote>
<h3 id="유튜브-플레이리스트">유튜브 플레이리스트</h3>
<ul>
<li><p><a href="https://youtube.com/playlist?list=PLqSXTNqsyZvvfVuaS2ngh0QEjmO9HHJGH" target="_blank">코딩 공부 (by.한형진)</a></p>
</li>
<li><p><a href="https://youtube.com/playlist?list=PLS8gIc2q83OjStGjdTF2LZtc0vefCAbnX" target="_blank">머신러닝/딥러닝 강의</a></p>
</li>
</ul>
<h3 id="기타-무료-인강">기타 무료 인강</h3>
<ul>
<li><p><a href="https://nomadcoders.co/flutter-for-beginners/lobby" target="_blank">Flutter 로 웹툰 앱 만들기</a></p>
</li>
<li><p><a href="https://nomadcoders.co/javascript-for-beginners/lobby" target="_blank">바닐라 JS로 크롬 앱 만들기</a></p>
</li>
<li><p><a href="https://nomadcoders.co/graphql-for-beginners/lobby" target="_blank">GraphQL로 영화 API 만들기</a></p>
</li>
<li><p><a href="https://nomadcoders.co/nestjs-fundamentals/lobby" target="_blank">NestJS로 API 만들기</a></p>
</li>
</ul>
<h2 id="2-2-실제로-자주-사용">2-2. 실제로 자주 사용</h2>
<blockquote>
<p>여기는 거의 항상 접속하는 그런 공간 (아마 나만 입장이 가능한 링크가 많을 듯)</p>
</blockquote>
<h3 id="개인-링크">개인 링크</h3>
<ul>
<li><p><strong>타인 입장 ⭕</strong></p>
<ul>
<li><p><a href="https://github.com/HyungJinHan" target="_blank">GitHub</a></p>
</li>
<li><p><a href="https://hyungjinhan.vercel.app/" target="_blank">포트폴리오 사이트</a></p>
</li>
</ul>
</li>
<li><p><strong>타인 입장 ❌</strong></p>
<ul>
<li><p><a href="https://www.notion.so/hyungjinhan/For-Study-90b983559d494a1da0b6f0d2885658a6" target="_blank">Notion</a></p>
</li>
<li><p><a href="https://www.figma.com/files/team/1211263693291028005" target="_blank">Figma</a></p>
</li>
<li><p><a href="https://hyungjinhan-portfolio.sanity.studio/desk" target="_blank">Sanity</a></p>
</li>
<li><p><a href="https://vercel.com/dashboard" target="_blank">Vercel Dashboard</a></p>
</li>
<li><p><a href="https://console.firebase.google.com/?hl=ko" target="_blank">Firebase</a></p>
</li>
<li><p><a href="https://thirdweb.com/goerli/0xDEff216166bF562E6Fea34c5D7fF343E59eAc74e" target="_blank">Thirdweb 대시보드</a></p>
</li>
</ul>
</li>
</ul>
<h3 id="유용한-링크">유용한 링크</h3>
<ul>
<li><p><a href="https://simpleicons.org/" target="_blank">Simple Icons</a></p>
</li>
<li><p><a href="https://undraw.co/illustrations" target="_blank">unDraw - 무료 svg 사이트</a></p>
</li>
<li><p><a href="https://react-icons.github.io/react-icons/" target="_blank">React Icons - <code>react-icons</code> 라이브러리용 아이콘 사이트</a></p>
</li>
<li><p><a href="https://tailwindcss.com/" target="_blank">Tailwind CSS 공식 사이트 - 생각보다 많이 헷갈리는 부분 때문</a></p>
</li>
<li><p><a href="https://express.adobe.com/ko-KR/sp" target="_blank">Adobe Express (영상, 이미지 편집)</a></p>
</li>
<li><p><a href="https://logo.com/" target="_blank">개인 Logo 제작 사이트</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JavaScript란?]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-JavaScript%EB%9E%80</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-JavaScript%EB%9E%80</guid>
            <pubDate>Fri, 24 Feb 2023 07:37:17 GMT</pubDate>
            <description><![CDATA[<h1 id="1-기본적인-웹의-구조">1. 기본적인 웹의 구조</h1>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/f614f993-006b-46f7-ad90-3f0e05be7b38/image.png" alt=""></p>
<p>위의 사진과 같이 웹의 구조를 간단하게 설명하자면,</p>
<ul>
<li><p><code>HTML</code> : 웹 페이지의 구조를 만들어준다. (마크업 언어)</p>
</li>
<li><p><code>CSS</code> : 웹 페이지에 디자인을 입혀준다. (스타일 규칙 언어)</p>
</li>
<li><p><code>JavaScript</code> : 웹 페이지가 동적으로 움직이도록 만들어준다 (<code>스크립트 언어</code>)</p>
</li>
</ul>
<p>이렇게 설명할 수 있다.</p>
<p>여기서 <code>JavaScript</code>가 무엇인지 알아보는 시간을 갖도록 한다.</p>
<hr>
<h1 id="2-javascript는-무엇인가">2. <code>JavaScript</code>는 무엇인가?</h1>
<p><code>JavaScript</code>는 웹을 위한 인터프리터 언어이자 객체 기반의 스크립트 프로그래밍 언어이며, <code>HTML</code>의 특정 요소(들)을 선택하여 다양한 이벤트(마우스 클릭, 키보드 입력 등)에 따라 어떤 동작을 하도록 기능을 넣을 수 있다.</p>
<blockquote>
<p>발생하는 이벤트에 따라 <code>HTML</code>, <code>CSS</code>를 조작할 수도 있고 그 외에도 여러가지의 기능을 구현할 수 있다.</p>
</blockquote>
<h2 id="2-1-javascript의-역사">2-1. <code>JavaScript</code>의 역사</h2>
<p><code>JavaScript</code>는 1995년에 넷스케이프(<code>Netscape</code>)의 브렌던 아이크(Brendan Eich)에 의해 만들어졌다.</p>
<p>처음에는 모카(<code>Mocha</code>)라는 이름으로 개발되었으나, 그 후에 라이브스크립트(<code>LiveScript</code>), 최종적으로는 자바스크립트(<code>JavaScript</code>)라는 이름으로 변경된다.</p>
<hr>
<h1 id="3-javascript-실행-순서">3. <code>JavaScript</code> 실행 순서</h1>
<p>일반적으로 <code>JavaScript</code>는 위에서 아래의 순서대로 실행이 된다.</p>
<p>이는 순서에 주의해서 코드를 작성해야 한다는 의미이다.</p>
<blockquote>
<p>단, <code>Hoisting</code>으로 인한 예외의 경우가 발생할 수 있다.</p>
</blockquote>
<h2 id="3-1-javascript-엔진">3-1. <code>JavaScript</code> 엔진</h2>
<p>브라우저에는 <code>JavaScript</code> 가상 시스템이라는 내장 엔진이 존재한다.</p>
<ul>
<li><p><code>Chrome</code>, <code>Opera</code> -&gt; <code>V8</code></p>
</li>
<li><p><code>Firefox</code> -&gt; <code>SpiderMonky</code></p>
</li>
<li><p><code>IE</code> -&gt; <code>Trident</code> 및 <code>Chakar</code></p>
</li>
<li><p><code>Microsoft Edge</code> -&gt; <code>ChakraCore</code></p>
</li>
<li><p><code>Safari</code> -&gt; <code>Nitro</code> 및 <code>SquirrelFish</code></p>
</li>
</ul>
<h3 id="3-1-1-javascript-가상-시스템-엔진의-작동-방법">3-1-1. <code>JavaScript</code> 가상 시스템 엔진의 작동 방법</h3>
<ol>
<li><p>엔진이 스크립트를 읽음</p>
</li>
<li><p>스크립트를 기계어로 변환</p>
</li>
<li><p>코드를 빠르게 실행</p>
</li>
</ol>
<p>순서로 작동한다.</p>
<hr>
<h1 id="4-javascript의-특징">4. <code>JavaScript</code>의 특징</h1>
<p><code>JavaScript</code>는 객체 기반의 스크립트 언어이며, 객체 지향형 프로그래밍과 함수형 프로그래밍을 모두 표현할 수 있다.</p>
<p>또한 <code>JavaScript</code>는 동적이며, 타입을 명시할 필요가 없는 인터프리터 언어이다.</p>
<blockquote>
<p>이로 인해 발생할 수 있는 문제를 보완하기 위해 나온 것이 <code>TypeScript</code>이다.</p>
</blockquote>
<h2 id="4-1-javascript의-장단점">4-1. <code>JavaScript</code>의 장단점</h2>
<h3 id="4-1-1-javascript의-장점">4-1-1. <code>JavaScript</code>의 장점</h3>
<ul>
<li><p>컴파일 과정이 필요없으므로, 빠른 시간 안에 스크립트 코드를 작성할 수 있다.</p>
</li>
<li><p>다른 언어들에 비해 단순한 구조와 원칙을 갖고 있어 배우기 쉽다.</p>
</li>
<li><p>웹에 특화된 기술이기 때문에 운영체제나 플랫폼에 상관없이 잘 작동되고 확장성이 높다.</p>
</li>
</ul>
<h3 id="4-1-2-javascript의-단점">4-1-2. <code>JavaScript</code>의 단점</h3>
<ul>
<li><p><code>OS</code>에 직접 접근이 불가능하다.</p>
</li>
<li><p>하드디스크를 읽거나 쓸 수 없다.</p>
</li>
<li><p>다른 프로그램을 호출할 수 없다.</p>
</li>
<li><p><code>JavaScript</code>는 도메인이 동일한 두 탭/윈도우를 제외하고 탭/윈도우 간에 통신을 수횅할 수 있다.</p>
</li>
<li><p><code>JavaScript</code>는 웹 브라우저에서 실행되기 때문에 일부 보안상의 제약이 있으며, 브라우저에서 웹 페이지를 열 때 안전하고 위험에 처하지 않도록 보장해야 한다.</p>
</li>
<li><p>일반적으로 <code>JavaScript</code>는 자체 도메인에 대해서만 제한없이 네트워크 요청을 보낼 수 있다.</p>
</li>
</ul>
<hr>
<h1 id="5-javascript의-역할">5. <code>JavaScript</code>의 역할</h1>
<blockquote>
<p><code>JavaScript</code>의 일반적인 용도는 웹 페이지에 기능을 더하여 <code>HTML</code> 페이지를 동적으로 만들어주는 역할을 한다.</p>
</blockquote>
<h2 id="5-1-javascript가-할-수-있는-일">5-1. <code>JavaScript</code>가 할 수 있는 일</h2>
<ul>
<li><p><code>HTML</code> 페이지 변경 및 <code>HTML</code> 엘리먼트와 콘텐츠의 추가나 제거</p>
</li>
<li><p><code>CSS</code> 및 <code>HTML</code> 엘리먼트의 스타일 변경</p>
</li>
<li><p>사용자와의 상호작용, 폼의 유효성 검증</p>
</li>
<li><p>마우스와 키보드 이벤트에 대한 스크립트 실행</p>
</li>
<li><p>웹 브라우저 제어, 쿠키 등의 설정과 조회</p>
</li>
<li><p><code>AJAX</code> 기술을 이용한 웹 서버와의 통신</p>
</li>
</ul>
<hr>
<h1 id="6-java-vs-javascript">6. <code>Java</code> vs <code>JavaScript</code></h1>
<blockquote>
<p>이름으로는 서로 관련이 있는 언어로 생각하기 쉽지만, 사실상 두 언어는 서로 직접적인 관련이 전혀 없다.</p>
<p>문법상의 비슷한 부분이 존재하지만, 그 이유는 두 언어의 문법이 모두 <code>C</code>언어를 기반으로 만들어졌기 때문이다.</p>
</blockquote>
<table>
<thead>
<tr>
<th><code>Java</code></th>
<th><code>JavaScript</code></th>
</tr>
</thead>
<tbody><tr>
<td>컴파일 언어이다.</td>
<td>인터프리터 언어이다.</td>
</tr>
<tr>
<td>타입 검사를 엄격하게 한다.</td>
<td>타입을 명시하지 않는다.</td>
</tr>
<tr>
<td>클래스(<code>Class</code>) 기반의 객체 지향 언어이다.</td>
<td>프로토타입(<code>Prototype</code>) 기반의 객체 지향 언어이다.</td>
</tr>
</tbody></table>
<hr>
<h1 id="7-javascript-표준">7. <code>JavaScript</code> 표준</h1>
<p>1996년에 넷스케이프(<code>Netscape</code>)는 <code>JavaScript</code>를 국제 표준안으로 만들기 위해 <code>ECMA(European Computer Manufacturers Association)</code>에 제출한다.</p>
<p>그 결과, <code>ECMA</code>는 <code>ECMAScript</code>라는 새로운 표준을 제정하였고, 그 첫 번째 버전인 <code>ECMA-262</code>를 1997년에 공표한다.</p>
<p><code>ECMAScript</code>는 자바스크립트뿐만 아니라 마이크로소프트의 <code>JScript</code>나 어도비의 액션스크립트도 따르는 국제 표준이 된다.</p>
<blockquote>
<p>현재 <code>JavaScript</code> 최신 표준은 2019년에 발표된 <code>ECMAScript 2019(EX2019)</code>이다.</p>
</blockquote>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://velog.io/@surim014/%EC%9B%B9%EC%9D%84-%EC%9B%80%EC%A7%81%EC%9D%B4%EB%8A%94-%EA%B7%BC%EC%9C%A1-JavaScript%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-7gk4thno6n">surim&#39;s develog - 웹을 움직이는 근육, JavaScript란 무엇인가?</a>
<a href="https://ko.wikipedia.org/wiki/ECMA%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8">위키백과 - ECMA스크립트</a>
<a href="https://joontae-kim.github.io/2020/10/03/with-javascript/">Dev and Dev - 자바스크립트란?</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 실행 컨텍스트]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Thu, 23 Feb 2023 15:03:57 GMT</pubDate>
            <description><![CDATA[<h1 id="1-execution-context실행-컨텍스트란">1. <code>Execution Context</code>(실행 컨텍스트)란?</h1>
<p>실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.</p>
<p><code>JavaScript</code>는 동일한 환경에 있는 환경 정보들을 모은 실행 컨텍스트를 콜스택에 쌓아올린 후 실행하여 코드의 환경과 순서를 보장할 수 있게 된다.</p>
<p>즉, 스택(<code>Stack</code>)의 경우, <code>FILO(First In, Last Out)</code>의 구조이기에 순서를 보장하며, 콜스택 내부에 쌓인 실행 컨텍스트의 정보를 통해 환경을 보장할 수 있는 것이다.</p>
<p>위에서 말한 환경이란 전역 공간이 될 수 있고, 함수 내부의 환경이 될 수도 있다.</p>
<pre><code class="language-js">var temp = &quot;temp&quot;;

function b() {
  console.log(&quot;Hello, World&quot;);
}

function a() {
  b();
}

a(); // Hello, World</code></pre>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/f8741167-61fc-4ecd-9710-6eb6d188ba0e/image.png" alt=""></p>
<p>위의 예시와 그림을 참고하면,</p>
<ol>
<li><p>콜스택엔 전역 컨텍스트를 제외하고 다른 컨텍스트가 없기에 전역 컨텍스트와 관련된 코드를 진행한다.</p>
</li>
<li><p>전역 컨텍스트와 관련된 코드를 진행 중, <code>a</code> 함수를 실행했기 때문에 <code>a</code> 함수의 환경 정보들을 수집하여 <code>a</code> 실행 컨텍스트를 생성하고 콜스택에 담으며, 콜스택 최상단에 <code>a</code> 실행 컨텍스트가 있기 때문에 기존의 전역 컨텍스트와 관련된 코드의 실행을 일시적으로 중단한 후, <code>a</code> 실행 컨텍스트의 코드를 실행한다.</p>
</li>
<li><p><code>a</code> 함수 내부에서 <code>b</code> 함수를 실행하였기 때문에 <code>b</code> 함수의 환경 정보들을 수집하여 실행 컨텍스트를 생성하고, 콜스택에 담으며, 이전과 똑같이 콜스택 최상단에 <code>b</code> 실행 컨텍스트가 있기 때문에 기존 <code>a</code> 실행 컨텍스트와 관련된 코드의 실행을 일시적으로 중단한다.</p>
</li>
<li><p><code>b</code> 함수가 종료된 후, <code>b</code> 실행 컨텍스트가 콜스택에서 제거되고, 그 후 콜스택 최상단에는 <code>a</code> 실행 컨텍스트가 있기 때문에 이전에 중단된 지점부터 코드 진행이 재개된다.</p>
</li>
<li><p><code>a</code> 함수 또한 종료된 후 실행 컨텍스트가 콜스택에서 제거되며, 이후에는 전역 공간에 실행할 코드가 남아있지 않다면 콜스택에서 전역 컨텍스트 또한 제거되며 콜스택에 아무것도 남지 않은 상태로 종료된다.</p>
</li>
</ol>
<p>위의 단계로 <code>JavaScript</code> 코드가 진행된다.</p>
<hr>
<h1 id="2-실행-컨텍스트-내의-정보">2. 실행 컨텍스트 내의 정보</h1>
<blockquote>
<p>실행 컨텍스트 내부에는 <code>variable environment</code>, <code>lexical environment</code>, <code>this binding</code>이 있다.</p>
</blockquote>
<h2 id="2-1-variableenvironment">2-1. <code>VariableEnvironment</code></h2>
<p><code>VariableEnvironment</code>란 현재 컨텍스트 내부의 식별자 정보 <code>environmentRecord</code>, 외부 환경 정보 <code>outerEnvironmentReference</code>가 포함되어 있다.</p>
<p><code>VariableEnvironment</code>에 먼저 정보를 담고, 그대로 <code>LexicalEnvironment</code>에 복사해 사용한다고 한다.</p>
<h2 id="2-2-lexicalenvironment">2-2. <code>LexicalEnvironment</code></h2>
<p><code>LexicalEnvironment</code>는 초기에는 <code>VariableEnvironment</code>와 같지만 변경 사항이 실시간으로 적용된다.</p>
<p>즉, <code>VariableEnvironment</code> 초기 상태를 기억하고 있으며, <code>LexicalEnvironment</code> 최신 상태를 저장하고 있다.</p>
<h3 id="2-2-1-environmentrecord">2-2-1. <code>environmentRecord</code></h3>
<p><code>environmentRecord</code>란 현재 컨텍스트와 관련된 식별자와 식별자에 바인딩된 값이 기록되는 공간이다.</p>
<p>더불어 실행 컨텍스트 내부 전체를 처음부터 끝까지 확인하며 순서대로 수집한다.</p>
<pre><code class="language-js">var hhj = &quot;HyungJin Han&quot;;

console.log(hhj); // HyungJin Han</code></pre>
<pre><code class="language-js">console.log(hhj); // undefined

var hhj = &quot;HyungJin Han&quot;;</code></pre>
<p>위의 예시를 보면, 첫 코드 예시의 경우 문제없이 작동되나, 두 번째 예시의 경우 선언하기도 전에 값을 호출했지만, <code>Reference error</code>가 발생하지 않고, <code>undefined</code>가 출력된다.</p>
<blockquote>
<p>위의 현상은 <code>JavaScript</code>의 호이스팅이라는 현상과 관련있다.</p>
<p>호이스팅에 관련된 포스팅은 <a href="https://velog.io/@hyungjin_han/JavaScript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting%EC%9D%B4%EB%9E%80">이전에 올렸던 포스팅</a>을 보며 재차 공부할 예정이다.</p>
</blockquote>
<p><code>LexicalEnvironment</code>의 <code>environmentRecord</code>의 경우 해당 컨텍스트 환경에 필요한 식별자와 식별자의 값이 기록되며, 함수 실행 시 실행 컨텍스트가 생성되므로(함수 실행보다 <code>environmentRecord</code> 수집이 먼저 되므로) 변수와 같은 식별자를 끌어올리는 것과 같다는 개념의 호이스팅이 생겨났다.</p>
<h3 id="2-2-2-outerenvironmentreference">2-2-2. <code>outerEnvironmentReference</code></h3>
<pre><code class="language-js">const greeding = &quot;Hello, World&quot;;

const info = () =&gt; {
  const hhj = {
    age: 28,
    name: &quot;HyungJin Han&quot;,
  };
  const jhh = {
    age: 23,
    breed: &quot;HyungHan Jin&quot;,
  };
  console.log(greeding);
  console.log(hhj);
  console.log(jhh);
};
info(); // Hello, World { age: 28, name: &#39;HyungJin Han&#39; } { age: 23, breed: &#39;HyungHan Jin&#39; }
console.log(hhj); // ReferenceError: hhj is not defined
console.log(jhh); // ReferenceError: jhh is not defined</code></pre>
<p>위의 예시를 보면, 해당 코드의 함수 내부에서는 외부의 <code>greeding</code>이 접근 가능하며, 내부에서 선언한 <code>hhj</code>와 <code>jhh</code> 또한 접근이 가능하다.</p>
<p>하지만 외부에서는 내부에 선언된 <code>hhj</code>와 <code>jhh</code>에 접근할 수 없다.</p>
<p>그 이유는 <code>outerEnvironmentReference</code> 때문이다.</p>
<p><code>outerEnvironmentReference</code>란 현재 호출된 함수가 선언될 당시의 <code>LexicalEnvironment</code>를 참조하게 된다.</p>
<p>여기서 선언될 당시를 집중해야 하는데, <code>info</code> 함수가 선언될 당시의 <code>outerEnvironmentReference</code>는 글로벌 실행 컨텍스트의 <code>LexicalEnvironment</code>를 참조하고 있으며, 해당 환경의 <code>environmentRecord</code>에 <code>greeding</code>과 같은 변수의 정보들이 기록되어 있게 된다.</p>
<p>그렇기에 함수 내부에서는 <code>outerEnvironmentReference</code>를 통해 상위 컨텍스트의 <code>LexicalEnvironment</code>에 접근하여 <code>environmentRecord</code>에서 변수인 <code>greeding</code>을 사용할 수 있게 되는 것이다.</p>
<p>또한 <code>outerEnvironmentReference</code>는 오직 자신이 선언될 당시의 <code>LexicalEnvironment</code>를 참조하기 때문에 순차적으로만 접근이 가능하며, 여러 스코프에서 동일한 식별자를 생성하였다고 하더라도 가장 먼저 발견된 식별자만 접근이 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/78911d80-f300-4df2-9265-bd6e957ebd78/image.png" alt=""></p>
<pre><code class="language-js">const a = &quot;a&quot;;
const b = &quot;b&quot;;

const sayHi = () =&gt; {
  const a = &quot;aa&quot;;
  console.log(a); // aa
  console.log(b); // b
};

sayHi();</code></pre>
<p>위의 코드 예제를 보면, <code>a</code>라는 변수는 현재 컨텍스트의 <code>LexicalEnvironment</code> =&gt; <code>environmentRecord</code>에 <code>a</code>라는 식별자가 있고, <code>outerEnvironmentReference</code> =&gt; <code>LexicalEnvironment</code> =&gt; <code>environmentRecord</code>에도 <code>a</code> 식별자가 있지만, 가장 먼저 발견된(가까운) 식별자에 바인딩 된 값인 <code>aa</code>를 출력한다.</p>
<p>결국 전역 컨텍스트에서 선언한 <code>a</code>의 경우 변수 은닉화가 된다.</p>
<p><code>b</code> 변수는 현재 컨텍스트의 <code>LexicalEnvironment</code> =&gt; <code>environmentRecord</code> 에 <code>b</code> 라는 식별자가 있으므로, <code>outerEnvironmentReference</code> 참조하여 전역 컨텍스트의 <code>LexicalEnvironment</code> 참조, <code>environmentRecord</code> 의 <code>b</code> 식별자에 접근하여 <code>b</code>를 출력한다.</p>
<blockquote>
<p>결론적으로 <code>outerEnvironmentReference</code>란 해당 함수가 선언된 위치의 <code>LexicalEnvironment</code>를 참조하며, 변수에 접근을 한다면 해당 <code>LexicalEnvironment</code>에서 발견된다면 사용, 찾지 못할 경우 다시 <code>outerEnvironmentReference</code>를 참조하여 탐색하는 과정을 반복한다.</p>
<p>이러한 과정을 <a href="https://velog.io/@hyungjin_han/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%EC%8A%A4%EC%BD%94%ED%94%84%EC%B2%B4%EC%9D%B8-%ED%81%B4%EB%A1%9C%EC%A0%80%EB%9E%80">스코프 체인</a> 이라고 하며 <code>outerEnvironmentReference</code> 는 스코프 체인을 가능하게 하는 역할이다.</p>
</blockquote>
<h2 id="2-3-thisbinding">2-3. <code>ThisBinding</code></h2>
<p>우선 <code>this</code> 는 컨텍스트를 가르킨다.</p>
<p><code>method</code>에서 사용시 해당 <code>method</code>가 담겨있는 <code>instance or object</code>를 가르키며, 함수표현식에서 사용시 <code>this</code> 를 바인딩하지 않는 이상 전역 객체를 가르킨다.</p>
<p>더불어 전역 공간에서 <code>this</code>는 함수 표현식과 같이 전역 객체를 가르킨다.</p>
<p><code>ES6</code>의 화살표 함수를 사용하면 <code>this</code> 바인딩, 우회법으로 변수에 <code>this</code>를 담아 실행할 필요 없이 함수를 실행한 컨텍스트를 바라본다.</p>
<pre><code class="language-js">const obj = {
  outer: function () {
    console.log(this); // { outer: [Function: outer] }
    // 메소드에서 사용되었기에 obj 출력
    function inner() {
      console.log(this); // Object [global] {...}
      // 함수 표현식에서 사용되었기에 전역 객체 출력
    }
    inner();

    const self = this;
    function inner2() {
      console.log(self); // { outer: [Function: outer] }
      // 우회하기 위해 this를 self에 할당, 출력했기에 obj 출력
    }
    inner2();

    const inner3 = () =&gt; {
      console.log(this); // { outer: [Function: outer] }
      // 화살표함수 사용으로 this는 상위 스코프의 컨텍스트를 가르킴, obj 출력
    };
    inner3();
  },
};

obj.outer();</code></pre>
<blockquote>
<p>요약하자면, <code>this</code>는 실행 컨텍스트 생성 시, 즉, 함수를 실행할 때 할당해주는 것으로 상황에 따라 전역 객체 또는 <code>instance</code>를 카르킨다.</p>
</blockquote>
<hr>
<h1 id="3-결론">3. 결론</h1>
<blockquote>
<p>위에서 설명했듯이, 실행 컨텍스트는 <code>VariableEnvironment</code>, <code>LexicalEnvironment</code>, <code>environmentRecord</code>, <code>outerEnvironmentReference</code>, <code>hisBinding</code> 등의 여러 정보들이 합쳐져 실행 컨텍스트가 되고, 이것이 콜스택에 쌓여 <code>JavaScript</code>의 코드가 실행된다.</p>
</blockquote>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://gamguma.dev/post/2022/04/js_execution_context">감구마- JS Execution Context (실행 컨텍스트) 란?</a>
<a href="https://resilient-923.tistory.com/302">천천히 꾸준하게 - [javascript 자바스크립트] 실행 컨텍스트(Execution Context) 란?</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] 웹 표준과 웹 접근성]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-%EC%9B%B9-%ED%91%9C%EC%A4%80%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-%EC%9B%B9-%ED%91%9C%EC%A4%80%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Tue, 21 Feb 2023 05:30:54 GMT</pubDate>
            <description><![CDATA[<h1 id="1-웹-표준-web-standards">1. 웹 표준 (<code>Web Standards</code>)</h1>
<blockquote>
<p>웹 표준(<code>Web Standards</code>)이란?</p>
<p>&quot;웹에서 표준적으로 사용되는 기술이나 규칙&quot;으로 표준화 단체인 <code>W3C</code>가 권고한 표준안에 따라 웹 사이트를 작성할 때 이용하는 <code>HTML</code>, <code>CSS</code>, <code>JavaScript</code> 등에 규정이 담겨있다.</p>
</blockquote>
<p>즉, 어떤 운영체제나 브라우저를 사용하더라도 웹페이지가 동일하게 보이고 정상 작동해야함을 의미하며, 표준 스펙을 잘 지키는 것 뿐만 아니라 구조적 마크업(<code>XHTML</code>)과 표현 및 레이아웃(<code>CSS</code>) 및 사용자 행위 제어(<code>DOMScripting</code>)를 잘 분리하는 고급 홈페이지 구축하는 방식을 말한다.</p>
<p><code>CSS</code> 와 <code>HTML(XHTML)</code>로 웹 문서를 작성하는 것의 명확한 용어는 권고(<code>Recommend</code>)라고 하며 버전과 상관없이 <code>HTML</code>, <code>XHTML</code>은 그 자체로 표준이라고 한다.</p>
<blockquote>
<p>가이드 라인 참조</p>
<p><a href="https://www.w3.org/standards/">W3C - STANDARDS</a></p>
</blockquote>
<h2 id="1-1-웹-표준이-중요한-이유">1-1. 웹 표준이 중요한 이유</h2>
<blockquote>
<p>현재 인터넷의 사용량이 급증하고 있으며, 앞으로도 꾸준히 증가할 것으로, 이에 따라 표준화는 개발자로써 반드시 해결해야 할 과제이다.</p>
</blockquote>
<p>웹 표준이 없던 1990년대 말부터 2000년대 초반에는 웹 사이트 개발자는 사실상 두 개의 사이트를 만들어야 했다. (익스플로러, 넷스케이프)</p>
<p>하지만 지금과 같은 표준이 있었다면, 해당하는 표준에 맞게끔 한 번만 작업을 진행해도 되며, 이에 따라 노동력과 시간을 아낄 수 있게 된다.</p>
<blockquote>
<p>결국, 자연스럽게 정보 제공의 질도 올라가게 되므로, 현재 웹 개발자는 웹 표준에 따라 개발하는 것을 중요하게 생각하게 된다.</p>
</blockquote>
<p>위의 이유로 인해 웹 표준을 지킬 시, 생길 수 있는 장점이 많다.</p>
<h3 id="1-1-1-웹-표준의-장점">1-1-1. 웹 표준의 장점</h3>
<ul>
<li><p>소스의 통일화로 수정 및 운영관리가 용이하다.</p>
</li>
<li><p>다양한 브라우저, 휴대폰 <code>PDA</code>, 장애인 지원용 프로그램에서도 대응이 가능하므로, 접근성이 향상되고, 장애인, 고령자 등을 포함한 사용자 층도 확대가 가능하다.</p>
</li>
<li><p>논리적이고 효율적으로 작성된 웹 문서는 코드의 양이 줄어 파일의 크기가 줄고 서버 부담의 감소로 이어질 수 있다.</p>
</li>
<li><p><code>CSS</code>와 <code>HTML</code>이 분리되어 유지보수에 들어가는 시간이 단축되고, 불필요한 마크업이 최소화되어 페이지 로딩 속도가 향상된다.</p>
</li>
<li><p>오래된 브라우저에서도 컨텐츠가 적절하게 표시되고, 호환성과 운용성이 확보된다.</p>
</li>
<li><p>스크린 리더기 등 보조 공학 기기 사용자들이 조금 더 정확한 정보를 얻을 수 있도록 돕는다.</p>
</li>
<li><p>검색봇을 통한 효율적인 노출과 감튼 검색 엔진 최적화(<code>SEO</code>)가 가능하다.</p>
</li>
</ul>
<h2 id="1-2-웹-표준의-기술">1-2. 웹 표준의 기술</h2>
<ol>
<li><p><code>XHTML (eXtensible Hypertext Markup Language)</code></p>
</li>
<li><p><code>CSS (Cascading Style Sheets)</code></p>
</li>
<li><p><code>XML (eXtensible Markup Language)</code> </p>
</li>
<li><p><code>DOM (Document Object Model)</code></p>
</li>
<li><p><code>ECMAScript</code></p>
<ul>
<li><code>ECMA international</code> 의 <code>ECMA-262</code> 기술 명세에 정의된 표준화 된 스크립트 프로그래밍 언어</li>
</ul>
</li>
</ol>
<hr>
<h1 id="2-웹-접근성-web-accessibility">2. 웹 접근성 (<code>Web Accessibility</code>)</h1>
<blockquote>
<p>웹 접근성이란?</p>
<p>모든 사용자가 신체적, 환경적 조건에 관계없이 웹에 접근하여 이용할 수 있도록 보장하는 것이다.</p>
</blockquote>
<p>즉, 어떠한 사용자(일반인, 장애인, 고령자 등)가 어떠한 환경(브라우저, 운영체제, 디바이스의 환경이나 사양 등)에서도 어려움 없이 접근, 이용할 수 있는 것을 접근성이라고 한다.</p>
<blockquote>
<p><code>W3C</code> 정의에 따르면 웹 표준은 접근성, 사생활 보호, 보안, 국제화의 측면에서 고려해야 한다고 말한다.</p>
</blockquote>
<p>위의 정의를 쉽게 정리하자면, 웹 접근성은 신체적 차이나 장애 여부와 상관없이 누구나 원활하게 웹페이지를 이용할 수 있어야 한다는 것을 의미 한다.</p>
<p>예를 들어, 시각 장애인의 경우 화면을 눈으로 볼 수 없기 때문에 &quot;스크린 리더&quot;라는 별도의 소프트웨어를 컴퓨터에 설치하여 음성으로 웹페이지에 담긴 정보를 이해 한다.</p>
<p>하지만 스크린 리더는 스스로 웹 페이지의 내용을 분석하지 못한다.</p>
<blockquote>
<p>예를 들어 &quot;로그인&quot;이라는 텍스트 대신 메뉴라고 로그인 이미지를 사용할 경우 비시각 장애인의 눈에는 로그인 메뉴로 인식 가능하지만, 소프트웨어의 입장에서는 그저 이미지일 뿐이다.</p>
</blockquote>
<p>따라서, 되도록이면 이미지 대신 소스코드에 내용을 그대로 담는 것이 권장되며, 부득이하게 이미지를 사용할 경우,</p>
<pre><code class="language-html">&lt;img src=&quot;img/login.jpg&quot; alt=&quot;로그인하기&quot; /&gt;</code></pre>
<p>위의 코드와 같이 반드시 이미지의 내용에 대한 설명을 추가해야 한다.</p>
<blockquote>
<p>가이드 라인 참조</p>
<p><a href="https://www.w3.org/WAI/guid-tech">W3C Accessibility Standards Overview</a></p>
</blockquote>
<h2 id="2-1-웹-콘텐츠-접근성-지침wcag">2-1. 웹 콘텐츠 접근성 지침(<code>WCAG</code>)</h2>
<h3 id="2-1-1-인지성-perceivable">2-1-1. 인지성 (<code>Perceivable</code>)</h3>
<blockquote>
<p>정보와 사용자 인터페이스 요소는 그들이 인지할 수 있도록 사용자에게 표시될 수 있어야 한다.</p>
</blockquote>
<ul>
<li><p>모든 텍스트가 아닌 콘텐츠에 대체 텍스트를 사람들이 원하는 인쇄, 점자, 음성, 기호 또는 간단한 언어 등과 같은 형태로 제공해야 한다.</p>
</li>
<li><p>시간을 바탕으로 한 미디어에 대한 대안을 제공해야 한다.</p>
</li>
<li><p>정보와 구조의 손실 없이 콘텐츠를 다른 방식(예를 들면 더욱 간단한 형태로)들로 표현할 수 있어야 한다.</p>
</li>
<li><p>사용자들이 보다 쉽게 보고 들을 수 있는 전경에서 배경을 분리한 콘텐츠를 만들어야 한다.</p>
</li>
</ul>
<h3 id="2-1-2-운용성-operable">2-1-2. 운용성 (<code>Operable</code>)</h3>
<blockquote>
<p>사용자 인터페이스 요소와 탐색은 운용이 가능해야 한다.</p>
</blockquote>
<ul>
<li><p>키보드로 모든 기능을 사용할 수 있도록 해야 한다.</p>
</li>
<li><p>읽기 및 콘텐츠를 사용하는 사용자에게 충분한 시간을 제공해야 한다.</p>
</li>
<li><p>알려진 방법으로 발작을 일으킬 수 있는 콘텐츠를 디자인하지 않아야 한다.</p>
</li>
<li><p>사용자가 탐색하고, 콘텐츠를 찾고 그들이 어디에 위치하고 있는지를 알 수 있도록 도와주는 방법을 제공해야 한다.</p>
</li>
</ul>
<h3 id="2-1-3-이해성-understandable">2-1-3. 이해성 (<code>Understandable</code>)</h3>
<blockquote>
<p>정보와 사용자 인터페이스 운용은 이해할 수 있어야 한다.</p>
</blockquote>
<ul>
<li><p>텍스트 콘텐츠를 판독하고 이해할 수 있도록 만들어야 한다.</p>
</li>
<li><p>웹 페이지의 탑재와 운용을 예측 가능한 방법으로 제작해야 한다.</p>
</li>
<li><p>사용자의 실수를 방지하고 수정할 수 있도록 도와야 한다.</p>
</li>
</ul>
<h3 id="2-1-4-내구성-robust">2-1-4. 내구성 (<code>Robust</code>)</h3>
<blockquote>
<p>콘텐츠는 보조 기술을 포함한 넓고 다양한 사용자 에이전트에 의존하여 해석될 수 있도록 충분히 내구성을 가져야 한다.</p>
</blockquote>
<ul>
<li>보조 기술을 포함한 현채 및 미래의 사용자 에이전트의 호환성을 극대화해야 한다.</li>
</ul>
<h2 id="2-2-웹-접근성을-위해-사용되는-보조기기">2-2. 웹 접근성을 위해 사용되는 보조기기</h2>
<ul>
<li><p>자막</p>
</li>
<li><p>스크린 리더</p>
</li>
<li><p>자동완성 기능</p>
</li>
<li><p>마우스 스틱</p>
</li>
<li><p>색상 대비 디자인 등</p>
</li>
</ul>
<hr>
<h1 id="3-관련-용어-정리">3. 관련 용어 정리</h1>
<ul>
<li><p><code>DTD(Document Type Definition)</code></p>
<ul>
<li>브라우저에 어떤 문서형 정의을 적용할 것인가를 선언하는 것</li>
</ul>
</li>
<li><p><code>Validator</code></p>
<ul>
<li>웹 문석가 표준안에 따라 만들어졌는지, 접근성에 대한 고려가 이루어졌는지에 대한 유효성을 검사해주는 도구</li>
</ul>
</li>
<li><p><code>Meta Data</code></p>
<ul>
<li>데이터를 위한 데이터로, 구조화된 정보를 분석/분류하고 부가적인 정보를 추가하기 위해 그 데이터와 함께 따라가는 정보</li>
</ul>
</li>
<li><p><code>Encoding</code></p>
<ul>
<li>문자들의 집합을 컴퓨터에서 저장하거나 통신에 사용할 목적으로 부호화하는 방법</li>
</ul>
</li>
<li><p><code>Semantic Web</code></p>
<ul>
<li>컴퓨터가 정보(웹 문서, 파일, 서비스 등) 사이에 연결되어 있는 의미를 컴퓨터가 이해하고 논리적인 추론까지 할 수 있는 지능형 웹</li>
</ul>
</li>
<li><p><code>Name Space</code></p>
<ul>
<li>서로 다른 <code>XML</code> 문서와 서로 인식할 수 있도록 태그로 나타내는 개념상의 공간</li>
</ul>
</li>
<li><p><code>MIME-TYPE (Multipurpose Internet Mail Extention Type)</code></p>
<ul>
<li>전송받은 멀티미디어 문서에 대해 클라이언트가 해당 <code>Data</code>를 어떻게 처리하는지 사전에 약속된 명칭</li>
</ul>
</li>
<li><p><code>Streaming</code></p>
<ul>
<li>인터넷에서 음성이나 영상, 애니메이션 등을 실시간으로 재생하는 기법</li>
</ul>
</li>
<li><p><code>Pointing Device</code></p>
<ul>
<li>컴퓨터 조작을 위해 표시 화면에 보이는 커서의 이동을 제어하는데 쓰이는 입력 장치</li>
</ul>
</li>
<li><p>서버측 이미지 맵</p>
<ul>
<li><code>img</code> 요소에 <code>ismap</code> 속성을 사용하고 링크 영역의 좌표 정보가 서버에 있으며, 마우스와 같은 포인팅 기기로만 사용할 수 있으며, 키보드로 접근은 불가능</li>
</ul>
</li>
<li><p>클라이언트측 이미지 맵</p>
<ul>
<li><p><code>img</code> 요소에 <code>usemap</code> 속성을 사용하고, 링크 영역의 좌표 정보가 <code>HTML</code>(클라이언트)에 존재하는 일반적으로 가장 많이 사용되는 이미지 맵</p>
<blockquote>
<p>클라이언트 측 이미지 맵의 경우 영역별로 대체 텍스트를 적절하게 제공해야 한다.</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://goddaehee.tistory.com/244">갓대희의 작은공간 - 웹표준의 이해(웹 표준이란?)</a>
<a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=weebee_&amp;logNo=220387422715">weebee design - 웹표준/웹접근성에 대한 요약</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] 주소창에 "www.google.com"을 친다면?]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90-www.google.com%EC%9D%84-%EC%B9%9C%EB%8B%A4%EB%A9%B4</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90-www.google.com%EC%9D%84-%EC%B9%9C%EB%8B%A4%EB%A9%B4</guid>
            <pubDate>Mon, 20 Feb 2023 15:41:37 GMT</pubDate>
            <description><![CDATA[<h1 id="1-웹의-기본적인-동작">1. 웹의 기본적인 동작</h1>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/e0c020ac-3b33-4516-8bc2-e3384874104b/image.png" alt=""></p>
<h2 id="1-1-웹의-동작-단계">1-1. 웹의 동작 단계</h2>
<p>위의 이미지를 참고하여 <code>www.google.com</code>을 입력했을 시, 어떻게 동작하는지 알아보면,</p>
<h3 id="1-1-1-사용자가-웹-브라우저-검색창에-wwwgooglecom-입력">1-1-1. 사용자가 웹 브라우저 검색창에 <code>www.google.com</code> 입력</h3>
<h3 id="1-1-2-웹-브라우저는-캐싱된-dns-기록들을-통해-해당-도메인-주소와-대응하는-ip-주소를-확인">1-1-2. 웹 브라우저는 캐싱된 <code>DNS</code> 기록들을 통해 해당 도메인 주소와 대응하는 <code>IP</code> 주소를 확인</h3>
<blockquote>
<p><code>DNS</code>란?</p>
<p><code>DNS (Domain Name System Servers)</code>는 <code>URL</code>들의 이름과 <code>IP</code> 주소를 저장하고 있는 데이터베이스로, 웹사이트를 위한 주소록이라고 볼 수 있다.</p>
<p>숫자로 된 <code>IP</code> 주소(ex. 63.245.217.105) 대신 사용자가 사용하기 편리하도록 주소를 매핑해주는 역할을 한다.</p>
</blockquote>
<ul>
<li>이 단계에서 캐싱된 기록이 없을 경우, 다음 단계로 넘어간다.</li>
</ul>
<h3 id="1-1-3-웹-브라우저가-http를-사용하여-dns에게-입력된-도메인-주소를-요청">1-1-3. 웹 브라우저가 <code>HTTP</code>를 사용하여 <code>DNS</code>에게 입력된 도메인 주소를 요청</h3>
<h3 id="1-1-4-dns가-웹-브라우저에게-찾는-사이트의-ip-주소를-응답">1-1-4. <code>DNS</code>가 웹 브라우저에게 찾는 사이트의 <code>IP</code> 주소를 응답</h3>
<ul>
<li><p><code>ISP(Internet Service Provider)</code>의 <code>DNS</code> 서버가 호스팅하고 있는 서버의 <code>IP</code> 주소를 찾기 위해 <code>DNS query</code>를 날린다.</p>
<blockquote>
<p><code>DNS query</code>의 목적</p>
<p><code>DNS</code> 서버들을 검색해서 해당 사이트의 <code>IP</code> 주소를 찾는데에 있다.</p>
<p><code>IP</code> 주소를 찾을 때까지 <code>DNS</code> 서버에서 다른 <code>DNS</code> 서버를 오가며 에러가 날때까지 반복적으로 검색한다. -&gt; <code>recursive search</code></p>
</blockquote>
</li>
<li><p><code>DNS recursor</code>(<code>ISP</code>의 <code>DNS</code> 서버)는 <code>name server</code>들에게 물어 물어 올바른 <code>IP</code> 주소를 찾는데에 책임이 있으며, <code>name server</code>는 도메인 이름 구조에 기반해서 주소를 검색하게 된다. (아래의 그림 참고)
  <img src="https://velog.velcdn.com/images/hyungjin_han/post/9b92da19-b776-401b-93cf-c06a2c36462d/image.png" alt=""></p>
<p>  정리하자면,</p>
<blockquote>
<p><code>www.google.com</code> 주소에 대해 검색할 때</p>
<ol>
<li><code>DNS recursor</code>가 <code>root name server</code>에 연락</li>
<li><code>.com</code> 도메인 <code>name server</code>로 리다이렉트</li>
<li><code>google.com name server</code>로 리다이렉트</li>
<li>최종적으로 <code>DNS</code> 기록에서 <code>www.google.com</code> 에 매칭되는 <code>IP</code> 주소 찾기</li>
<li>찾은 주소를 <code>DNS recursor</code>로 보내기</li>
</ol>
</blockquote>
<p>  위의 모든 요청들과 <code>DNS recursor</code>, <code>IP</code> 주소는 작은 데이터 패킷을 통해 보내지며, 원하는 <code>DNS</code> 기록을 가진 <code>DNS</code> 서버에 도달할 때까지 클라이언트와 서버를 여러번 오가는 과정을 거친다.</p>
</li>
</ul>
<h3 id="1-1-5-웹-브라우저가-웹-서버에게-ip-주소를-이용하여-html-문서를-요청">1-1-5. 웹 브라우저가 웹 서버에게 <code>IP</code> 주소를 이용하여 <code>html</code> 문서를 요청</h3>
<ul>
<li><p><code>TCP</code>로 연결이 되면, 브라우저는 <code>GET</code> 요청을 통해 서버에게 <code>www.google.com</code>의 웹 페이지를 요구한다.</p>
<blockquote>
<p><code>TCP/IP(Transmission Control Protocol / Internet Protocol)</code>란?</p>
<p>&#39;전송제어규약&#39;과 &#39;인터넷규약&#39;은 데이터가 어떻게 웹을 건너 여행하는지 정의하는 통신 규약이다.</p>
<p>이를 사용하겠다는 것은, <code>IP</code> 주소 체계를 따르며 <code>TCP</code>의 특성을 활용해 송신자와 수신자의 논리적 연결을 생성하고 신뢰성을 유지할 수 있도록 하겠다는 의미이다.</p>
<p>즉 송신자가 수신자에게 <code>IP</code> 주소를 사용해서 데이터를 전달하고 그 데이터가 제대로 갔는지에 대해 이야기하는 것이다.</p>
</blockquote>
</li>
</ul>
<h3 id="1-1-6-웹-애플리케이션-서버was와-데이터-베이스에서-우선-웹-페이지-작업을-처리">1-1-6. 웹 애플리케이션 서버(<code>WAS</code>)와 데이터 베이스에서 우선 웹 페이지 작업을 처리</h3>
<ul>
<li><p>웹 서버 혼자서 모든 로직을 수행하고 데이터를 관리할 수 있다면 간단하겠지만, 그렇게 될 경우엔 서버에 과부하가 일어날 수 있다.</p>
<p>그렇기 때문에 서버의 일을 돕는 조력자 역할을 하는 것이 웹 애플리케이션 서버(<code>Web Application Server</code>, <code>WAS</code>)이다.</p>
<blockquote>
<p><code>WAS</code>(<code>Web Application Server</code>)란?</p>
<p><code>WAS</code> 는 사용자의 컴퓨터나 장치에 웹 애플리케이션을 수행해주는 미들웨어를 말한다.</p>
<p>브라우저로부터 요청을 받으면, 웹 서버는 페이지의 로직이나 데이터 베이스(<code>DB</code>)의 연동을 위해 <code>WAS</code>에게 이들의 처리를 요청한다.</p>
<p>그러면 <code>WAS</code>는 이 요청을 받아 동적인 페이지 처리를 담당하고, <code>DB</code>에서 필요한 데이터 정보를 받아서 파일을 생성한다.</p>
<blockquote>
<p>웹 서버와 웹 애플리케이션 서버(<code>WAS</code>)의 차이점</p>
<ul>
<li>웹 서버</li>
</ul>
<p>정적인 콘텐츠(<code>HTML</code>, <code>CSS</code>, <code>Image</code> 등)를 요청받아 처리</p>
<ul>
<li>웹 애플리케이션 서버(<code>WAS</code>)</li>
</ul>
<p>동적인 컨텐츠(<code>JSP</code>, <code>ASP</code>, <code>PHP</code> 등)를 요청받아 처리</p>
<p><code>DB</code> 서버에 대한 접속 정보가 있기 때문에 외부에 노출 될 경우 보안상의 문제를 이유로 웹 서버와의 연결을 통해 요청을 전달받음</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/2e61e54a-f051-40a1-a217-b00fe3046627/image.png" alt=""></p>
</blockquote>
</blockquote>
</li>
</ul>
<h3 id="1-1-7-위의-작업처리-결과를-웹-서버로-전송">1-1-7. 위의 작업처리 결과를 웹 서버로 전송</h3>
<h3 id="1-1-8-웹-서버는-웹-브라우저에게-html-문서-결과를-응답">1-1-8. 웹 서버는 웹 브라우저에게 <code>HTML</code> 문서 결과를 응답</h3>
<ul>
<li><p><code>response</code>는 <code>status code</code>로 서버 요청에 따른 상태를 보내며, 총 5가지의 종류가 있다.</p>
<p>  <img src="https://velog.velcdn.com/images/hyungjin_han/post/b85e9ab0-aa5b-471d-b705-3eddbddd6f45/image.png" alt=""></p>
<blockquote>
<p><code>1xx</code> ▶️ 정보만 담긴 메세지
<code>2xx</code> ▶️ <code>response</code> 성공 (기분좋은 <code>200 OK</code> 해당)
<code>3xx</code> ▶️ 클라이언트를 다른 <code>URL</code>로 리다이렉트
<code>4xx</code> ▶️ 클라이언트 측에서 에러 발생 (자주보는 <code>404 Error</code> 해당)
<code>5xx</code> ▶️ 서버 측에서 에러 발생 (자주보는 <code>505 Error</code> 해당)</p>
</blockquote>
</li>
</ul>
<h3 id="1-1-9-웹-브라우저는-화면에-웹-페이지-내용물-출력">1-1-9. 웹 브라우저는 화면에 웹 페이지 내용물 출력</h3>
<hr>
<h1 id="2-웹의-동작-정리">2. 웹의 동작 정리</h1>
<blockquote>
<ol>
<li>사용자가 웹 브라우저 검색창에 <code>www.google.com</code> 입력</li>
</ol>
<ol start="2">
<li>웹 브라우저는 캐싱된 <code>DNS</code> 기록들을 통해 해당 도메인 주소와 대응하는 <code>IP</code> 주소를 확인</li>
</ol>
<ol start="3">
<li>웹 브라우저가 <code>HTTP</code>를 사용하여 <code>DNS</code>에게 입력된 도메인 주소를 요청</li>
</ol>
<ol start="4">
<li><code>DNS</code>가 웹 브라우저에게 찾는 사이트의 <code>IP</code> 주소를 응답</li>
</ol>
<ol start="5">
<li>웹 브라우저가 웹 서버에게 <code>IP</code> 주소를 이용하여 <code>html</code> 문서를 요청</li>
</ol>
<ol start="6">
<li>웹 애플리케이션 서버(<code>WAS</code>)와 데이터 베이스에서 우선 웹 페이지 작업을 처리</li>
</ol>
<ol start="7">
<li>위의 작업처리 결과를 웹 서버로 전송</li>
</ol>
<ol start="8">
<li>웹 서버는 웹 브라우저에게 <code>HTML</code> 문서 결과를 응답</li>
</ol>
<ol start="9">
<li>웹 브라우저는 화면에 웹 페이지 내용물 출력</li>
</ol>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/8be0204d-5e4b-4571-b3c9-f12af2965624/image.png" alt=""></p>
</blockquote>
<hr>
<h1 id="3-브라우저-렌더링-과정">3. 브라우저 렌더링 과정</h1>
<p><a href="https://velog.io/@hyungjin_han/JavaScript-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95"><img src="https://velog.velcdn.com/images/hyungjin_han/post/b830fa81-226b-4f5d-adde-22feeb78f9ff/image.png" alt=""></a></p>
<p align='center'>▲ 이미지 클릭으로 해당 포스트로 가기 ▲</p>

<br>

<p>이후로는 <u><strong><a href="https://velog.io/@hyungjin_han/JavaScript-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95">브라우저 렌더링 과정</a></strong></u>을 통해 사용자에게 <code>www.google.com</code> 주고에 맞는 화면을 출력하게 된다.</p>
<p>브라우저 렌더링 과정은 따로 포스팅한 내용을 추가적으로 읽어보며 공부할 예정이다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://velog.io/@eassy/www.google.com%EC%9D%84-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90%EC%84%9C-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC">eassy.log - &#39;www.google.com&#39;을 주소창에서 입력하면 일어나는 일</a>
<a href="https://velog.io/@tnehd1998/%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90-www.google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%96%88%EC%9D%84-%EB%95%8C-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EA%B3%BC%EC%A0%95">billy - 주소창에 www.google.com을 입력했을 때 일어나는 과정</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 스코프와 스코프 체인, 클로저란?]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%EC%8A%A4%EC%BD%94%ED%94%84%EC%B2%B4%EC%9D%B8-%ED%81%B4%EB%A1%9C%EC%A0%80%EB%9E%80</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%EC%8A%A4%EC%BD%94%ED%94%84%EC%B2%B4%EC%9D%B8-%ED%81%B4%EB%A1%9C%EC%A0%80%EB%9E%80</guid>
            <pubDate>Mon, 20 Feb 2023 07:34:23 GMT</pubDate>
            <description><![CDATA[<h1 id="1-scope-유효범위-스코프">1. <code>Scope</code> (유효범위, 스코프)</h1>
<blockquote>
<p>유효범위(<code>Scope</code>)는 <code>JavaScript</code> 뿐만 아니라 모든 프로그래밍 언어에서 가장 기본적인 개념 중 하나로 반드시 알고 넘어가야 한다.</p>
<p>하지만 <code>JavaScript</code>의 유효범위는 다른 언어의 유효범위와 다르다.</p>
</blockquote>
<p>프로그래밍 언어에서 유효범위는 어느 범위까지 참조하는 지를 뜻한다.</p>
<ul>
<li><p>전역 스코프 (<code>Global Scope</code>)</p>
<ul>
<li>스크립트 전체에서 참조되는 것을 의미하며, 어느 곳에서든 참조된다.</li>
</ul>
</li>
<li><p>지역 스코프 (<code>Local Scope</code>)</p>
<ul>
<li>정의된 함수 내에서만 참조되는 것을 의미하며, 밖에서는 참조되지 않는다.</li>
</ul>
</li>
</ul>
<h2 id="1-1-scope유효범위의-특징">1-1. <code>Scope</code>(유효범위)의 특징</h2>
<ul>
<li><p>함수 단위의 유효범위 (<code>function-level-scope</code>)</p>
</li>
<li><p>변수명 중복 허용</p>
</li>
<li><p>암묵적 선언 (<code>Implied Globals</code>)</p>
</li>
<li><p><code>Lexical Scoping</code> (<code>Static Scoping</code>)</p>
</li>
</ul>
<h3 id="1-1-1-function-level-scope">1-1-1. <code>function-level-scope</code></h3>
<p><code>function-level-scope</code>란?</p>
<p>함수 코드 블럭 내에서 선언된 변수는 함수 코드 블럭 내에서만 유효하고, 함수 외부에서는 유효하지 않다는 것이다.</p>
<pre><code class="language-js">var x = 0;

{
  var x = 1;
  console.log(x); // 1
}

console.log(x); // 1 - 결론적으로 var로 선언한 x가 값이 1로 변경

let y = 0;

{
  let y = 1;
  console.log(y); // 1
}

console.log(y); // 0 - 결론적으로 let로 선언한 y는 함수 내부에서만 1</code></pre>
<h3 id="1-1-2-변수명-중복-허용">1-1-2. 변수명 중복 허용</h3>
<p>클로벌 영역에 변수를 선언하면, 이 변수는 어느 곳에서든지 참조할 수 있는 <code>Global Scope</code> 를 갖는 전역 변수가 된다.</p>
<pre><code class="language-js">var global = &#39;global&#39;;

function foo() {
  var local = &#39;local&#39;;

  console.log(global); // global
  // Global 영역의 변수로 어디서든 사용 가능
  console.log(local); // local
}

foo();

console.log(global); // global
console.log(local); // Uncaught ReferenceError: local is not defined
// Local 영역의 변수로 함수 내에서만 사용 가능</code></pre>
<h3 id="1-1-3-암묵적-전역-implied-globals">1-1-3. 암묵적 전역 (<code>Implied Globals</code>)</h3>
<p>명시적으로 변수 앞에 <code>var</code>를 붙여주지 않으면 암묵적 전역 변수가 된다.</p>
<p>하지만 암묵적 전역은 오류를 발생시키는 원인이 될 가능성이 크기 때문에, 반드시 <code>var</code>, <code>let</code>, <code>const</code> 키워드를 사용하여 변수를 선언한 다음 사용해야 한다.</p>
<p>하지만 오타나 문법지식의 미비로 인한 실수는 언제나 발생할 수 있기 때문에, 이를 위해 <code>ES5</code> 부터 <code>Strict Mode</code>(엄격 모드)가 추가되었으며, <code>ES6</code>에서 도입된 클래스와 모듈은 기본적으로 <code>Strict Mode</code>가 적용된다.</p>
<blockquote>
<p><code>Strice Mode</code>(엄격 모드)란?</p>
<p><code>Strice Mode</code>(엄격 모드)는 <code>JavaScript</code> 언어의 문법을 좀 더 엄격히 적용하여 오류를 발생시킬 가능성이 높거나 자바스크립트 엔진의 최적화 작업에 문제가 될 수 있는 코드에 대해 명시적 에러를 발생시킨다.</p>
<blockquote>
<p><code>ESLint</code>와 같은 도구를 사용해도 <code>Strice Mode</code>와 유사한 효과를 얻을 수 있다.</p>
<p><code>ESLint</code> 도구는 정적 분석(<code>Static Analysis</code>)기능을 통해 소스코드를 실행하기 전에 소스코드를 스캔하여 문법적 오류만 아니라 잠재적 오류까지 찾아내고 오류의 원인을 리포팅해주는 유용한 도구다.</p>
<p><code>ESLint</code> 도구는 <code>Strice Mode</code>가 제한하는 오류는 물론 코딩 컨벤션을 설정 파일 형태로 정의하고 강제할 수 있기 때문에 더욱 강력한 효과를 얻을 수 있다.</p>
</blockquote>
</blockquote>
<pre><code class="language-js">function foo() {
  x = &#39;x&#39;; // ES6의 Strinc Mode 및 ESLint로 인해 오류 출력
  var y = &#39;y&#39;;
}

foo();

console.log(x); // x
console.log(y); // Uncaught ReferenceError: y is not defined
// Local 영역의 변수로 함수 내에서만 사용 가능</code></pre>
<h3 id="1-1-4-lexical-scoping-static-scoping">1-1-4. <code>Lexical Scoping</code> (<code>Static Scoping</code>)</h3>
<p><u><strong>자바스크립트는 함수가 선언된 시점에서의 유효범위를 갖는다.</strong></u></p>
<ul>
<li><p>예제 1</p>
<pre><code class="language-js">var number = 1234;

function printNumber() {
  console.log(number);
}

function wrapper() {
  number = 4321;
  // printNumber 함수를 실행시키기 전에 number를 변경했기 때문에 값이 변경됨
  printNumber();
}

wrapper(); // 4321</code></pre>
<blockquote>
<p><code>printNumber</code> 함수를 실행하기 직전에 <code>number</code> 의 값을 변경해주었으므로 <code>wrapper</code> 함수를 실행시켰을 때에 값이 변경되어, <code>1234</code>에서 <code>4321</code>가 출력된다.</p>
</blockquote>
</li>
<li><p>예제 2</p>
<pre><code class="language-js">var number = 1234;

function printNumber() {
  console.log(number);
}

function wrapper() {
  var number = 4321;
  console.log(number); // 4321
  printNumber();
}
wrapper(); // 1234</code></pre>
<blockquote>
<p><code>wrapper</code> 함수 안에서 <code>var</code> 키워드를 사용하게 되면 결과가 달라진다.</p>
<p>함수를 처음 선언하는 순간, 함수 내부의 변수는 자기 스코프로부터 가장 가까운 곳(상위 범위에서)있는 변수를 계속 참조하게 된다.</p>
<p>위에 예시에서는 <code>printNumber</code> 함수 안의 <code>number</code> 변수는 선언 시 가장 가까운 전역변수 <code>number</code>를 참조하게 된다.</p>
</blockquote>
</li>
</ul>
<hr>
<h1 id="2-스코프체인-scope-chain">2. 스코프체인 (<code>Scope Chain</code>)</h1>
<p>새롭게 정의된 스코프는 상위의 스코프에 접근할 수 있다.</p>
<p>스코프 체인은 <code>Scope</code>의 가장 내부에서 <code>Scope Chain</code>을 따라 바깥쪽으로 검색을 하게 된다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/e2554feb-23f7-4cc2-a485-b55b309aba3c/image.png" alt=""></p>
<hr>
<h1 id="3-클로저-closure">3. 클로저 (<code>Closure</code>)</h1>
<p>클로저는 함수가 선언된 환경의 (<code>Lexical</code>) 스코프를 기억하여, 함수가 스코프 밖에서 실행될 때에도 이 스코프에 접근할 수 있게 하는 기술이다.</p>
<pre><code class="language-js">const counter = () =&gt; {
  let count = 0;

  // changeCounter는 inner 함수
  // 객체를 리턴하고 있고, 객체 안에는 increase, decrease, show라는 inner 함수들을 저장
  function changeCount(number) {
    count += number;
  }

  return {
    increase: function () {
      changeCount(100);
    },
    decrease: function () {
      changeCount(-10);
    },
    show: function () {
      console.log(count);
    }
  }
};

const counterClosure = counter();
// counter를 실행하면, outer 함수 스코프를 기억하고 있는 클로저들이 담긴 객체를 반환
// counterClosure는 counter 함수 내부에 정의된 count나 changeCount에 접근 가능

counterClosure.increase();
counterClosure.show(); // 100

counterClosure.decrease();
counterClosure.show(); // 90</code></pre>
<blockquote>
<p>내부 함수는 외부 함수의 지역 변수에 접근 할 수 있는데, <u><strong>외부 함수의 실행이 끝나서 외부 함수가 소멸된 이후에도 내부 함수가 외부 함수의 변수에 접근할 수 있다.</strong></u></p>
<p>이러한 <u><strong>매커니즘을 클로저(<code>Closure</code>)</strong></u>라고 한다.</p>
</blockquote>
<h2 id="3-1-react-hook에서의-클로저closure">3-1. <code>React Hook</code>에서의 클로저(<code>Closure</code>)</h2>
<h3 id="3-1-1-usestate의-작동-방식">3-1-1. <code>useState</code>의 작동 방식</h3>
<p><code>React</code>에서 함수형 컴포넌트의 상태 관리를 위해서는 컴포넌트 외부에 저장된 값을 사용하며 클로저(<code>Closure</code>)를 통해 해당 값에 접근해서 상태를 비교하고 변경한다.</p>
<p><code>useState</code>는 컴포넌트 내부에서 값을 변경시키는 것이 아니라, 외부에 있는 값을 변경시키기 때문에 상태가 변경된 직후 컴포넌트가 가진 값은 이전의 값을 그대로 참조한다.</p>
<p>각 컴포넌트의 상태 정보는 배열 형태로 저장되기 때문에 상태를 변화시키는 <code>hook</code>을 조건문이나 반복문 안에서 사용하면 잘못된 순서의 값을 참조하게 될 수 있다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://velog.io/@aeong98/JS-%EC%8A%A4%EC%BD%94%ED%94%84Scope-%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80Closure%EC%9D%98-%EC%9D%B4%ED%95%B4">aeong98.log - 스코프(Scope) 와 클로저(Closure)의 이해</a>
<a href="https://eunhyejung.github.io/javascript/2021/09/08/JsStudy08.html">암묵적 전역(Implicit Global), Strict Mode</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] Cookie, Local Storage, Session Storage]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-Cookie-Local-Storage-Session-Storage</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-Cookie-Local-Storage-Session-Storage</guid>
            <pubDate>Mon, 20 Feb 2023 06:20:09 GMT</pubDate>
            <description><![CDATA[<h1 id="1-cookie와-web-storage의-생성">1. <code>Cookie</code>와 <code>Web Storage</code>의 생성</h1>
<blockquote>
<p><code>HTTP</code>는 요청과 응답으로 이뤄지는 하나의 사이클이 끝나면, 연결이 끊어지는 무상태성을 띄어서 클라이언트의 상태를 보존하지 않는다.</p>
<p>클라이언트의 상태를 서버가 아닌 클라이언트에 저장해두고 필요시마다 데이터를 꺼내서 서버에 전달하는 방식으로 <code>HTTP</code>의 단점을 보완하고자 쿠키와 웹 스토리지를 사용한다.</p>
</blockquote>
<hr>
<h1 id="2-cookie란">2. <code>Cookie</code>란?</h1>
<blockquote>
<p>만료 기간이 있는 클라이언트 단에서 저장하는 작은 텍스트 파일이다.</p>
<p>요청과 응답만이 존재했던 <code>HTTP</code> 웹에서 이전에 서버와 클라이언트가 주고 받은 내역을 기억하고 불러올 수 있는 역할을 수행하고 있다.</p>
</blockquote>
<ul>
<li><p>일시적으로 필요한 가벼운 데이터 저장이 필요한 경우 사용한다.</p>
<ul>
<li>다시 보지 않음 팝업창, 로그인 자동 완성 등에 사용</li>
</ul>
</li>
</ul>
<h2 id="2-1-cookie-종류">2-1. <code>Cookie</code> 종류</h2>
<ul>
<li><p><code>Session Cookie</code></p>
<ul>
<li>메모리에만 저장되며, 만료 시간이 있지만 브라우저 종료 시 삭제되는 쿠키이다.</li>
</ul>
</li>
<li><p><code>Persistent Cookie</code></p>
<ul>
<li>파일로 저장되며, <code>Max-Age</code> 설정을 통해 자기간 유지가 가능하고, 브라우저 종료와 관계없이 사용이 가능한 쿠키이다.</li>
</ul>
</li>
<li><p><code>Secure Cookie</code></p>
<ul>
<li><code>HTTPS</code>에서 사용되는 암호화된 쿠키로, 비교적 안전하지만 실질적 보안이 제공되지 않기 때문에 민감한 데이터 저장에는 위험한 쿠키이다.</li>
</ul>
</li>
<li><p><code>Third Party Cookie</code></p>
<ul>
<li>다른 도메인에 요청이 필요할 때 생성하는 쿠키로, 주로 광고 목적으로 사용되며, 유저 개인정보 악용의 문제가 발생할 수 있는 쿠키이다.</li>
</ul>
</li>
</ul>
<h2 id="2-2-cookie-동작-원리">2-2. <code>Cookie</code> 동작 원리</h2>
<ol>
<li><p>클라이언트가 서버에 <code>HTTP</code>를 요청한다.</p>
</li>
<li><p>서버가 <code>HTTP</code> 응답시, <code>set-cookie</code>를 통해 쿠키를 생성하여 전달한다.</p>
</li>
<li><p>클라이언트는 이때부터 매 <code>HTTP Request</code>시에 <code>HTTP Header</code>에 쿠키를 담아서 전송한다.</p>
</li>
<li><p>만료 기간 전이라면, 쿠키는 브라우저에 저장되어 있으며, 항상 요청 시에 사용이 가능하다.</p>
</li>
<li><p>만료되었다면, 클라이언트가 새로 서버에 요청하여 쿠키를 새로 발급받아야 한다.</p>
</li>
</ol>
<h2 id="2-3-cookie의-특징">2-3. <code>Cookie</code>의 특징</h2>
<h3 id="2-3-1-장점">2-3-1. 장점</h3>
<ul>
<li><p>대부분의 브라우저에서 지원한다.</p>
</li>
<li><p>데이터 유효기간을 지정할 수 있다. (1시간, 1일 등)</p>
</li>
<li><p><code>XSS</code>(사이트 간에 악성 <code>JavaScript</code> 코드를 심는 행위)로부터 안전하며, 서버에서 쿠키의 <code>httpOnly</code> 옵션을 설정하여 <code>JavaScript</code>에서 쿠키에 접근 자체를 막을 수 있다.</p>
</li>
</ul>
<h3 id="2-3-2-단점">2-3-2. 단점</h3>
<ul>
<li><p>저장 용량이 매우 작다. (<code>4kb</code>)</p>
</li>
<li><p>매번 서버에 <code>HTTP</code> 요청시에 같이 전달되어 서버에 부담을 줄 수 있다.</p>
</li>
<li><p>암호화가 안되어 있어서 유저 정보의 도난 위험이 있다.</p>
</li>
<li><p><code>CSRF</code>(사이트 간 요청 위조)의 위협에 취약하다.</p>
<blockquote>
<p><code>CSRF</code>(사이트 간 요청 위조)란?</p>
<p>공격자가 사용자의 요청을 가로챈 뒤 사용자의 의지와 상관없이 보안적으로 위험한 행동을 하게끔 변조하여 부당하게 이익을 취하는 행위</p>
</blockquote>
</li>
<li><p>문자열 데이터만 저장이 가능하다.</p>
</li>
</ul>
<hr>
<h1 id="3-web-storage란">3. <code>Web Storage</code>란?</h1>
<blockquote>
<p>클라이언트에 데이터를 저장할 수 있도록 <code>HTML5</code>부터 나온 새로운 방식의 데이터 저장소이다.</p>
<p><code>Local Storage</code>와 <code>Session Storage</code> 두 가지의 방식이 존재하며, <code>key</code>와 <code>value</code> 1쌍의 형태로 데이터를 저장한다.</p>
<p>또한 <code>window</code> 객체의 프로퍼티로써 존재한다.</p>
</blockquote>
<h2 id="3-1-local-storage-vs-session-storage">3-1. <code>Local Storage</code> VS <code>Session Storage</code></h2>
<h3 id="3-1-1-local-storage">3-1-1. <code>Local Storage</code></h3>
<blockquote>
<p><code>Local Storage</code>는 사용자의 로컬 환경에 데이터를 저장하는 방식으로, 영구적인 저장이 가능하다.</p>
</blockquote>
<ul>
<li><p>지속적으로 필요한 데이터 저장이 필요한 경우에 사용한다.</p>
<ul>
<li>자동 로그인 등에 사용</li>
</ul>
</li>
</ul>
<h3 id="3-1-2-session-storage">3-1-2. <code>Session Storage</code></h3>
<blockquote>
<p><code>Session Storage</code>는 브라우저 탭/윈도우 자체에 데이터를 저장하는 방식으로, 브라우저 탭/윈도우가 닫힐 경우, 스토리지가 초기화된다.</p>
</blockquote>
<ul>
<li><p>일시적으로 필요한 데이터 저장이 필요한 경우 사용한다.</p>
<ul>
<li>일회성 로그인, 입력 폼 저장, 비로그인 장바구니 등에 사용</li>
</ul>
</li>
</ul>
<h2 id="3-2-web-storage의-특징">3-2. <code>Web Storage</code>의 특징</h2>
<h3 id="3-2-1-장점">3-2-1. 장점</h3>
<ul>
<li><p>서버에 불필요하게 데이터 저장하지 않는다.</p>
</li>
<li><p>데이터의 저장 용량이 <code>Cookie</code>비해 크다</p>
<blockquote>
<p>모바일 : <code>2.5MB</code>
데스크탑 : <code>5~10MB</code></p>
</blockquote>
</li>
<li><p>문자열 외에도 <code>JavaScript</code>의 모든 원시형 데이터와 객체형 데이터를 저장할 수 있다.</p>
</li>
<li><p>도메인 단위로 접근이 제한되는 <code>CORS</code> 특성 덕분에 <code>CSRF</code>로부터 안전하다.</p>
</li>
</ul>
<h3 id="3-2-2-단점">3-2-2. 단점</h3>
<ul>
<li><p><code>HTML5</code>를 지원하는 브라우저만 사용이 가능하다.</p>
</li>
<li><p><code>Local Storage</code>에 접근하는 <code>JavaScript</code> 코드로 쉽게 접근 가능하며, <code>XSS</code>로부터 취약하다.</p>
</li>
</ul>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://velog.io/@hs0217/%EC%BF%A0%ED%82%A4-%EB%A1%9C%EC%BB%AC-%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80-%EC%84%B8%EC%85%98-%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80">hs.log - 쿠키, 로컬 스토리지, 세션 스토리지</a>
<a href="https://blog.loginradius.com/engineering/guest-post/local-storage-vs-session-storage-vs-cookies/">Login Radius Blog - Local Storage vs. Session Storage vs. Cookies</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] React의 불변성 관리]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-React%EC%9D%98-%EB%B6%88%EB%B3%80%EC%84%B1-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-React%EC%9D%98-%EB%B6%88%EB%B3%80%EC%84%B1-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Sun, 19 Feb 2023 15:22:58 GMT</pubDate>
            <description><![CDATA[<p><code>React</code>에서 배열이나 객체를 업데이트 해야 할 때에는 직접 수정하면 안되며, 반드시 불변성을 지켜주면서 업데이트를 해야 한다.</p>
<h1 id="1-불변성이란">1. 불변성이란?</h1>
<p>불변성이 프로그래밍에서 주목받는 이유는 변경 가능한 상태를 여러 곳에서 공유하게 됨으로써 발생하는 여러 가지 문제를 해결하기 위함이었다.</p>
<p>이런 문제는 멀티 스레딩과 같은 동시성 프로그래밍(동시에 값을 읽고 다른 동작을 할 때)을 사용할 때 많이 발생했는데 기존에는 락을 걸어놓고 락이 풀린 상태에만 스레드가 상태에 접근할 수 있도록 허가하는 방식을 주로 사용했었다.</p>
<p>즉, 불변성(<code>Immutability</code>)은 상태나 값을 변경하지 않는 것이다.</p>
<p><code>JavaScript</code>의 경우 원시 타입의 값들은 불변성을 갖고 있다.</p>
<pre><code class="language-javascript">let a = 0
a = 1
console.log(a);
// 결과 : 1</code></pre>
<p>위의 코드처럼 변수에 값을 재할당하면 <code>a</code>가 참조하고 있는 메모리의 값이 변경되는 것이 아니라 새로운 값인 <code>2</code>가 메모리에 새로 저장되고 그 주소 값이 <code>a</code>에 할당되는 방식으로 작동한다.</p>
<p>하지만, 원시 타입 값이 아닌 다른 참조형 값들(객체, 배열, 함수 등)은 다른 방식으로 작동한다.</p>
<pre><code class="language-javascript">const object = { a: 0 };
object.a = 1;
console.log(object);
// 결과 : { a: 1 }</code></pre>
<p>위의 코드에서 <code>object</code>의 내부 프로퍼티의 값을 변경했을 때 <code>object</code>에서 참조하고 있는 <code>a</code>값은 변경되지 않고 값이 변경된다.</p>
<p>단, <code>a</code>가 참조하고 있는 <code>1</code>의 주소 값은 변경된다.</p>
<p>이처럼 <code>JavaScript</code> 객체는 가변한며, <code>React</code>에서는 <code>JavaScript</code> 객체가 가변하기 때문에 문제가 된다.</p>
<hr>
<h1 id="2-react의-상태값-불변성의-필요">2. <code>React</code>의 상태값 불변성의 필요</h1>
<p><code>React</code>에서 상태값의 불변성을 유지해야 하는 이유는</p>
<ol>
<li><p>값이 변경됐는지 알기 위함</p>
</li>
<li><p>값을 수정하면, 이전 상태와 바뀐 상태값이 동일해져서 비교할 수 없음</p>
</li>
</ol>
<p>등이 있다.</p>
<p><code>React</code>에서는 상태가 변하면 컴포넌트가 리렌더링이 된다.</p>
<p><code>React</code>에서 리렌더링할 때 값 자체가 아니라 참조 값을 비교하므로 참조 값이 동일하면, 변경을 감지할 수 없게 된다.</p>
<p>또한, 값을 수정하면 이전 상태와 바뀐 상태값이 동일해지기 때문에, 이전 상태와 현재 상태를 비교하여 렌더링할 수 없게 된다.</p>
<p>불변 객체를 사용하지 않고 객체의 변화를 감지할 수 있지만, 효과적으로 객체의 변화를 감지할 수 있는 가장 좋은 방법은 불변 객체를 사용하는 것이다.</p>
<hr>
<h1 id="3-불변성을-유지하는-방법">3. 불변성을 유지하는 방법</h1>
<p><code>JavaScript</code>에서 객체를 불변하게 만드는 방법은 크게 3가지 정도가 있다.</p>
<ol>
<li><p>assign 메서드 사용</p>
</li>
<li><p>spread 연산자 사용</p>
</li>
<li><p><code>immer</code> 라이브러리 사용</p>
</li>
<li><p><code>MobX</code> 라이브러리를 통한 전역 상태 관리</p>
</li>
</ol>
<p>등이 있다.</p>
<h2 id="3-1-objectassign">3-1. <code>Object.assign()</code></h2>
<p><code>Object.assign</code> 메서드를 통해 불변성을 유지할 수 있다.</p>
<pre><code class="language-javascript">const object = { a: 0 };
object.a = 1;
console.log(object);
// 결과 : { a: 1 }

const cloneAssign = Object.assign({}, object, { b: 2 });
console.log(cloneAssign);
// 결과 : { a: 1, b: 2 }</code></pre>
<p><code>Object.assign()</code>은 매개 변수로 전달된 객체의 모든 속성을 첫 번째 매개 변수에 지정된 객체에 복사한다.</p>
<p>주의 사항으로는 <code>Object.assign()</code>은 속성의 값을 복사(얕은 복사)하기 때문에, 깊은 복사를 수행하려면 다른 방법을 사용해야 한다.</p>
<h2 id="3-2-spread-연산자">3-2. <code>Spread</code> 연산자</h2>
<p><code>Spread</code> 연산자를 이용하면, 객체 혹은 배열을 펼칠 수 있으며, 객체나 배열을 통채로 끌고와서 사용이 가능하다.</p>
<p>또한 기존의 것은 건들이지 않고 새로운 객체를 만들 때 사용한다. (기존 값의 불변성 유지)</p>
<pre><code class="language-js">const object = { a: 0 };
object.a = 1;
console.log(object);
// 결과 : { a: 1 }

const cloneAssign = Object.assign({}, object, { b: 2 });
console.log(cloneAssign);
// 결과 : { a: 1, b: 2 }

const cloneSpread = { ...object, ...cloneAssign, c: 3 };
console.log(cloneSpread);
// 결과 : { a: 1, b: 2, c: 3 }

const numberObject = { one: &#39;하나&#39;, two: &#39;둘&#39;, three: &#39;셋&#39; }
const { three, ...rest } = numberObject;
console.log(three);
// 결과 : 셋
console.log(rest);
// 결과 : { one: &#39;하나&#39;, two: &#39;둘&#39; } - rest 안에는 three 값을 제외한 값이 들어있음
console.log(numberObject);
// 결과 : { one: &#39;하나&#39;, two: &#39;둘&#39;, three: &#39;셋&#39; }</code></pre>
<h2 id="3-3-immer-라이브러리-사용">3-3. <code>immer</code> 라이브러리 사용</h2>
<p>위의 두 가지 방식을 사용하면 얕은 복사가 된다.</p>
<p>그러므로 객체 안의 객체가 있으면 그 안의 객체도 복사해 주어야 한다.</p>
<p>하지만 무분별하게 깊은 복사를 사용하는 것은 다음과 같은 이유로 문제가 될 수 있다.</p>
<ul>
<li><p>깊은 복사는 성능이 저하될 수 있다.</p>
</li>
<li><p>리액트에서 변경되지 않은 객체도 변경되었다고 감지하여 모든 것을 리렌더링할 수 있다.</p>
</li>
</ul>
<p>그러므로, 변경된 객체만 변경해주는 것이 좋다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/61de3884-07a3-49eb-8d97-6aee6ff11d1f/image.png" alt=""></p>
<p><a href="https://immerjs.github.io/immer/"><code>immer</code></a>와 같은 라이브러리를 사용하여 쉽게 불변성을 관리할 수 있다.</p>
<p><a href="https://immerjs.github.io/immer/performance">Immer performance</a> 문서를 보면, 변경된 객체만 복사하여 성능을 향상시킬 수 있다고 나와 있다.</p>
<blockquote>
<p>위의 3가지의 불변성을 유지한 프로그래밍의 경우 <u><strong>객체 지향 프로그래밍에 적합하지 않으며</strong></u>, <u><strong>불변성 유지를 위해 계속해서 노력하고 신경을 써야한다</strong></u>.</p>
</blockquote>
<h2 id="3-4-mobx-라이브러리를-통한-전역-상태-관리">3-4. <code>MobX</code> 라이브러리를 통한 전역 상태 관리</h2>
<blockquote>
<p><code>MobX</code>는 전역 상태 라이브러리로, 모든 상태 변화롤 일어나는 부분으로 자동으로 추적해주는 역할을 한다.</p>
</blockquote>
<p><code>MobX</code>는 다음과 같은 특징을 가지고 있다.</p>
<ol>
<li><p><code>React</code>에 종속적인 라이브러리가 아님</p>
</li>
<li><p>아키텍처나 상태 컨테이너가 아닌 라이브러리</p>
</li>
<li><p><code>Redux</code>와 다르게 <code>store</code>에 제한이 없음</p>
</li>
<li><p>또한 <code>Redux</code>에서 해줘야했던 <code>action</code> 선언, <code>connect</code>, <code>mapStateToProps</code>, <code>mapDispatchToProps</code> 등 번거로운 작업들은 데코레이터로 간단하게 대체</p>
</li>
<li><p><code>observable</code>을 기본적으로 사용하고 있음</p>
</li>
<li><p><code>Mobx</code>는 절대적으로 필요한 경우에만 <code>state</code> 변경</p>
</li>
<li><p><code>Typescript</code>를 기반으로 만들어짐</p>
</li>
<li><p><u><strong>객체 지향 프로그래밍에 적합</strong></u></p>
</li>
<li><p><u><strong>불변성을 신경쓰지 않아도 내부적으로 처리</strong></u></p>
</li>
</ol>
<p>후에 추가적으로 <code>MobX</code> 라이브러리에 대해 사용 및 정보 등을 포스팅할 예정이다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://bohyeon-n.github.io/deploy/react/react_immutable.html">구보현 블로그 - 리액트의 상태가 불변해야 하는 이유</a>
<a href="https://velog.io/@badahertz52/%EC%B0%B8%EC%A1%B0%ED%83%80%EC%9E%85%EA%B3%BC-React%EC%9D%98-%EB%B6%88%EB%B3%80%EC%84%B1">badahertz52.log - React의 불변성</a>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">MDN - Object.assign()</a>
<a href="https://hanamon.kr/javascript-spread-reat/">Spread / React 문법 (feat. 구조 분해 할당)</a>
<a href="https://immerjs.github.io/immer/">Immer - Introduction to Immer</a>
<a href="https://kyounghwan01.github.io/blog/React/mobx/basic/#mobx-%E1%84%8C%E1%85%AE%E1%84%8B%E1%85%AD-%E1%84%8B%E1%85%AD%E1%84%89%E1%85%A9">기억보다 기록을 - mobx 알아보기</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] HTTP? HTTPS?]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-HTTP-HTTPS</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-HTTP-HTTPS</guid>
            <pubDate>Sun, 19 Feb 2023 13:39:40 GMT</pubDate>
            <description><![CDATA[<h1 id="1-http">1. <code>HTTP</code></h1>
<p><code>Hyper Text Transfer Protocol</code>의 약자로 서버/클라이언트 모델을 따라 데이터를 주고 받기 위한 프로토콜이다.</p>
<p>즉, <code>HTTP</code>는 인터넷에서 하이퍼텍스트를 교환하기 위한 통신 규약으로, 80번 포트를 사용하고 있으며, 따라서 <code>HTTP</code> 서버가 80번 포트에서 요청을 기다리고 있으며, 클라이언트는 80번 포트로 요청을 보내게 된다.</p>
<blockquote>
<p><code>HTTP</code>의 역사</p>
<p><code>HTTP</code>는 1989년 팀 버너스 리(Tim Berners Lee)에 의해 처음 설계되었으며, <code>WWW(World-Wide-Web)</code> 기반에서 세계적인 정보를 공유하는데 큰 역할을 하였다.</p>
</blockquote>
<h2 id="1-1-http의-구조">1-1. <code>HTTP</code>의 구조</h2>
<p><code>HTTP</code>는 애플리케이션 레벨의 프로토콜로 <code>TCP/IP</code> 위에서 작동한다.</p>
<p><code>HTTP</code>는 상태를 가지고 있지 않는 <code>Stateless</code> 프로토콜이며 <code>Method</code>, <code>Path</code>, <code>Version</code>, <code>Headers</code>, <code>Body</code> 등으로 구성된다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/adaed690-fbc4-4caf-8c2b-100e9618d91f/image.png" alt=""></p>
<p>하지만 <code>HTTP</code>는 <u><strong>암호화가 되지 않은 평문 데이터를 전송하는 프로토콜</strong></u>이였기 때문에, <code>HTTP</code>로 비밀번호나 주민등록번호 등을 주고 받으면 제3자가 정보를 조회할 수 있었다.</p>
<p>그리고 이러한 문제를 해결하기 위해 <code>HTTPS</code>가 등장하게 되었다.</p>
<hr>
<h1 id="2-https">2. <code>HTTPS</code></h1>
<p><code>Hyper Text Transfer Protocol Secure</code>의 약자이며, <code>HTTPS(https://)</code>는 <code>SSL(Secure Socket Layer)</code> 인증서를 사용하는 <code>HTTP(http://)</code>이다.</p>
<p><code>HyperText Transfer Protocol over Secure Socket Layer</code>, <code>HTTP over TLS</code>, <code>HTTP over SSL</code>, <code>HTTP Secure</code> 등으로 불리며, <code>HTTPS</code>는 <code>HTTP</code>에 데이터 암호화가 추가된 프로토콜이다.</p>
<p><code>HTTPS</code>는 <code>HTTP</code>와 다르게 443번 포트를 사용하며, <u><strong>네트워크 상에서 중간에 제3자가 정보를 볼 수 없도록 암호화를 지원</strong></u>하고 있다.</p>
<h2 id="2-1-https의-동작-과정">2-1. <code>HTTPS</code>의 동작 과정</h2>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/4bc36149-a1a5-487a-967d-a916cc140115/image.png" alt=""></p>
<p><code>HTTPS</code>는 대칭키 암호화와 비대칭키 암호화를 모두 사용하여 빠른 연산 속도와 안정성을 모두 얻고 있다.</p>
<p><code>HTTPS</code> 연결 과정(<code>Hand-Shaking</code>)에서는 먼저 서버와 클라이언트 간에 세션키를 교환한다.</p>
<p>여기서 세션키는 주고 받는 데이터를 암호화하기 위해 사용되는 대칭키이며, 데이터 간의 교환에는 빠른 연산 속도가 필요하므로 세션키는 대칭키로 만들어진다.</p>
<p>문제는 이 세션키를 클라이언트와 서버가 어떻게 교환할 것이냐 인데, 이 과정에서 비대칭키가 사용된다.</p>
<p>즉, 처음 연결을 성립하여 안전하게 세션키를 공유하는 과정에서 비대칭키가 사용되는 것이고, 이후에 데이터를 교환하는 과정에서 빠른 연산 속도를 위해 대칭키가 사용되는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/5e0154df-70e4-4661-997e-43a093f67d54/image.png" alt=""></p>
<p>위의 그림을 통해 실제 <code>HTTPS</code> 연결 과정이 성립되는 흐름을 살펴보면 다음과 같다.</p>
<ol>
<li><p>클라이언트(브라우저)가 서버로 최초 연결 시도를 함</p>
</li>
<li><p>서버는 공개키(엄밀히는 인증서)를 브라우저에게 넘겨줌</p>
</li>
<li><p>브라우저는 인증서의 유효성을 검사하고 세션키를 발급함</p>
</li>
<li><p>브라우저는 세션키를 보관하며 추가로 서버의 공개키로 세션키를 암호화하여 서버로 전송함</p>
</li>
<li><p>서버는 개인키로 암호화된 세션키를 복호화하여 세션키를 얻음</p>
</li>
<li><p>클라이언트와 서버는 동일한 세션키를 공유하므로 데이터를 전달할 때 세션키로 암호화/복호화를 진행함</p>
</li>
</ol>
<h3 id="2-1-1-대칭키-암호화와-비대칭키-암호화">2-1-1. 대칭키 암호화와 비대칭키 암호화</h3>
<blockquote>
<p>HTTPS는 대칭키 암호화 방식과 비대칭키 암호화 방식을 모두 사용하고 있다.</p>
<p>각각의 암호화 방식은 다음과 같다.</p>
</blockquote>
<ul>
<li><p>대칭키 암호화</p>
<ul>
<li><p>클라이언트와 서버가 동일한 키를 사용해 암호화/복호화를 진행함</p>
</li>
<li><p>키가 노출되면 매우 위험하지만 연산 속도가 빠름</p>
</li>
</ul>
</li>
<li><p>비대칭키 암호화</p>
<ul>
<li><p>1개의 쌍으로 구성된 공개키와 개인키를 암호화/복호화를 하는데 사용함</p>
</li>
<li><p>키가 노출되어도 비교적 안전하지만, 연산 속도가 느림</p>
<blockquote>
<p> <u><strong>공개키</strong></u></p>
<p>모두에게 공개가능한 키이다.</p>
<p>공개키 암호화를 하면 개인키로만 복호화할 수 있다.
개인키는 나만 가지고 있으므로, 자신만 볼 수 있다.</p>
</blockquote>
<blockquote>
<p> <u><strong>개인키</strong></u></p>
<p>자신만 가지고 알고 있어야 하는 키.</p>
<p>개인키로 암호화하면 공개키로만 복호화할 수 있다.
공개키는 모두에게 공개되어 있으므로, 자신이 인증한 정보임을 알려 신뢰성을 보장할 수 있다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/7571b12a-9e9f-468e-ae6b-f2415181c648/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<h2 id="2-2-https의-발급-과정">2-2. <code>HTTPS</code>의 발급 과정</h2>
<p>위의 과정에서 추가로 살펴봐야 할 부분은 서버가 비대칭키를 발급받는 과정이다.</p>
<p>서버는 클라이언트와 세션키를 공유하기 위한 공개키를 생성해야 하는데, 일반적으로는 인증된 기관(<code>Certificate Authority</code>)에 공개키를 전송하여 인증서를 발급받는다.</p>
<p>자세한 과정은 다음과 같다.</p>
<blockquote>
<p><code>A</code> : <code>Authority</code>
<code>CA</code> : <code>Certification Authority</code></p>
</blockquote>
<ol>
<li><p><code>A</code> 기업은 <code>HTTP</code> 기반의 앱에 <code>HTTPS</code>를 적용하기 위해 공개키/개인키를 발급</p>
</li>
<li><p><code>A</code> 기업은 <code>CA</code> 기업에게 돈을 지불하고, 공개키를 저장하는 인증서 발급 요청</p>
</li>
<li><p><code>CA</code> 기업은 <code>CA</code> 기업의 이름, 서버의 공개키, 서버의 정보 등을 기반으로 인증서를 생성</p>
</li>
<li><p><code>CA</code> 기업의 개인키로 암호화 후, <code>A</code> 기업에게 이를 제공</p>
</li>
<li><p><code>A</code> 기업은 클라이언트에게 암호화된 인증서 제공</p>
</li>
<li><p>브라우저는 <code>CA</code> 기업의 공개키를 미리 다운받아 갖고 있어, 암호화된 인증서를 복호화</p>
</li>
<li><p>암호화된 인증서를 복호화하여 얻은 <code>A</code> 기업의 공개키로 세션키를 공유</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/9e902f08-f816-410a-ad37-58c6183ff26e/image.png" alt=""></p>
</li>
</ol>
<p>인증서는 <code>CA</code> 기업의 개인키로 암호화되었기 때문에 신뢰성을 확보할 수 있고, 클라이언트는 <code>A</code> 기업의 공개키로 데이터를 암호화하였기 때문에 <code>A</code> 기업만 복호화하여 원본의 데이터를 얻을 수 있다.</p>
<p>여기서 인증서에는 <code>A</code> 기업의 공개키가 포함되어 있으므로, <code>A</code> 기업의 공개키라고 봐도 무방하다.</p>
<p>또한 브라우저에는 인증된 <code>CA</code> 기관의 정보들이 사전에 등록되어 있어 인증된 <code>CA</code> 기관의 인증서가 아닐 경우에는 다음과 같은 형태로 브라우저에서 보여지게 된다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/64ec9ae9-08e9-4640-9e12-7b4a4ee2bc98/image.png" alt=""></p>
<hr>
<h1 id="3-http와-https">3. <code>HTTP</code>와 <code>HTTPS</code></h1>
<p><code>HTTP</code>는 암호화가 추가되지 않았기 때문에 보안에 취약한 반면, <code>HTTPS</code>는 안전하게 데이터를 주고받을 수 있다.</p>
<p>하지만 <code>HTTPS</code>를 이용하면 암호화/복호화의 과정이 필요하기 때문에 <code>HTTP</code>보다 속도가 느리다. </p>
<blockquote>
<p>물론 오늘날에는 거의 차이를 못느낄 정도이다.</p>
</blockquote>
<p>또한 <code>HTTPS</code>는 인증서를 발급하고 유지하기 위한 추가 비용이 발생한다.</p>
<h2 id="3-1-언제-어떤걸-써야하나">3-1. 언제, 어떤걸 써야하나?</h2>
<h3 id="3-1-1-http-사용">3-1-1. <code>HTTP</code> 사용</h3>
<p>노출이 되어도 괜찮은 단순한 정보 조회 등만을 처리하고 있다면 <code>HTTP</code>를 이용하면 된다.</p>
<p>또한 <code>HTTPS</code>의 추가 비용 발생으로 인해, 간단한 프로젝트 진행의 경우, <code>http://localhost:3000/</code>과 같은 주소로 프로젝트 개발을 진행한다.</p>
<h3 id="3-1-2-https-사용">3-1-2. <code>HTTPS</code> 사용</h3>
<p>개인 정보와 같은 민감한 데이터를 주고 받아야 한다면 <code>HTTPS</code>를 이용해야 한다.</p>
<p>사실상, 어플리케이션을 개발하여 사용자를 유치하고 서비스를 진행하기 위해서는 <code>HTTPS</code> 방식을 채택해야 한다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://mangkyu.tistory.com/98">망나니개발자 - HTTP와 HTTPS의 개념 및 차이점</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] CORS란?]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-CORS%EB%9E%80</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-CORS%EB%9E%80</guid>
            <pubDate>Fri, 17 Feb 2023 07:26:01 GMT</pubDate>
            <description><![CDATA[<h1 id="1-cors의-정의">1. <code>CORS</code>의 정의</h1>
<p>교차 출처 리소스 공유(<code>Cross-Origin Resource Sharing</code>, <code>CORS</code>)는 브라우저가 추가 <code>HTTP</code> 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.</p>
<p>쉽게 정리하자면, 사용자가 지금 접속한 사이트와 다른 출처의 릴소스를 사용하려 할 때, 브라우저가 참고하는 화이트 리스트라고 할 수 있다.</p>
<p>만약, 이 리스트에 없다면 콘솔 창에 빨갛게 <code>CORS</code> 에러를 마주하게 된다.</p>
<hr>
<h1 id="2-sop란">2. <code>SOP</code>란?</h1>
<p>동일 출처 정책(<code>Same-Origin Policy</code>)은 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식으로, 동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리함으로써 공격받을 수 있는 경로를 줄여준다.</p>
<h2 id="2-1-동일-출처란">2-1. 동일 출처란?</h2>
<p>프로토콜 / 호스트 / 포트 3가지가 모두 동일하면 동일 출처라고 할 수 있다.</p>
<table>
<thead>
<tr>
<th><code>URL</code></th>
<th>동일 출처 여부</th>
</tr>
</thead>
<tbody><tr>
<td><a href="http://hhj.blog.com/dir/other">http://hhj.blog.com/dir/other</a></td>
<td>기본 <code>URL</code></td>
</tr>
<tr>
<td><a href="http://hhj.blog.com/dir3/other1">http://hhj.blog.com/dir3/other1</a></td>
<td>동일 출처 ⭕ - 경로만 다름</td>
</tr>
<tr>
<td><a href="https://hhj.blog.com/dir/other">https://hhj.blog.com/dir/other</a></td>
<td>동일 출처 ❌ - 프로토콜(<code>https</code>)이 다름</td>
</tr>
<tr>
<td><a href="http://hhj.blog.com:81/dir/other">http://hhj.blog.com:81/dir/other</a></td>
<td>동일 출처 ❌ - 포트가 다름 (기본 <code>http://</code> 는 80, <code>https://</code> 는 443)</td>
</tr>
<tr>
<td><a href="http://jhh.blog.com/dir/other">http://jhh.blog.com/dir/other</a></td>
<td>동일 출처 ❌ - 호스트(<code>jhh</code>)가 다름</td>
</tr>
</tbody></table>
<p>동일 출처가 아닌데 <code>ajax</code> 요청을 보내면 <code>CORS error</code>를 만나게 되며, 즉, 동일 출처가 아닐 때 요청을 막는 것은 <code>SOP</code>이고, 요청이 가능하도록 하는 것이 <code>CORS</code>이다.</p>
<h2 id="2-2-왜-동일-출처-정책이-필요한가">2-2. 왜 동일 출처 정책이 필요한가?</h2>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/2c335263-12a4-49bf-a9b9-e5fe2e9612d7/image.png" alt=""></p>
<p>위의 그림을 통해 예시를 들자면,</p>
<ol>
<li><p>유저가 어떤사이트에 접속하고 로그인을 하면, 브라우저의 토큰 등의 로그인 정보가 쿠키에 저장된다.</p>
</li>
<li><p>이때 로그인 했던 사이트에 접속할때 쿠키를 요청에 같에 보내어 로그인되었다고 판단한다.</p>
</li>
<li><p>즉, 인증 정보가 브라우저의 쿠키, 세션등의 스토리지에 저장되어 있고 이를 특정 요청에 같이 실어 보내어 인증을 진행하는 것이다.</p>
</li>
<li><p>만일 악의적인 사이트가 있다면 해당 사이트 접속시 <code>JavaScript</code> 코드가 유저의 브라우저에 다운로드되게 된다.</p>
</li>
<li><p>악의적인 사이트의 <code>JavaScript</code> 코드가 유저의 브라우저에 저장된 쿠키나 세션등에 접근할 수 있다.</p>
</li>
<li><p>이를 이용해 유저의 인증정보를 이용해 정보를 탈취할 수 있게된다.</p>
</li>
</ol>
<blockquote>
<p>원래 보안을 위해 다른 출처의 리소스를 접근하는 것이 불가능했지만, 웹 생태계가 다양해지면서 여러 서비스들끼리 자유롭게 데이터가 주고 받아질 필요가 생겼다.</p>
<p>그런데, 다른 사이트 간의 요청들을 브라우저가 막고 있기 때문에 이를 허용해주기 위해 어떠한 기준을 충족시키면 리소스를 공유할 수 있도록 만들어진 체제가 바로 <code>CORS</code>다.</p>
</blockquote>
<hr>
<h1 id="3-cors의-동작원리">3. CORS의 동작원리</h1>
<p><code>CORS</code> 동작의 시나리오는 다음 2가지로 나뉜다.</p>
<h2 id="3-1-simple-request">3-1. <code>Simple Request</code></h2>
<blockquote>
<p>예비 요청을 보내지 않고, 서버에게 바로 본 요청을 전송한다.</p>
<p>이 후 서버가 응답 헤더에 <code>Access-Control-Allow-Origin</code>과 같은 값을 보내주면 그때 브라우저가 CORS 정책 위반 여부를 검사하는 방식이다.</p>
<p><code>GET</code>이나 <code>POST</code> 등 일정 조건에 요청들에 대해 사용된다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/3f5de617-9590-4f05-b4a5-46d0fb269d9c/image.png" alt=""></p>
<ol>
<li><p>기본적으로 웹은 다른 출처의 리소스를 요청할 때는 <code>HTTP</code> 프로토콜을 사용하여 요청을 하는데, 이때 브라우저는 요청 헤더에 <code>Origin</code> 필드에 요청을 보내는 출처를 담아 전송한다.</p>
</li>
<li><p>서버는 요청에 대한 응답을 하는데, 응답 헤더에 <code>Access-Control-Allow-Origin</code>이라는 항목에 이 리소스를 접근하는 것이 허용된 출처를 명시해준다.</p>
<blockquote>
<p><code>Access-Control-Allow-Origin: *</code> 처럼 와일드카드(<code>*</code>)를 사용하면 모든 <code>origin</code> 요청을 허용하는게 된다.</p>
</blockquote>
</li>
<li><p>이후, 응답을 받은 브라우저는 자신이 보냈던 요청의 <code>Origin</code>과 서버가 보내준 응답의 <code>Access-Control-Allow-Origin</code>을 비교한 후 이 응답 가능 여부를 결정한다.</p>
</li>
</ol>
<p>요청 시 <code>header</code>의 <code>origin</code> 항목에 <code>URL</code>(프로토콜/호스트/포트) 정보가 담겨있고, 응답 header에 Access-Control-Allow-Origin 항목에 요청시 <code>origin</code> 항목의 URL 정보가 있다면 브라우저는 응답을 받아오게 되고 없다면, 거부하게되며 <code>CORS error</code>가 나타나게 된다.</p>
<p>이러한 에러를 해결할 수 있도록, <code>Spring</code>이나 <code>Django</code>, <code>Express</code> 등의 문서에 <code>CORS</code> 옵션 설정하는 방법이 잘 나와있다.</p>
<h2 id="3-2-preflight-request">3-2. <code>Preflight Request</code></h2>
<blockquote>
<p>요청을 한번에 보내는 것이 아닌 예비 요청과 본 요청으로 나누어서 서버로 전송한다.</p>
<p>본 요청을 보내기 전 미리 예비로 보내는 요청을 <code>Preflight</code>라고 하며, <code>HTTP</code> 메서드 중 <code>OPTIONS</code> 메서드를 사용한다.</p>
<p>서버는 예비 요청에 대한 응답으로, 어떤 요청을 허용하고 또 금지하는지에 대한 정보를 응답 헤더에 담아 보낸다.</p>
<p>예비 요청으로 본 요청이 안전한지 확인한 다음에야 본격적으로 요청을 보낼 수 있다.</p>
<p><code>PUT</code>이나 <code>DELETE</code> 등 서버 데이터에 영향을 줄 수 있는 요청들이기 때문에 먼저 요청의 허용 여부를 검증하는 것이다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/8058a165-f3c1-4cd6-92aa-e227f9f0fad7/image.png" alt=""></p>
<p>만약, 토큰 등 사용자 식별 정보가 담긴 요청에 대해서는 보다 엄격하다.</p>
<p>요청 옵션에 <code>crendentials</code> 항목을 <code>true</code>로 세팅해야 하고, 서버에서도 모든 출처를 허용하는 와일드카드 (<code>*</code>)가 아닌 요청 웹페이지의 주소를 정확히 명시한 다음 <code>Access-Control-Allow-Credentials</code> 항목을 <code>true</code>로 설정해주어야 한다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://velog.io/@gwanuuoo/CORS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80">gwanuuoo.log - CORS란 무엇인가?</a>
<a href="https://velog.io/@hinyc/CORS-%EC%89%BD%EA%B2%8C-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90">hinyc.log - CORS ? 쉽게 알아보자</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] 소프트웨어 개발 방법론]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%EB%B0%A9%EB%B2%95%EB%A1%A0</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-%EB%B0%A9%EB%B2%95%EB%A1%A0</guid>
            <pubDate>Thu, 16 Feb 2023 06:15:36 GMT</pubDate>
            <description><![CDATA[<h1 id="1-소프트웨어-개발-방법론의-정의">1. 소프트웨어 개발 방법론의 정의</h1>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/451b5b8e-4989-4b0e-9a8b-51c821e4b688/image.png" alt=""></p>
<p>소프트웨어 개발 방법론은 소프트웨어를 어떻게 만들지에 대한 관심을 가지게 된다.</p>
<p>따라서 개발 방법론에는 단계별 산출물뿐만 아니라 산출물을 누가 어떤 순서로 어떻게 만들어야 하는지, 그리고 어떤 도구를 사용해야 하는지를 구체적으로 정의하고 있다.</p>
<hr>
<h1 id="2-소프트웨어-개발-방법론의-종류">2. 소프트웨어 개발 방법론의 종류</h1>
<p>소프트웨어의 개발 방법론은 크게 5가지로 나뉘며,</p>
<ol>
<li><p>구조적 개발 방법론</p>
</li>
<li><p>정보공학 개발 방법론</p>
</li>
<li><p>객체지향 개발 방법론</p>
</li>
<li><p>컴포넌트 기반(<code>CBD</code>) 개발 방법론</p>
</li>
<li><p>애자일, 폭포수 모델, 프로토타입 개발 방법론</p>
</li>
</ol>
<p>등이 있다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/384878c5-44f8-4e3a-8f7e-9a2c729bed7e/image.png" alt=""></p>
<hr>
<h1 id="3-구조적-개발-방법론">3. 구조적 개발 방법론</h1>
<blockquote>
<p>구조적 방법론은 구조, 흐름, 간결, 간단 이 구조적 개발 방법의 특징이다.</p>
<p><strong>요구사항 분석 -&gt; 구조적 분석 -&gt; 구조적 설계 -&gt; 구조적 프로그래밍</strong> 순서로 이루어져 있다.</p>
</blockquote>
<h2 id="3-1-구조적-개발-방법론의-특징">3-1. 구조적 개발 방법론의 특징</h2>
<h3 id="3-1-1-구조적-개발-방법론의-단계">3-1-1. 구조적 개발 방법론의 단계</h3>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/ef41029a-e8ed-4b48-9825-8a8030112027/image.png" alt=""></p>
<p>위의 그림을 참고하면,</p>
<ol>
<li><p>요구사항 분석 단계</p>
<ul>
<li><p>데이터, 시스템 환경, 사용자 요구기능 등을 분석하는 단계이다.</p>
</li>
<li><p>고객이 원하는 요구사항을 끌어내 명세화한다.</p>
</li>
</ul>
</li>
<li><p>구조적 분석 단계</p>
<ul>
<li><p><code>DFD</code> , <code>DD</code>, <code>Minispec</code> 등을 작성하고 <code>DB</code>를 분석하는 단계이다.</p>
</li>
<li><p>고객이 원하는 기능/시스템 환경/데이터를 종합하여 데이터 흐름도(<code>DFD</code>)를 작성한다.</p>
<blockquote>
<p>데이터 흐름도(<code>DFD</code>, <code>Data Flow Diagram</code>)란?
데이터 흐름도는 유구사항 분석에서 데이터의 흐름 및 변환 과정과 기능을 도형 중심으로 기술하는 방법으로 데이터 흐름 그래프, 버블 차트라고도 하며, 데이터 흐름과 기능을 자세히 표현하기 위해 단계적으로 세분화된다.</p>
</blockquote>
<blockquote>
<p>데이터 사전(<code>DD</code>, <code>Data Dictionary</code>)이란?
  데이터 사전은 데이터 흐름도에 있는 자료를 더 자세히 정의하고 기록한 것으로, 이처럼 데이터를 설명하는 데이터를 데이터의 데이터 또는 메타 데이터(<code>Meta Data</code>)라고 한다.</p>
</blockquote>
<blockquote>
<p>소단위 명세서(<code>Minispec</code>)란?
  소단위 명세서는 세분화된 데이터 흐름도에서 최하위 단계 버블(프로세스)의 처리 절차를 기술한 것으로 프로세스 명세서라고도 하며, 분석가의 문서이며 데이터 프름도(<code>DFD</code>)를 지원하기 위해 작성한다.</p>
</blockquote>
</li>
</ul>
</li>
<li><p>구조적 설계 단계</p>
<ul>
<li><p>구조적 분석 단계에서의 <code>DB</code> 분석을 통해 <code>DB</code> 설계 및 어플리케이션을 설계하는 단계이다.</p>
</li>
<li><p>모듈 중심으로 설계를 진행하며, 재활용 가능하도록, 결합도를 낮춰서 독립성을 높이기 위한 목적으로 진행한다.</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li><p>구조적 프로그래밍 단계</p>
<ul>
<li><p>위의 3단계의 논리적인 구조를 통해 실질적인 프로그래밍을 진행하는 단계이다.</p>
</li>
<li><p>순차, 선택, 반복의 논리 구조 구성으로 프로그램 복잡성을 최소화한다.</p>
</li>
</ul>
</li>
</ol>
<h2 id="3-2-구조적-개발-방법론의-장단점">3-2. 구조적 개발 방법론의 장/단점</h2>
<h3 id="3-2-1-구조적-개발-방법론의-장점">3-2-1. 구조적 개발 방법론의 장점</h3>
<ul>
<li><p>명확한 요구사항을 추출하여 설계에 반영이 가능하며, 정형화/체계화가 가능하다.</p>
</li>
<li><p>효율적인 재사용 및 유지보수가 용이한 모듈화가 가능하다.</p>
</li>
</ul>
<h3 id="3-2-2-구조적-개발-방법론의-단점">3-2-2. 구조적 개발 방법론의 단점</h3>
<ul>
<li><p>거시적 관점의 인식이 부족하며, 방법론에 대한 다양한 시도를 하고 있지 않다는 뜻으로 프로젝트에서만 사용하는 추세이다.</p>
</li>
<li><p>실제 사례를 기반으로 하는 자료 부족으로 데이터 모델링 방법과 명확한 방법론적 지침이 미흡하다.</p>
</li>
<li><p>유지보수성 및 재사용성이 낮기 때문에 기능이 불완전하고 자주 변한다.</p>
</li>
</ul>
<hr>
<h1 id="4-정보공학-개발-방법론">4. 정보공학 개발 방법론</h1>
<blockquote>
<p>정보공학 개발 방법론은 비지니스 시스템 규모 성장과 소프트웨어 공학 발전에 따라 1980년대 중반에 등장한 방법론이다.</p>
<p>기업 전체 또는 기업의 주요 부분을 계획, 분석, 설계 및 구축에 정형화된 기법들을 상호 연관성있게 통합, 적용하는 데이터 중심 방법론이다.</p>
</blockquote>
<h2 id="4-1-정보공학-개발-방법론의-특징">4-1. 정보공학 개발 방법론의 특징</h2>
<h3 id="4-1-1-정보공학-개발-방법론의-단계">4-1-1. 정보공학 개발 방법론의 단계</h3>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/b1875c48-cbe2-434f-885e-d0958f3ae744/image.png" alt=""></p>
<p>위의 그림을 참고하면,</p>
<ol>
<li><p>정보 전략 계획 수립 단계 (<code>ISP</code>, <code>Information Strategy Planning</code>)</p>
<ul>
<li><p>기업의 경영 전략을 뒷받침할 수 있는 정보화 전략을 수립하기 위해 현행 업무 프로세스와 시스템을 분석하고 미래 아키텍처와 전략 계획을 수립하는 단계이다.</p>
</li>
<li><p>경영 전략, 관련 조직, 업무 자료를 거시적으로 분석하며, 현행 시스템을 평가한다.</p>
</li>
</ul>
</li>
<li><p>업무영역 분석단계(<code>BAA</code>, <code>Business Area Analysis</code>)</p>
<ul>
<li><p>기업의 업무 현황을 분석해서 개념 수준의 데이터와 프로세스를 설계하는 업무 분석 단계이다.</p>
</li>
<li><p><code>ERD</code>를 통해 데이터 모델링을 진행하며, 프로세스 계층도(<code>PHD</code>), 프로세스 의존도(<code>PDD</code>), 데이터 흐름도(<code>DFD</code>) 등의 프로세스 모델링을 진행한다.</p>
</li>
</ul>
</li>
<li><p>업무 시스템 설계단계(<code>BSD</code>, <code>Business System Design</code>)</p>
<ul>
<li>실질적으로 시스템을 설계하는 단계로 우리가 많이 사용하고 있는 논리적 <code>ER</code> 다이어그램으로 데이터를 설계하고 분할 다이어그램, 액션 다이어그램, 의존 다이어그램을 사용해 프로세스를 설계한다.</li>
</ul>
</li>
<li><p>시스템 구축단계(<code>SC</code> ,<code>System Construction</code>)</p>
<ul>
<li>확정된 설계 명세서로부터 데이터 베이스 생성기와 프로그램 코드 생성기를 이용해 데이터 베이스와 실행 가능한 프로그램 코드를 생성한다.</li>
</ul>
</li>
</ol>
<h3 id="4-1-2-정보공학-개발-방법론의-개념">4-1-2. 정보공학 개발 방법론의 개념</h3>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/04b49316-d666-426b-a4fa-722b13c9bbe4/image.png" alt=""></p>
<blockquote>
<p>설계할 때는 스토리 보드, 데이터 설계서, <code>UI</code> 설계서 정도를 작성하고 개발 과정에서는 이를 바탕으로 물리적 테이블과 프로그램 코드가 만들어 진다.</p>
<p>이런 관점에서 정보공학 방법론을 바라 본다면 <code>BAA</code>에 해당하는 요구분석 단계에서는 요구사항 명세서가 만들어지고 <code>BSD</code>에 해당하는 시스템 설계 단계에서는 논리 <code>ERD</code>와 업무 프로세서를 설명하는 프로세스 구조도/흐름도가 만들어 진다.</p>
<p>그리고 <code>SC</code>에 해당하는 개발 단계에서는 물리 <code>ERD</code>, <code>UI</code>, 프로그램 코드가 개발된다.</p>
</blockquote>
<h2 id="4-2-정보공학-개발-방법론의-장단점">4-2. 정보공학 개발 방법론의 장/단점</h2>
<h3 id="4-2-1-정보공학-개발-방법론의-장점">4-2-1. 정보공학 개발 방법론의 장점</h3>
<ul>
<li><p>경쟁 우위 전략적 기회를 식별할 수 있으며, 방안 또한 제공이 가능하다.</p>
</li>
<li><p>일관/통일된 정보 시스템을 구축할 수 있다.</p>
</li>
<li><p>데이터 중심으로 업무의 절차가 진행되며 환경 변화에 유연하다.</p>
</li>
</ul>
<h3 id="4-2-2-정보공학-개발-방법론의-단점">4-2-2. 정보공학 개발 방법론의 단점</h3>
<ul>
<li><p>정보 공학의 효과를 위해 장기간이 소요된다.</p>
</li>
<li><p>특정 사업 영역으로부터 독립된 시스템의 개발에 부적합하다.</p>
</li>
<li><p>소규모 자동화 요구 사업에는 부적합하다.</p>
</li>
</ul>
<hr>
<h1 id="5-객체지향-개발-방법론">5. 객체지향 개발 방법론</h1>
<blockquote>
<p>객체지향 개발 방법론은 현실 세계의 개체(<code>Entity</code>)를 속성(<code>Attribute</code>)과 메소드(<code>Method</code>)가 결합된 형태의 객체(<code>Object</code>)로 표현한다.</p>
<p>이를 통해 현실 세계에 존재하는 실체 및 개념들을 객체(<code>Object</code>)라는 독립된 단위로 구성하고 이 객체들이 메시지 교환을 통해 상호작용함으로써 전체 시스템이 운영되는 개념이다.</p>
</blockquote>
<h2 id="5-1-객체지향-개발-방법론의-특징">5-1. 객체지향 개발 방법론의 특징</h2>
<blockquote>
<p>객체지향 개발 방법론에서는 분석, 설계, 구현의 전 과정을 객체 중심으로 진행한다.</p>
<p>심지어 데이터를 저장하는 테이블도 따로 설계하지 않고 데이터 객체로 설계하며, 데이터는 결국 데이터 베이스에 저장되는데 만일 데이터 베이스가 객체형 <code>DB</code>라면 별다른 변환 과정 없이 데이터 객체를 그대로 저장하면 되지만, 관계형 <code>DB</code>를 사용한다면 객체를 관계형 테이블로 변환하는 과정이 필요하다.</p>
<p>이 과정을 객체-관계 매핑(<code>Object Relation Mapping</code>)이라 하며 <strong>현재 대부분의 회사에서 관계형 데이터 베이스를 사용하고 있기 때문에 객체-관계 매핑은 필수적인 과정</strong>이라 할 수 있다. </p>
</blockquote>
<h3 id="5-1-1-객체지향-개발-방법론의-특성">5-1-1. 객체지향 개발 방법론의 특성</h3>
<ul>
<li>추상화 (<code>Abstraction</code>)
객체지향 이전에도 많이 다뤘던 설계 개념으로, <strong>불필요한 세부 사항은 배제하고 핵심이 되는 공통 사항을 묶어 개략화하는 작업</strong>을 말한다.</li>
</ul>
<ul>
<li>캡슐화 (<code>Encapsulation</code>)
객체지향 그 자체를 설명하는 개념으로 볼 수 있으며, 속성과 메소드와 같은 각 알맹이들을 하나의 캡슐 안에 넣어서, 안에 무엇이 들어있는지 모르게 할수도, 한 입 크기로 먹어 삼키게 할 수도 있는 작업이다.</li>
</ul>
<ul>
<li>정보은닉 (<code>Information Hiding</code>)
캡슐화된 객체 내부에 자료 구조나 함수의 기능을 외부의 영향을 받거나 주지 않도록 설계하는 방법이다.</li>
</ul>
<ul>
<li>상속성 (<code>Inheritance</code>)
객체지향만의 특정으로 볼 수 있으며, 이 객체를 만드는 클래스들을 PC의 폴더(트리) 구조와 같이 부모/자식 계층으로 구성하여, 자식(하위) 계층에서는 부모(상위) 계층의 성질을 물려받을 수 있도록 하는 특성으로, 객체 간 메시지 전달을 통해 프로그래밍하는 방법이다.</li>
</ul>
<ul>
<li>다형성 (<code>Polymorphism</code>)
같은 메시지에 대해 클래스에 따라 다른 행위를 하게 하는 특성으로, 부모로부터 상속받은 메소드를 자식이 재정의할 수 있다. (오버라이딩)</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/ff20e628-dd0a-415f-ae12-04629e394afc/image.png" alt=""></p>
<h3 id="5-1-2-객체지향-개발-방법론의-구성요소">5-1-2. 객체지향 개발 방법론의 구성요소</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td>클래스</td>
<td>- 같은 종류(또는 문제 해결을 위한)의 집단에 속한 속성(<code>Attribute</code>)과 행위(<code>Behavior</code>)이다.</td>
</tr>
<tr>
<td></td>
<td>- 객체 지향 프로그램의 기본적인 사용자 정의 데이터형 (<code>user define data type</code>)이다.</td>
</tr>
<tr>
<td>객체</td>
<td>- 자신 고유의 데이터(<code>Attribute</code>)를 가지며 클래스에서 정의한 행위(<code>Behavior</code>)를 수행한다.</td>
</tr>
<tr>
<td></td>
<td>- 객체는 클래스의 한 인스턴스(<code>instance</code>)가 된다.</td>
</tr>
<tr>
<td></td>
<td>- 데이터(실체)와 그 데이터에 관련되는 동작(절차, 방법, 기능)을 모두 포함한 개념이다.</td>
</tr>
<tr>
<td>메소드</td>
<td>- 클래스로부터 생성된 객체를 사용하는 방법</td>
</tr>
<tr>
<td>메시지</td>
<td>- <code>Sender</code> 와 <code>Receiver</code> 객체들간의 상호작용의 수단으로 다른 객체에 특정 작업을 요청하는 신호이다.</td>
</tr>
<tr>
<td></td>
<td>- 수신 객체 이름, 오퍼레이션 이름, 매개 변수로 구성된다.</td>
</tr>
</tbody></table>
<h3 id="5-1-3-객체지향-개발-방법론의-단계">5-1-3. 객체지향 개발 방법론의 단계</h3>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/8ed78816-995e-43a5-a6fe-ce2d79002dc5/image.png" alt=""></p>
<p>위의 그림을 참고하면,</p>
<ol>
<li><p>개념화 단계(<code>Inception Phase</code>)</p>
<ul>
<li><p>시스템에 대한 비즈니스 사례(<code>Business Case</code>)를 만들고 프로젝트 범위(<code>Scope</code>)를 정의한다.</p>
</li>
<li><p>시스템과 상호작용을 하는 모든 외부 엔티티(<code>Actor</code>)를 명시하고, 상위 레벨(<code>High Level</code>)에서 상호작용의 특징을 정의한다.</p>
</li>
<li><p>모든 유즈케이스(<code>Use Case</code>)를 명시하고 중요한 몇 가지를 설명하는 것도 포함된다.</p>
</li>
<li><p>비즈니스 사례는 성공기준(<code>Success Criteria</code>), 위험관리(<code>RiskManagement</code>), 필요한 자원의 평가, 주요한 이정표 날짜를 보여주는 단계별 계획을 포함한다.</p>
</li>
<li><p>개념화 단계의 마지막에는 프로젝트 목적을 검사하고 개발 진행 여부를 결정한다.</p>
</li>
</ul>
</li>
<li><p>상세화 단계(<code>Elaboration Phase</code>)</p>
<ul>
<li><p>문제영역(<code>Problem Domain</code>)을 분석하고 견고한 아키텍처 토대를 마련하고 프로젝트 계획을 개발하며 프로젝트에서 가장 위험한 요소를 제거하는 것이다.</p>
</li>
<li><p>아키텍처에 대한 결정은 전체 시스템의 충분한 이해를 통하여 이루어져야 하며, 이것은 유즈케이스를 기술하고 추가적인 요구사항과 같은 제약사항을 고려하는 것을 의미한다.</p>
</li>
<li><p>아키텍처를 검증하기 위해서는 선정된 아키텍처를 실현하고(<code>demonstrates</code>) 중요한 유즈케이스를 실행하는 시스템을 구현하는 것이다.</p>
</li>
<li><p>상세화 단계의 마지막에는 상세한 시스템의 목적과 범위 및 아키텍처 선정과 주요 위험을 검사한다.</p>
</li>
</ul>
</li>
<li><p>구축 단계(<code>Construction Phase</code>)</p>
<ul>
<li><p>구축 단계에서는 사용자들(<code>User Community</code>)에게 전이할 수 있도록 반복 및 점증적으로 제품을 완전히 개발하는 것으로, 이것은 나머지 유즈케이스를 기술하고 설계 부문을 더욱 충실하게 하며, 구현을 완전히 끝내고 소프트웨어를 테스트하는 것을 의미한다.</p>
</li>
<li><p>구축 단계의 마지막에는 소프트웨어와 환경과 사용자들이 운영될 준비가 되었는지를 결정한다.</p>
</li>
</ul>
</li>
<li><p>전이 단계(<code>Transition Phase</code>)</p>
<ul>
<li><p>소프트웨어를 사용자들(<code>User Community</code>)에게 전달하는 것이다.</p>
</li>
<li><p>제품이 사용자의 손에 전해졌을 때에는, 시스템에 적합하도록 추가적인 개발 및 발견되지 않은 문제점을 수정하고 미루어 놓은 사항들(<code>Features</code>)을 마무리 짓는다.</p>
</li>
<li><p>일반적으로 이 단계는 시스템의 &quot;베타 릴리즈(<code>Beta Release</code>)&quot;로 시작된다.</p>
</li>
<li><p>전이 단계의 마지막에는 생명주기 목적의 충족여부 및 또 다른 개발 주기의 시작여부를 결정해야 하며, 또한 프로세스를 개선하기 위해 프로젝트에서 경험한 것을 여기서 정리한다.</p>
</li>
</ul>
</li>
</ol>
<h2 id="5-2-객체지향-개발-방법론의-장단점">5-2. 객체지향 개발 방법론의 장/단점</h2>
<h3 id="5-2-1-객체지향-개발-방법론의-장점">5-2-1. 객체지향 개발 방법론의 장점</h3>
<ul>
<li><p>규모가 큰 대형 프로젝트에 적합하다.</p>
</li>
<li><p>소프트웨어의 재사용률/확장성/유지보수성이 향상된다.</p>
</li>
<li><p>신속하게 개발이 가능하다.</p>
</li>
<li><p>사용자 타입을 중심으로 개발된다.</p>
</li>
<li><p>대화식 프로그램 개발에 용이하다.</p>
</li>
</ul>
<h3 id="5-2-2-객체지향-개발-방법론의-단점">5-2-2. 객체지향 개발 방법론의 단점</h3>
<ul>
<li><p>설계 단계가 어렵다.</p>
</li>
<li><p>규모가 크기 때문에 실행 속도가 저하된다.</p>
</li>
</ul>
<hr>
<h1 id="6-cbd-개발-방법론">6. <code>CBD</code> 개발 방법론</h1>
<blockquote>
<p><code>CBD</code> 개발 방법론(<code>Component Base Development</code>) 은 개발된 S/W 컴포넌트를 조립, 시스템을 개발하여 객체지향의 단점인 S/W 재사용성을 극대화한 개발 방법론이다.</p>
<p>컴포넌트는 인터페이스로 접근 가능하고 독립적인 기능을 수행하는 모듈로써 교체가 가능한 소프트웨어 부품이다.</p>
</blockquote>
<h2 id="6-1-cbd-개발-방법론의-특징">6-1. <code>CBD</code> 개발 방법론의 특징</h2>
<blockquote>
<p><code>CBD</code> 개발 방법론은 크게 컴포넌트를 개발하는 <code>CD</code>(<code>Component Development</code>) 단계와 개발된 컴포넌트를 사용해서 개발을 진행하는 <code>CBD</code>(<code>Component Base Development</code>) 단계로 나눌 수 있다.</p>
<p><code>CD</code> 단계에서는 도메인을 분석해 컴포넌트 대상 업무를 선별하고 컴포넌트를 개발해 저장소에 입력한다.</p>
<p><code>CBD</code> 단계에서는 요구 분석을 통해 컴포넌트 기반으로 설계하고 필요한 컴포넌트를 저장소에서 찾아서 조립하는 방식으로 프로그램 개발을 진행한다.</p>
<p>만일 필요한 컴포넌트가 저장소에 없다면 <code>CD</code> 단계로 돌아가서 컴포넌트를 개발하고 이를 사용해 개발을 계속 진행한다.</p>
</blockquote>
<h3 id="6-1-1-cbd-개발-방법론의-단계">6-1-1. <code>CBD</code> 개발 방법론의 단계</h3>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/e3f8c11b-6aee-41a5-939d-9568132d4297/image.png" alt=""></p>
<p>위의 그림을 참고하면,</p>
<ol>
<li><p>요구 파악</p>
<ul>
<li><p>사용자 요구사항을 수집, 도메인을 분석하며, 요구사항 기술서, 용어 사전, 개념 모델등을 이해한다.</p>
</li>
<li><p>요구사항 이해를 기반으로 유즈케이스를 작성하며 요구사항을 정의한다.</p>
</li>
</ul>
</li>
<li><p>분석 및 설계</p>
<ul>
<li><p>객체 모델의 프로토타이핑 및 <code>UI</code>를 시획하여 객체 모델과 <code>UI</code> 설계서를 제작하며 요구사항을 분석한다.</p>
</li>
<li><p>아키텍쳐 기술서를 작성하며 소프트웨어 컴포넌트 아키택처를 정의한다.</p>
</li>
<li><p>아키택처를 기반으로 <code>I/D</code> 명세화와 모델링을 진행하며, 인터페이스 명세서와 컴포넌트 명세서를 작성하며 컴포넌트 설계를 한다.</p>
</li>
<li><p>객체 모델의 텐티티 클래스를 대상으로 <code>DB</code>를 모델링하며, <code>ERD</code>, <code>DB</code> 설계서를 작성하며 데이터 베이스를 설계한다.</p>
</li>
</ul>
</li>
<li><p>구현</p>
<ul>
<li>플랫폼 특성을 검토하며, 표준을 수립하고 명명 규칙, 코딩 규칙, 프로그래밍 가이드 등의 개발 표준 정의를 한다.</li>
<li>플랫폼에 따른 전용 <code>Compiler</code>를 이용하며 코드를 구현한다.</li>
</ul>
</li>
<li><p>테스트</p>
<ul>
<li><p>테스트의 목표와 대상, 방법, 절차 등을 수립하며 테스트 계획을 진행하고 계획서를 작성한다.</p>
</li>
<li><p>테스트의 수행, 절차 기록 및 승인을 진행하며, 컴포넌트 테스트, 통합 테스트, 인수 테스트 등의 보고서를 작성하며 테스트에 대한 수행/보고를 진행한다.</p>
</li>
</ul>
</li>
</ol>
<h2 id="6-2-cbd-개발-방법론의-장단점">6-2. <code>CBD</code> 개발 방법론의 장/단점</h2>
<h3 id="6-2-1-cbd-개발-방법론의-장점">6-2-1. <code>CBD</code> 개발 방법론의 장점</h3>
<ul>
<li><p>반복적인 활용에 의한 수익성 제고 및 개발 기간과 개발 비용이 감소한다.</p>
</li>
<li><p>검증된 <code>Component</code> 사용으로 S/W의 품질 수준을 향상시킨다.</p>
</li>
<li><p>지적 자산의 재활용 범위가 확대된다.</p>
</li>
<li><p>소프트웨어 개발, 유지보수 부문의 생산성을 극대화시킬 수 있다.</p>
</li>
</ul>
<h3 id="6-2-2-cbd-개발-방법론의-단점">6-2-2. <code>CBD</code> 개발 방법론의 단점</h3>
<ul>
<li><p>파라다임 변화에 따른 시행 착오가 따른다.</p>
</li>
<li><p>고객과의 문제제로 인해 프로젝트의 잦은 범위 변경 요청에 취약하다.</p>
</li>
<li><p>초기 선행에 투자가 필요하다.</p>
</li>
<li><p>조립식 정보 시스템 구축에 따른 각각의 책임이 따른다.</p>
</li>
</ul>
<hr>
<h1 id="7-애자일-개발-방법론">7. 애자일 개발 방법론</h1>
<blockquote>
<p>애자일 개발 방법론은 기존 방법론들이 너무 절차를 중시한 나머지 변화에 대응하기 어려웠던 단점을 개선하기 위해 나왔다.</p>
<p>애자일 방법론은 절차보다는 사람을, 문서보다는 작동하는 소프트웨어를, 미리 철저하게 계획하기 보다는 변화에 대한 민첩한 대응을, 계약과 협상에 얽매이기 보다는 고객과의 협력을 중요하게 생각한다.</p>
</blockquote>
<h2 id="7-1-애자일-개발-방법론의-특징">7-1. 애자일 개발 방법론의 특징</h2>
<blockquote>
<p>애자일 방법론에서는 먼저 개발 범위 안에 있는 요구사항을 분석해 우선 순위가 높은 요구사항을 먼저 개발한다.</p>
<p>개발된 부분에 대해 실행하는 모습을 보여줘서 고객의 평가를 받고 고객의 요구사항과 개선사항을 반영해 다음 요구사항 개발에 참고한다.</p>
<p>이런 방식을 계속 반복하면서 소프트웨어 개발 범위를 점진적으로 늘려가게 되는데, 여기에서 가장 핵심이 되는 사항은 단계별로 고객에게 동작하는 소프트웨어를 계속 보여주고 요구사항에 대한 변경을 적극적으로 수용한다는 것이다.</p>
</blockquote>
<h3 id="7-1-1-애자일-소프트웨어-개발-12대-원칙">7-1-1. 애자일 소프트웨어 개발 12대 원칙</h3>
<ul>
<li><p>고객 만족</p>
</li>
<li><p>변화 수용</p>
</li>
<li><p>자주 납품</p>
</li>
<li><p>팀으로 작업</p>
</li>
<li><p>동기부여</p>
</li>
<li><p>대면 소통</p>
</li>
<li><p>가독성 측정</p>
</li>
<li><p>속도 일정 유지</p>
</li>
<li><p>품질 최우선</p>
</li>
<li><p>복잡하지 않도록</p>
</li>
<li><p>설계 진화</p>
</li>
<li><p>규칙적 반영</p>
</li>
</ul>
<h3 id="7-1-2-애자일-개발-방법론의-단계">7-1-2. 애자일 개발 방법론의 단계</h3>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/aa9ff9e3-0611-4c10-8bc6-023fb982b6fa/image.png" alt=""></p>
<p>위의 그림을 참고하면,</p>
<ol>
<li><p>계획 및 분석</p>
<ul>
<li>고객과 사용자가 원하는 바를 파악하여 타당성을 조사하고 S/W 기능과 제약 조건을 정의하는 명세서 작성, 대상이 되는 문제 영역과 사용자가 원하는 <code>Task</code>를 이해하는 단계이다.</li>
</ul>
</li>
<li><p>설계 (디자인)</p>
<ul>
<li>기획 의도에 맞는 설계 및 디자인 추가 및 수정하는 단계이다.</li>
</ul>
</li>
<li><p>개발 (발전)</p>
<ul>
<li>설계 단계에서 만들어진 설계서를 바탕으로 프로그램을 작성, 코딩, 디버깅, 단위/통합 테스트를 수행한다.</li>
</ul>
</li>
<li><p>테스트</p>
<ul>
<li>발생할 수 있는 실행 프로그램 오류를 발견, 수정하는 단계이다.</li>
</ul>
</li>
<li><p>검토 (피드백)</p>
<ul>
<li>기획 의도를 파악하고 시험 결과와 기획에 따라 수정할 부분을 제시하는 단계이다.</li>
</ul>
</li>
</ol>
<h2 id="7-2-애자일-개발-방법론의-장단점">7-2. 애자일 개발 방법론의 장/단점</h2>
<h3 id="7-2-1-애자일-개발-방법론의-장점">7-2-1. 애자일 개발 방법론의 장점</h3>
<ul>
<li><p>프로젝트 계획에 걸리는 시간을 최소화할 수 있다.</p>
</li>
<li><p>점진적으로 테스트할 수 있어서 버그를 쉽고 빠르게 발견할 수 있다.</p>
</li>
<li><p>계획 혹은 기능에 대한 수정과 변경에 유연하다.</p>
</li>
<li><p>고객 요구사항에 대한 즉각적인 피드백에 유연하며 프로토타입 모델을 빠르게 출시할 수 있다.</p>
</li>
<li><p>빠듯한 기한의 프로젝트를 빠르게 출시할 수 있다.</p>
</li>
</ul>
<h3 id="7-2-2-애자일-개발-방법론의-단점">7-2-2. 애자일 개발 방법론의 단점</h3>
<ul>
<li><p>확정되지 않은 계획 및 요구사항으로 인한 반복적인 유지보수 작업이 많다.</p>
</li>
<li><p>고객의 요구사항 및 계획이 크게 변경되면 모델이 무너질 수 있다.</p>
</li>
<li><p>개인이 아닌 팀이 중심이 되다 보니 공통으로 해야 할 작업이 많을 수 있다. (회의, 로그 등)</p>
</li>
<li><p>반복적인 업무로 속도는 빠를 수 있으나 미흡한 기능들에 대한 대처가 필요하다.</p>
</li>
<li><p>확정되지 않은 계획으로 개발 진행 시 이해하지 못하고 진행하는 부분이 많을 수 있다.</p>
</li>
</ul>
<hr>
<h1 id="8-결론">8. 결론</h1>
<ul>
<li><p><u><strong>구조적 개발 방법론</strong></u></p>
<blockquote>
<p>정형화 된 분석 절차에 따라 사용자 요구사항을 파악하여 문서화 하는 처리 중심의 방법론</p>
</blockquote>
</li>
<li><p><u><strong>정보공학 개발 방법론</strong></u></p>
<blockquote>
<p>정보 시스템의 개발을 위해 계획, 분석, 설계, 구축에 정형화된 기법들을 상호 연관성 있게 통합 및 적용하는 자료 중심의 방법론</p>
</blockquote>
</li>
<li><p><u><strong>객체지향 개발 방법론</strong></u></p>
<blockquote>
<p>객체들을 조립해서 필요한 소프트웨어를 구현하는 방법론</p>
</blockquote>
</li>
<li><p><u><strong><code>CBD</code> 개발 방법론</strong></u></p>
<blockquote>
<p>정보 시스템의 개발을 위해 계획, 분석, 설계, 구축에 정형화된 기법들을 상호 연관성 있게 통합 및 적용하는 자료 중심의 방법론</p>
</blockquote>
</li>
<li><p><u><strong>애자일 개발 방법론</strong></u></p>
<blockquote>
<p>고객의 요구사항 변화에 유연하게 대응할 수 있도록 일정한 주기를 반복하면서 개발 과정을 진행하는 방법론</p>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="http://wiki.hash.kr/index.php/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4_%EA%B0%9C%EB%B0%9C%EB%B0%A9%EB%B2%95%EB%A1%A0">해시넷 - 소프트웨어 개발방법론</a>
<a href="https://underflow101.tistory.com/category/%EA%B8%B0%EC%88%A0%EC%82%AC%20%EC%A4%80%EB%B9%84/SW%EA%B3%B5%ED%95%99%20-%20%EA%B0%9C%EB%B0%9C%20%EB%B0%A9%EB%B2%95%EB%A1%A0">공대생의 차고 - 기술사 준비/SW공학 - 개발 방법론</a>
<a href="https://many258.github.io/study/software-engineering-object-oriented/">My LifeChronicle - [소프트웨어공학] 객체지향 개발 방법론</a>
<a href="http://www.incodom.kr/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4_%EA%B0%9C%EB%B0%9C_%EB%B0%A9%EB%B2%95%EB%A1%A0">인코덤 - 소프트웨어 개발 방법론</a>
<a href="https://velog.io/@with667800/%EA%B0%9C%EB%B0%9C-%EB%B0%A9%EB%B2%95%EB%A1%A0">log.log.log.log.log.log - 개발 방법론</a>
<a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=jvioonpe&amp;logNo=220226743707">AI IMPACTS - [개발방법론] 객체지향방법론이란?</a>
<a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=deepb1ue&amp;logNo=221195044749">느리게 생각하기 - 구조적 분석 도구</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] SSR VS CSR]]></title>
            <link>https://velog.io/@hyungjin_han/Computer-Science-SSR-VS-CSR</link>
            <guid>https://velog.io/@hyungjin_han/Computer-Science-SSR-VS-CSR</guid>
            <pubDate>Wed, 15 Feb 2023 08:12:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><code>CSR</code>(Client Side Rendering)과 <code>SSR</code>(Server Side Rendering)은 대척 관계에 있는 방식인만큼 장단점이 서로 엇갈려 있기 때문에 서로의 장단을 정확하게 알고, 적재적소에 필요한 방식으로 구현하는 것이 중요하다.</p>
</blockquote>
<h1 id="1-ssr이란">1. <code>SSR</code>이란?</h1>
<p><code>Server Side Rendering</code>의 약자로 말 그대로 서버 쪽에서 렌터링 준비를 끝마친 상태로 클라이언트에게 전달하는 방식이다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/3b1e6018-ed68-48ee-986c-4cfced7c724b/image.png" alt=""></p>
<p>위의 그림을 통해 <code>SSR</code> 단계를 설명하자면,</p>
<ol>
<li><p>유저가 웹 사이트에 요청을 보낸다.</p>
</li>
<li><p><code>Server</code>는 &quot;Ready to Render&quot;. 즉, 즉시 렌더링 가능한 <code>HTML</code> 파일을 만든다.</p>
<blockquote>
<p>리소스 체크, 컴파일 후 완성된 <code>HTML</code> 컨텐츠로 만든다.</p>
</blockquote>
</li>
<li><p>클라이언트에 전달되는 순간, 이미 렌더링 준비가 되어있기 때문에 <code>HTML</code>은 즉시 렌더링이 되지만, 사이트 자체는 조작이 불가능하다.</p>
<blockquote>
<p><code>JavaScript</code>가 읽히기 전이기 때문이다.</p>
</blockquote>
</li>
<li><p>클라이언트가 <code>JavaScript</code>를 다운받는다.</p>
</li>
<li><p>다운받아지고 있는 사이에 유저는 컨텐츠를 볼 수 있지만, 사이트 조작을 할 수는 없다.</p>
<blockquote>
<p>이때의 사용자 조작 자체를 기억하고는 있다.</p>
</blockquote>
</li>
<li><p>브라우저가 <code>JavaScript</code> 프레임워크를 실행한다.</p>
</li>
<li><p><code>JavaScript</code>까지 성공적으로 컴파일 되었기 때문에 기억하고 있던 사용자 조작이 실행되고 이제 웹 페이지는 상호작용이 가능해진다.</p>
</li>
</ol>
<ul>
<li><code>SSR</code>을 설명하는 간단한 이미지
<img src="https://velog.velcdn.com/images/hyungjin_han/post/97f081f4-8e11-4cf8-bbb9-9e6f0a6e899b/image.png" alt=""></li>
</ul>
<blockquote>
<p>즉, 서버에서 이미 &quot;렌더 가능한&quot; 상태로 클라이언트에 전달되기 때문에, <code>JavaScript</code>가 다운로드 되는 동안 사용자는 <strong>무언가</strong>를 보고 있을 수 있다.</p>
</blockquote>
<hr>
<h1 id="2-csr이란">2. <code>CSR</code>이란?</h1>
<p><code>Client Side Rendering</code>의 약자로 말 그대로 <code>SSR</code>과 달리 렌더링이 클라이언트 쪽에서 일어나며, 서버는 요청을 받으면 클라이언트에 <code>HTML</code>과 <code>JavaSript</code>를 보내주고, 클라이언트는 그것을 받아 렌더링을 시작한다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/e96497a4-0d64-48e3-819b-663b108a5025/image.png" alt=""></p>
<p>위의 그림을 통해 <code>CSR</code> 단계를 설명하자면,</p>
<ol>
<li><p>유저가 웹 사이트에 요청을 보낸다.</p>
</li>
<li><p><code>CDN</code>이 <code>HTML</code> 파일과 <code>JavaScript</code>로 접근할 수 있는 링크를 클라이언트로 보낸다.</p>
<blockquote>
<p><code>CDN</code>이란?
<code>AWS</code>의 <code>Cloudflare</code>를 생각하면 되며, 엔트 유저의 요청에 &quot;물리적&quot;으로 가까운 서버에서 요청에 응답하는 방식이다.</p>
</blockquote>
</li>
<li><p>클라이언트는 <code>HTML</code>과 <code>JavaScript</code>를 다운로드 받는다.</p>
<blockquote>
<p>이때 <code>SSR</code>과는 달리 유저는 아무것도 볼 수 없다.</p>
</blockquote>
</li>
<li><p>다운로드된 <code>JavaScript</code>가 실행되며, 데이터를 위한 <code>API</code>가 호출된다.</p>
<blockquote>
<p>이때 유저들은 <code>placeholder</code>를 보게 된다.</p>
</blockquote>
</li>
<li><p>서버가 <code>API</code>로부터의 요청에 응답한다.</p>
</li>
<li><p><code>API</code>로부터 받아온 <code>Data</code>를 <code>placeholder</code> 자리에 넣어주며, 이제 페이지는 상호작용이 가능해진다.</p>
</li>
</ol>
<ul>
<li><code>CSR</code>을 설명하는 간단한 이미지
<img src="https://velog.velcdn.com/images/hyungjin_han/post/eaf9cca8-6a43-469a-ad98-059b71fbaff8/image.png" alt=""></li>
</ul>
<blockquote>
<p>즉, 서버에서 처리 없이 클라이언트로 보내주기 때문에 <code>JavaScript</code>가 모두 다운로드 되고 실행이 끝나기 전까지 사용자는 볼 수 있는 것이 없다.</p>
</blockquote>
<hr>
<h1 id="3-ssr과-csr의-차이">3. <code>SSR</code>과 <code>CSR</code>의 차이</h1>
<h2 id="3-1-웹-페이지의-로딩-시간">3-1. 웹 페이지의 로딩 시간</h2>
<p>웹 페이지 로딩의 종류는 두 가지로 나눌 수 있으며, 하나는 웹 사이트의 가장 첫 페이지 로딩, 다른 하나는 나머지 컨텐츠를 로딩하는 것으로 나누어진다.</p>
<h3 id="3-1-1-첫-페이지-로딩-시간">3-1-1. 첫 페이지 로딩 시간</h3>
<ul>
<li><code>CSR</code>
  <code>HTML</code>, <code>CSS</code>와 모든 스크립트들을 한 번에 불러오는 방식이다.</li>
<li><code>SSR</code>
  필요한 부분의 <code>HTML</code>과 스크립트만 불러오는 방식이다.</li>
</ul>
<blockquote>
<p>따라서 평균적으로 첫 페이지 로딩 시간은 <code>SSR</code> 방식이 더 빠르다고 볼 수 있다.</p>
</blockquote>
<h3 id="3-1-2-나머지-컨텐츠-로딩-시간">3-1-2. 나머지 컨텐츠 로딩 시간</h3>
<blockquote>
<p>첫 페이지를 로딩한 후, 사이트의 다른 곳으로 이동하는 식의 동작으로 가정한다.</p>
</blockquote>
<ul>
<li><code>CSR</code>
  <code>HTML</code>, <code>CSS</code>와 모든 스크립트들을 첫 페이지 로딩에서 한번에 불러오는 방식이므로 나머지 컨텐츠 부분을 구성하는 코드를 받아왔기 때문에 비교적 빠르게 작동한다.</li>
<li><code>SSR</code>
  필요한 부분의 <code>HTML</code>과 스크립트만 불러오는 방식이므로 나머지 컨텐츠 부분을 첫 페이지를 로딩한 과정처럼 정확하게 다시 실행하기 때문에 비교적 느리게 작동한다.</li>
</ul>
<blockquote>
<p>따라서 평균적으로 첫 페이지 로딩의 작동 방식의 차이로 인해 나머지 컨텐츠 로딩 시간은 <code>CSR</code> 방식이 더 빠르다고 볼 수 있다.</p>
</blockquote>
<h2 id="3-2-seo-대응">3-2. <code>SEO</code> 대응</h2>
<blockquote>
<p><code>SEO</code>란?
<code>SEO</code>(검색 엔진 최적화)는 웹 사이트가 유기적인(무료) 검색 방식을 통해 검색 엔진에서 상위에 노출될 수 있도록 최적화하는 과정을 말하며, 비즈니스 유형이 어떤 것이든 <code>SEO</code>는 가장 중요한 마케팅 유형 중 하나이다.</p>
</blockquote>
<ul>
<li><code>CSR</code>
  <code>CSR</code>은 <code>JavaScript</code>를 실행시켜 동적으로 컨텐츠가 생성되기 때문에, <code>JavaScript</code>가 실행 되어야 <code>meatadata</code>가 바뀌는 방식이다.<blockquote>
<p>이전 크롤러들은 <code>JavaScript</code>를 실행시키지 않았기에 <code>SEO</code> 최적화가 필수적이었으며, 구글이 그 트렌드를 바꾸고 있다고 한다.</p>
</blockquote>
</li>
<li><code>SSR</code>
   애초에 <code>Server Side</code>에서 컴파일되어 클라이언트로 넘어오기 때문에 크롤러에 대응하기 용이하다.</li>
</ul>
<blockquote>
<p>따라서 <code>JavaScript</code>를 실행시켜 동적으로 컨텐츠를 생성하는 <code>CSR</code>에 비해 클라이언트로 넘어오기 전에 <code>JavaScript</code>를 서버 쪽에서 컴파일되기 때문에, <code>SEO</code>에 대응하기에 용이한 방식은 <code>SSR</code> 방식이라고 볼 수 있다.</p>
</blockquote>
<h2 id="3-3-서버-자원-사용">3-3. 서버 자원 사용</h2>
<ul>
<li><p><code>CSR</code>
  클라이언트에서 <code>JavaScript</code>를 실행시켜 컨텐츠를 생성한 후, 서버로 보내기 때문에 서버 자원 사용이 적다.</p>
</li>
<li><p><code>SSR</code>
   애초에 매번 서버를 통해 <code>JavaScript</code> 컴파일을 오청하기 때문에 서버 자원의 사용이 많을 수 밖에 없다.</p>
<blockquote>
<p><code>React</code>의 <code>renderToString</code> 메소드를 사용하여 <code>SSR</code> 방식을 구현할 수 있지만, 다음과 같은 문제가 발생한다.</p>
<blockquote>
<p><code>renderToString</code> 메소드는 스택을 막고 동기적으로 처리하는 방식으로, 메소드가 실행되는 동안 서버가 멈추게 된다.</p>
</blockquote>
</blockquote>
</li>
</ul>
<blockquote>
<p>당연한 말이지만, <code>SSR</code> 방식이 서버 자원 사용량이 많다.</p>
</blockquote>
<blockquote>
<p>참고로 <code>React</code>가 18버전으로 버전업되면서 <code>NextJS</code>를 사용하여 <code>SSR</code>을 구현하는 것과 달리, <code>React</code> 자체적으로 <code>React-router</code>와 <code>@loadable-component</code>의 조합으로 <code>SSR</code>을 구현할 수 있다.</p>
<blockquote>
<p>하지만, <code>CSS</code>는 <code>@loadable-component</code>에서 지원하지 않아, <code>Hot Reload</code>가 아직 불가능하다.</p>
</blockquote>
</blockquote>
<hr>
<h1 id="4-ssr과-csr-사용">4. <code>SSR</code>과 <code>CSR</code> 사용</h1>
<h2 id="4-1-ssr의-사용">4-1. <code>SSR</code>의 사용</h2>
<ul>
<li><p><code>SSR</code> 방식은 각 페이지마다 나누어서 불러오기 때문에 네트워크가 느린 경우</p>
</li>
<li><p><code>SEO</code>(검색 엔진 최적화)가 필요한 경우</p>
</li>
<li><p>최초 페이지의 로딩이 빨라야 하는 사이트를 개발하는 경우</p>
</li>
<li><p>메인 스크립트가 크고, 로딩이 매우 느린 경우</p>
<blockquote>
<p><code>CSR</code> 방식은 메인 스크립트가 로딩이 모두 끝나고 나서 <code>API</code>로 테이터 요청을 보내지만, <code>SSR</code> 방식은 한 번의 요청에 아예 렌더가 가능한 페이지로 돌아온다.</p>
</blockquote>
</li>
<li><p>웹 사이트가 상호작용이 많지 않은 경우</p>
</li>
</ul>
<h2 id="4-2-csr의-사용">4-2. <code>CSR</code>의 사용</h2>
<ul>
<li><p><code>CSR</code> 방식은 한 번에 모든 스크립트를 불러오는 방식으로, 네트워크가 빠른 경우</p>
</li>
<li><p>서버 성능이 좋지 않은 경우</p>
</li>
<li><p>사용자에게 보여줘야 하는 데이터의 양이 많은 경우</p>
<blockquote>
<p>로딩창을 띄울 수 있는 장점이 있다.</p>
</blockquote>
</li>
<li><p>메인 스크립트가 가벼운 경우</p>
</li>
<li><p><code>SEO</code>(검색 엔진 최적화)에 대해 상관이 없는 경우</p>
</li>
<li><p>웹 어플리케이션이 사용자와 상호작용할 것들이 많은 경우</p>
<blockquote>
<p>아예 렌더링 되지 않아서 의도하지 않은 사용자의 행동을 막는 것이 <code>UX</code> 부분에서 오히려 유리함.</p>
</blockquote>
</li>
</ul>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://proglish.tistory.com/216">Blog 프로그래밍 - SSR과 CSR의 차이</a>
<a href="https://www.startupcode.kr/company/blog/archives/12">스타트업코드 - SSR과 CSR의 차이</a>
<a href="https://minoo.medium.com/next-js-%EC%B2%98%EB%9F%BC-server-side-rendering-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-7608e82a0ab1">DylanJu - React로 Next.js처럼 Server-side-rendering 구현하기</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Class 사용하기]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-Class-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-Class-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 14 Feb 2023 09:04:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀로, 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.</p>
</blockquote>
<h1 id="1-javascript의-class">1. <code>JavaScript</code>의 <code>Class</code></h1>
<p><code>JavaScript</code>에서 <code>class</code> 사용은 <code>ES6</code>에서부터 지원을 하기 시작했으며, 익스플로러에서는 해당 코드 사용이 불가능하나, 최신 브라우저를 이용할 경우 <code>class</code>를 지원한다.</p>
<p><code>class</code>를 사용하는 가장 큰 이유는 재사용성으로, 작은 사이트의 경우 잘 만든 <code>Function</code> 하나로도 충분히 개발이 용이했다면 좀 더 복잡한 사이트를 만들게 될 경우 <code>class</code>의 장점을 더 잘 알 수 있다고 한다.</p>
<h2 id="1-1-class의-기본-문법">1-1. <code>Class</code>의 기본 문법</h2>
<h3 id="1-1-1-class-생성">1-1-1. <code>Class</code> 생성</h3>
<p><code>JavaScript</code> 내에서 <code>class</code>를 생성하려면 간단하며, <code>class</code>를 선언만 해준다면 <code>class</code> 객체를 바로 만들 수 있다.</p>
<pre><code class="language-javascript">class Person {

}

let hhj = new Person();

console.log(hhj, &#39;class 객체 생성&#39;);
// Person {} &#39;class 객체 생성&#39;</code></pre>
<p><code>class</code>로 만들어준 예시 <code>Perwon</code>이라는 이름의 객체가 생성된다.</p>
<h3 id="1-1-2-class-초기값-설정">1-1-2. <code>Class</code> 초기값 설정</h3>
<p><code>Constructor</code>(생성자)를 이용하면 <code>class</code> 객체의 초기 값을 설정해 줄 수 있다.</p>
<p><code>class</code> 내부에서 <code>Constructor</code>는 한 개만 존재할 수 있으며, 2번 이상 사용 시 <code>Syntax Error</code>가 발생할 수 있다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name, age, city) {
    console.log(&#39;construtor&#39;); // construtor
    this.name = name;
    this.age = age;
    this.city = city;
  }
}

let hhj = new Person(&#39;hhj&#39;, &#39;28&#39;, &#39;Gwangju&#39;);

console.log(hhj);
// Person {name: &#39;hhj&#39;, age: &#39;28&#39;, city: &#39;Gwangju&#39;}</code></pre>
<p>위의 코드처럼 <code>Constructor</code>는 새로운 클래스를 생성할 때 가장 처음으로 실행되며 초기값을 설정해준다.</p>
<h3 id="1-1-3-class-메서드-사용">1-1-3. <code>Class</code> 메서드 사용</h3>
<p><code>class</code>에서 설정한 초기값을 접근해 특정 기능을 하는 메서드를 만드는 것도 가능하며, <code>class</code>안에 <code>function</code> 형식으로 만들어준 뒤 해당 메서드를 호출하기만 하면 된다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  nextYear() {
    return Number(this.age) + 1;
  }
}

let hhj = new Person(&#39;hhj&#39;, &#39;28&#39;, &#39;Gwangju&#39;);

console.log(hhj.nextYear());
// 29</code></pre>
<p><code>class</code>는 <code>JavaScript</code> 상 객체의 형태이므로 생성된 <code>class</code> 객체에 <code>class</code> 밖에서 새로운 메서드를 넣는 것도 가능하다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  nextYear() {
    return Number(this.age) + 1;
  }
}

let hhj = new Person(&#39;hhj&#39;, &#39;28&#39;, &#39;Gwangju&#39;);

hhj.eat = function () {
  return &#39;meat&#39;;
}

console.log(hhj.nextYear());
// 29

console.log(hhj.eat());
// meat</code></pre>
<p><code>class</code> 밖에서 추가한 <code>eat</code>이라는 메서드도 함수로써 작동하지만, 이와 같이 밖에서 추가한 <code>class</code>는 추후 새로운 <code>new Person class</code>로 새로운 객체를 만들 경우에 호출하여 사용할 수 없다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  nextYear() {
    return Number(this.age) + 1;
  }
}

let hhj = new Person(&#39;hhj&#39;, &#39;28&#39;, &#39;Gwangju&#39;);

hhj.eat = function () {
  return &#39;meat&#39;;
}

console.log(&#39;hhj의 내년의 나이 -&gt;&#39;, hhj.nextYear());
// hhj의 내년의 나이 -&gt; 29

console.log(&#39;hhj의 먹은 음식 -&gt;&#39;, hhj.eat());
// hhj의 먹은 음식 -&gt; meat

let hhj2 = new Person(&#39;hhj2&#39;, &#39;24&#39;, &#39;Chumdan&#39;);

console.log(&#39;hhj2의 내년의 나이 -&gt;&#39;, hhj2.nextYear());
// hhj2의 내년의 나이 -&gt; 25

console.log(&#39;hhj2의 먹은 음식 -&gt;&#39;, hhj2.eat());
// console.log(&#39;hhj2의 먹은 음식 -&gt;&#39;, hhj2.eat());
// TypeError: hhj2.eat is not a function</code></pre>
<h2 id="1-2-class의-상속-extends">1-2. <code>Class</code>의 상속 (<code>extends</code>)</h2>
<p><code>class</code>에서 상속 개념을 이용할 수 있으며, <code>CSS</code>를 이용한 분들이라면 하나의 속성이 하위 속성에도 같이 적용되는 것처럼 <code>class</code>에서도 상속을 이용하면 기존의 <code>class</code>의 값을 모두 접근하여 사용할 수 있다.</p>
<p>상속은 <code>extends</code>를 써서 이용할 수 있다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  nextYear() {
    return Number(this.age) + 1;
  }
}

class introducePerson extends Person {
  introduce() {
    return `저는 ${this.name}이며, ${this.city}에서 살고 있고, 나이는 ${this.age}세입니다.`
  }
}

let hhj = new introducePerson(&#39;hhj&#39;, &#39;28&#39;, &#39;Gwangju&#39;);

console.log(hhj.introduce());
// 저는 hhj이며, Gwangju에서 살고 있고, 나이는 28세입니다.</code></pre>
<p>위의 코드와 같이 <code>introducePerson</code> 클래스에서 <code>Person</code>을 상속받았기 때문에 <code>this.city</code>와 <code>this.name</code>을 모두 사용할 수 있는 것을 확인할 수 있다.</p>
<h2 id="1-3-class의-super-사용">1-3. <code>Class</code>의 <code>super</code> 사용</h2>
<p><code>introducePerson</code> 하위 클래스에서 기존 <code>class</code>의 값을 가져다 쓰는 건 좋지만, 추가적으로 <code>introducePerson</code>이라는 하위 클래스에서만 사용하고 싶은 값이 있을 수도 있다.</p>
<p>이때 이용하는 것은 <code>super</code>라는 키워드로, 이는 객체의 부모가 가지고 있는 메서드를 호출할 수 있다.</p>
<p>자식 쪽의 추가적으로 사용할  초기값이 필요할 경우 <code>constructor</code>에 <code>super</code>로 부모 초기값을 세팅한 뒤 자식 <code>class</code>에서만 사용할 초기값을 따로 지정하는 것도 가능하며 <code>super</code> 기능을 이용해서 자식 <code>class</code>에서 부모 메서드를 호출할 수도 있다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  nextYear() {
    return Number(this.age) + 1;
  }
}

class introducePerson extends Person {
  constructor(name, age, city, job) {
    super(name, age, city);
    this.job = job;
  }

  introduce() {
    return `
    저는 ${this.name}이며, ${this.city}에서 살고 있고, 나이는 ${this.age}세입니다.
    내년에는 ${super.nextYear()}세이며, 하는 일은 ${this.job}입니다.
    `
  }
}

let hhj = new introducePerson(&#39;hhj&#39;, &#39;28&#39;, &#39;Gwangju&#39;, &#39;프론트엔드 개발자&#39;);

console.log(hhj.introduce());
// 저는 hhj이며, Gwangju에서 살고 있고, 나이는 28세입니다.
// 내년에는 29세이며, 하는 일은 프론트엔드 개발자입니다.</code></pre>
<p><code>class</code>를 이용할 경우 규칙성을 갖는 객체를 일관성 있게 만드는 게 가능하며, 상속을 통해서 기능 확장이 용이하다는 것 알 수 있었다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
</blockquote>
<p><a href="https://ordinary-code.tistory.com/22">김평범&#39;s OrdinaryCode - 자바스크립트에서 Class 사용하기</a>
<a href="https://ingryong.tistory.com/entry/JavaScript-%EC%83%9D%EC%84%B1%EC%9E%90Constructor-%EB%A7%8C%EB%93%A4%EA%B8%B0">잉룡&#39;s Devlog - 생성자(Constructor) 만들기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 브라우저 렌더링 과정]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Mon, 13 Feb 2023 08:49:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>파싱(<code>Parsing</code>)이란?
프로그래밍 언어로 작성된 파일을 실행시키기 위해 구문 분석(<code>Syntax Analysis</code>)을 하는 단계이다.
파일의 문자열들을 문법적 의미를 갖는 최소 단위인 &#39;토큰&#39;으로 분해하고, 이 토큰들을 문법적인 의미와 구조에 따라 노드라는 요소로 만든다.
이러한 단계에서 노드들은 상하관계를 반영해 트리를 형성하는데, 이 트리를 <code>Parse Tree</code>라고 한다.</p>
</blockquote>
<blockquote>
<p>렌더링(<code>Rendering</code>)이란?
<code>HTML</code>, <code>CSS</code>, <code>JavaScript</code> 파일을 파싱해, 브라우저에 시각적으로 출력하는 과정이다.</p>
</blockquote>
<hr>
<h1 id="1-브라우저-렌더링-전체-과정">1. 브라우저 렌더링 전체 과정</h1>
<ol>
<li><p>브라우저는 <code>HTML</code>, <code>CSS</code>, <code>JS</code>, 이미지, 폰트 등 리소소를 서버에 요청하고, 응답으로 받아온다.</p>
</li>
<li><p>브라우저 렌더링 엔진은 받아온 <code>HTML</code>, <code>CSS</code>를 파싱해 <code>Dom</code>, <code>CSSOM</code>을 생성하고, 이들을 결합해 <strong><code>Render Tree</code>를 생성</strong>한다.</p>
</li>
<li><p>브라우저 <code>JS</code> 엔진은 받아온 <code>JS</code>를 파싱해 <strong><code>AST</code>를 생성</strong>하고, <strong>바이트 코드로 변환해 실행</strong>한다.</p>
</li>
<li><p>렌더트리를 기반으로 <code>HTML</code> 요소의 <strong>레이아웃(위치, 크기)을 계산</strong>한다.</p>
</li>
<li><p>화면에 <strong><code>HTML</code>요소를 페인팅</strong>한다.</p>
</li>
</ol>
<h2 id="1-1-요청-응답">1-1. 요청, 응답</h2>
<blockquote>
<p>브라우저는 <code>HTML</code>, <code>CSS</code>, <code>JS</code>, 이미지, 폰트 등 리소스를 서버에 요청하고, 응답으로 받아온다.</p>
</blockquote>
<p>서버가 가지고 있는 <code>HTML</code>, <code>CSS</code>, <code>JavaScript</code> 파일을 브라우저애서 서버에게 요청하고, 응답으로 받아와야 한다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/f1332f9f-3739-4fd1-96da-96cc0d2627ff/image.png" alt=""></p>
<p>브라우저에 있는 주소창에 위와 같은 <code>URL</code>을 입력하고 엔터키를 누르면, <code>URL</code>의 호스트 이름이 <code>DNS</code>(도메인 네임 서비스)를 통해 진짜 주소인 <code>IP</code> 주소로 변환되고, 이 <code>IP</code> 주소를 갖는 서버에게 요청을 보낸다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/dd5082ff-15f1-4dc0-870e-20f2036a9643/image.png" alt=""></p>
<p>서버는 기본적으로 보통 <code>index.html</code>을 응답으로 주도록 설정되어 있다.</p>
<p>예를 들어, <a href="https://www.google.com">https://www.google.com</a> 을 검색하면 사실은 <a href="https://www.google.com/index.html%EC%9D%84">https://www.google.com/index.html을</a> 요청하는 것과 다름 없다.</p>
<p>이 요청에 대해 구글 서버는 클라이언트에 <code>index.html</code> 파일을 전달 해주며, 다른 파일을 요청하고 싶다면 뒤에 다른 파일 경로를 적거나, <code>JavaScript</code>를 통해서 동적으로 요청할 수도 있다.</p>
<h2 id="1-2-파싱-생성">1-2. 파싱, 생성</h2>
<h3 id="1-2-1-html-파싱-dom-생성">1-2-1. <code>HTML</code> 파싱, <code>DOM</code> 생성</h3>
<blockquote>
<p>브라우저 렌더링 엔진은 받아온 <code>HTML</code>, <code>CSS</code>를 파싱해 <code>DOM</code>, <code>CSSOM</code>을 생성하고, 이들을 결합해 렌더 트리를 생성한다.</p>
</blockquote>
<p>응답으로 받아온 <code>HTML</code> 문서는 오직 텍스트로만 이루어져 있다.</p>
<p>이 텍스트들 우리가 알아볼 수 있도록 이 문서를 브라우저가 이해할 수 있는 형태로 바꾸는 작업이 필요한데, 여기서 말하는 형태가 바로 <code>DOM</code> 구조이다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/c851c39f-033d-4e2e-8b2d-2c7f439e576c/image.png" alt=""></p>
<p>위의 그림은 서버에서 받아온 파일을 브라우저가 이해하기까지의 과정이다.</p>
<ol>
<li><p>바이트 (<code>Bytes</code>) : 서버는 브라우저에게 2진수 형태의 <code>HTML</code> 문서를 응답으로 준다.</p>
</li>
<li><p>문자열 (<code>Characters</code>) : 문서는 <code>&lt;meta&gt;</code>의 <code>charset</code> 속성에 지정된 방식으로 문자열로 인코딩 된다.(ex : <code>UTF-8</code>) 서버는 이 인코딩 방식은 응답 헤더에 담아준다.</p>
</li>
<li><p>토큰 (<code>Tokens</code>) : 문자열 형태의 HTML문서를 &#39;토큰&#39;단위로 분해한다. (문법적 의미를 갖는 코드의 최소 단위)</p>
</li>
<li><p>노드 (<code>Nodes</code>) : 각 토큰을 객체로 변환해, 노드를 생성한다. (<code>DOM</code>을 구성하는 기본 요소)</p>
</li>
<li><p><code>DOM</code> : <code>HTML</code> 문서의 요소들의 중첩관계를 기반으로 노드들을 트리 구조로 구성한다. 이 트리를 <code>DOM</code>이라고 한다.</p>
</li>
</ol>
<p>위와 같은 과정을 거쳐서 <code>HTML</code> 문서가 파싱되고, <code>DOM</code> 이라는 결과물을 생성하게 된다.</p>
<p>위와 같은 복잡한 과정을 거치는 이유는 <code>DOM</code>은 <code>Document Object Model</code>의 줄임말로, 우리말로는 문서 객체 모델이라 할 수 있다.</p>
<p>말 그래도 <strong>문서를 객체로 바꾼 모델</strong>로, 브라우저는 <code>JavaScript</code> 언어만 알아듣는데, <code>JavaScript</code>는 <code>HTML</code>의 태그나 속성들을 바로 다룰 수 없기 때문에, 다룰 수 있는 형태인 &#39;객체&#39;로 바꿔주어야 한다.</p>
<p>그래야 브라우저도 <code>HTML</code> 문서를 이해할 수 있게 되기 때문에 이러한 과정을 거친다.</p>
<h3 id="1-2-2-css-파싱-cssom-생성">1-2-2. CSS 파싱, CSSOM 생성</h3>
<p>앞서 html 파일을 파싱하다가 <code>&lt;link&gt;</code>, <code>&lt;style&gt;</code> 태그를 만나면 파싱을 잠시 멈추고 리소스 파일을 서버로 요청한다.</p>
<p>이 태그들은 <code>CSS</code> 파일을 가져올 때 보통 쓰는데, 이렇게 가져온 <code>CSS</code> 파일도 <code>HTML</code>과 마찬가지로 파싱을 한다. 서버에서 받아온 2진수 파일을 문자열로 인코딩하고, 토큰 단위로 나누고, 노드를 생성하고, 트리를 만들고.. <strong>이렇게 파싱해 만든 트리는 <code>CSSOM</code> 이라고 한다</strong>.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/bb990413-41b8-4bc1-b4f5-1595a2abda8b/image.png" alt=""></p>
<p>위의 그림처럼 <code>CSSOM</code>은 <code>CSS</code>의 속성이 상속되기 때문에, 이를 반영한다는 점이다.</p>
<p>예를 들어 <code>ul</code> 이 부모 요소이고, <code>li</code>를 자식 요소로 가진다고 생각하면, 아래 코드처럼 <code>ul</code>는 파란색 속성을 가지고 있는데, 이 속성은 자식 요소인 <code>li</code>도 상속받게 된다.</p>
<p>따라서 <code>li</code>는 상속받은 <code>color: blue</code>와 자신이 가지고 있던 <code>font-size</code> 속성 두 가지를 갖게 된다.</p>
<h3 id="1-2-3-렌더-트리-생성">1-2-3. 렌더 트리 생성</h3>
<p><code>DOM</code>과 <code>CSSOM</code>은 굉장히 비슷하게 생겼지만, 서로 다른 속성들을 가진 독립적인 트리들이다.</p>
<p><code>HTML</code>은 구조를, <code>CSS</code>는 디자인을 담당하기 때문에 둘을 합치는 작업이 필요하다.</p>
<p>렌더 트리는 이름처럼 렌더링을 목적으로 만드는 트리이며, 렌더링은 브라우저가 이제 진짜로 사용자에게 보여주기 위한 화면을 그리는 과정이기 때문에, 보이지 않을 요소들은 이 트리에 포함하지 않는다.</p>
<p>예를 들어, <code>DOM</code>에서는 <code>meta</code>태그같은 정보 전달 목적의 태그나, <code>CSSOM</code>에서는 <code>display: none</code>으로 보이지 않게 해둔 요소(정확히는 노드)들은 렌더 트리에서는 제외된다.</p>
<blockquote>
<p>단, <code>visibility: hidden</code>은 레이아웃 트리에 포함되니 주의해야 한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/d28efdb7-ed1f-46e4-abd5-84c0adf6462b/image.png" alt=""></p>
<p>위의 그림처럼 <code>DOM</code>, <code>CSSOM</code>에 있던 속성들이 합쳐져 렌더트리를 구성하는 것을 확인할 수 있지만, 렌더 트리는 아직까지도 텍스트로 구성된 객체로 밖에 보이지 않는다.</p>
<p>실제로 우리가 보는 페이지를 만들기 위해서는 &#39;페인팅&#39;이라는 작업을 거쳐야 한다.</p>
<p>페인팅 작업은 렌더트리의 노드들이 가지고 있는 속성들을 바탕으로 이루어지는데, 이 작업은 잠시 후에 다시 자세히 알아보도록 하고 우선은 <code>JavaScript</code> 파일은 어떻게 해석이 되는지부터 잠시 살펴본다.</p>
<h2 id="1-3-javascript-파싱">1-3. <code>JavaScript</code> 파싱</h2>
<blockquote>
<p>브라우저 <code>JS</code> 엔진은 받아온 <code>JS</code>를 파싱해 <code>AST</code>를 생성하고, 바이트 코드로 변환해 실행한다.</p>
</blockquote>
<p>렌더링 엔진은 <code>HTML</code> 파일을 한줄씩 파싱하며 <code>DOM</code>을 생성하다가 <code>JavaScript</code> 코드들 불러오는 <code>&lt;script&gt;</code> 태그를 만날 때도 파싱을 잠시 멈춘다.</p>
<p>그리고 나서 <code>src</code> 속성에 적혀있는 파일을 서버에 요청해 받아오고, 이렇게 받아온 <code>js</code> 파일도 마찬가지로 파싱을 해야하는데, 이 파싱은 브라우저 렌더링 엔진이 직접하지 않고, <code>JavaScript</code> 엔진이 담당하게 된다.</p>
<p>이 때 렌더링 엔진은 <code>JS</code> 엔진에게 제어권을 아예 넘겨주기 때문에, <code>HTML</code> 파싱을 멈췄다가 <code>JS</code> 파싱이 전부 되면 다시 제어권을 돌려받아 파싱을 다시 시작하는 것이다.</p>
<p><code>JS</code> 엔진은 <code>js</code> 파일의 코드를 파싱해서 컴퓨터가 이해할 수 있는 기계어로 변환하고 실행한다.</p>
<p>좀 더 구체적으로 살펴보면, 먼저 단순한 텍스트 문자열인 코드를 토큰 단위로 분해하며, 이렇게 분해된 토큰에 문법적인 의미와 구조가 더해져, <code>AST</code>(추상 구문 트리) 라는 트리가 완성된다.</p>
<p>구체적인 속성은 다르지만, 이전에 봤던 과정들과 비슷해 보이며, 아래 그림에서 맨 왼쪽의 코드가 바로 다음의 트리 구조로 바뀌는 부분이 여기까지의 내용에 해당한다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/496c8b15-1244-4ca8-a123-4f58946efbb1/image.png" alt=""></p>
<p>이제 이렇게 코드를 해석해서 만든 <code>AST</code>라는 트리를 실제로 실행할 수 있도록 만들어야 한다.</p>
<p>코드의 실제 실행은 인터프리터가 담당하는데, 인터프리터가 알아들을 수 있도록 하기 위해서는 AST트리를 바이트 코드라는 중간 수준의 코드로 변환해야 한다.</p>
<p>이 변환은 바이트 코드 생성기가 담당해주며, 이제 위의 그림에서 가장 오른쪽에 있는 형태로 바뀌어 받아온 <code>js</code>파일 내용이 실제로 실행된다.</p>
<h2 id="1-4-레이아웃리플로우">1-4. 레이아웃(리플로우)</h2>
<blockquote>
<p>렌더 트리를 기반으로 <code>HTML</code> 요소의 레이아웃(위치, 크기)을 계산한다.</p>
</blockquote>
<p>레이아웃은 요소의 기하학적인 속성들을 찾는 과정이며, 아까 만들었던 렌더트리가 여기서 사용되니 다시 떠올려야 한다.</p>
<p>렌더 트리에는 요소들의 위치나 크기와 관련된 정보들이 들어있었다.</p>
<p>하지만 이 정보들은 각 요소들에 대한 정보일 뿐, 전체 화면에서 정확히 어디에 위치할 것인지에 대해서는 아직 알지 못하며, 이런 계산을 하는 단계가 레이아웃 단계이다.</p>
<p>브라우저는 각 요소들이 전체 화면에서 어디에, 어떤 크기로 배치되어야 할 지 파악하기 위해 렌더트리의 맨 윗부분부터 아래로 내려가며 계산을 진행하며, 모든 값들은 절대적인 단위인 <code>px</code>값으로 변환된다.</p>
<p>예를들어 우리가 <code>&lt;div&gt;</code>요소 하나만 띄우도록 코드를 작성했고, width를 50%로 지정해두었다면, 이 값은 전체 화면 크기(<code>viewport</code>)의 절반 크기로 계산되고, 절대적인 값인 px 단위로 변환되는 식이다.</p>
<h2 id="1-5-페인팅">1-5. 페인팅</h2>
<blockquote>
<p>화면에 <code>HTML</code> 요소를 페인팅한다.</p>
</blockquote>
<p>이제 위치에 대한 계산도 마쳤으니, 정말로 화면에 보여줄 차례이다.</p>
<p>브라우저 화면은 픽셀이라고 하는 정말 작은 점들로 이루어져 있으며, 각각 정보를 가진 픽셀들이 모여 하나의 이미지, 화면을 구성하는 것이다.</p>
<p>따라서 화면에 색상을 입히고, 어떤 요소를 보여주기 위해서는 이 픽셀에 대한 정보가 있어야 하고, 페인팅은 이러한 픽셀들을 채워나가는 과정이다.</p>
<p>따라서 이 과정을 마지막으로 우리는 단순한 텍스트에 불과했던 파일 내용들을 이미지화된 모습으로 브라우저 화면을 통해 볼 수 있게되는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/d9ea80b6-95d9-4dd4-a186-d1f4ea46dfe3/image.png" alt=""></p>
<hr>
<h1 id="2-reflow리플로우-repaint리페인트">2. <code>Reflow</code>(리플로우), <code>Repaint</code>(리페인트)</h1>
<blockquote>
<p>리플로우(<code>Reflow</code>) = 레이아웃 계산을 다시하는 것
리페인트(<code>Repaint</code>) = 새로운 렌더트리를 바탕으로 다시 페인트를 하는 것</p>
</blockquote>
<p>만약 사용자가 브라우저 화면을 늘리거나 줄이는 등 크기를 조절하거나, 어떤 버튼을 눌러 화면에 요소가 추가되거나 삭제되는 경우가 생기면, 당연히 화면에 있던 요소들의 위치나 크기 등이 바뀌는 일이 생기게 될 것이다.</p>
<p>굉장히 당연하게 여겨지지만, 이렇게 화면에 나타나는 모습을 바꾸기 위해서는 모든 요소들의 위치와 크기를 다시 계산하고, 다시 그려서 보여주어야 한다.</p>
<p>이렇게 어떤 <strong>인터랙션으로 인해 앞서 보았던 레이아웃, 페인팅 과정을 반복하는 것을 리플로우, 리페인트</strong>라고 한다.</p>
<pre><code class="language-javascript">const makeDiv = document.createElement(&#39;div&#39;);</code></pre>
<p>위의 코드는 <code>JavaScript</code>를 통해 DOM을 조작하는 코드이다.</p>
<p><code>DOM</code>은 단순히 <code>HTML</code> 파일의 정보만 담고있게 아니라, 이렇게 <code>JavaScript</code>를 통해 요소들을 동적으로 조작할 수 있도록 <code>DOM API</code>라는 것을 제공한다. <code>CSS</code>도 마찬가지로 이런식으로 조작이 가능하다. 이렇게 <code>JavaScript</code> 조작으로 변경이 일어나면, <code>DOM</code> 트리를 다시 구성하는 것으로 시작해 <code>CSSOM</code>와 합쳐져 새 렌더 트리를 생성한다.</p>
<p>그리고 레이아웃과 페인트 과정을 또다시 거쳐서 화면에 보여진다.</p>
<p><code>DOM</code> 조작은 리플로우, 리페인팅이 일어나는 대표적인 예시라고 할 수 있다.</p>
<p>물론 레이아웃과 페인트는 별개의 작업이기 때문에, 하나 씩만 발생할 수도 있고, 둘 다 발생할 수도 있으며, 위치나 크기에 대한 변경만 있다면 레이아웃 작업만 다시하면 되고, 요소의 색상이나 보이는지 여부 같은 스타일에 대한 사항에 대한 변경만 있다면 페인팅 작업만 다시하면 되기 때문이다.</p>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/66ae9347-770e-4d68-a488-0ef1d409dd81/image.png" alt=""></p>
<h2 id="2-1-reflow">2-1. <code>Reflow</code></h2>
<p><code>Reflow</code>는 렌더링 엔진에서 요소를 배치하는 과정을 의미한다.</p>
<p>렌더 트리 구축 단계에서 <code>DOM</code> 트리와 스타일 규칙을 합쳐서 렌더 트리를 만들고, 여기에서 <code>Reflow</code>를 통해 각각의 요소들의 레이아웃을 위치시킨다.</p>
<p>여기서 렌더 트리는 <code>DOM</code> 요소를 기반으로 만들어지지만, 완전히 대응되지는 않는다.</p>
<p><code>DOM</code> 트리가 문서의 구조를 나타낸다면 렌더 트리는 문서의 시각적 구조를 나타낸다.</p>
<p>예를 들어 스타일에 <code>display: none</code> 속성이 있다면 <code>DOM</code>에는 존재하지만 시각적으로는 없기에 렌더 트리에는 할당되지 않는다.</p>
<p><code>Reflow</code>가 발생하는 경우는 다음과 같다.</p>
<ul>
<li><p><code>DOM</code> 노드의 추가, 제거</p>
</li>
<li><p><code>DOM</code> 노드의 위치 변경</p>
</li>
<li><p><code>DOM</code> 노드의 크기 변경</p>
<blockquote>
<p><code>margin</code>, <code>padding</code>, <code>border</code>, <code>width</code>, <code>height</code> 등</p>
</blockquote>
</li>
<li><p><code>CSS3</code> 애니메이션과 트랜지션</p>
</li>
<li><p>폰트 변경, 텍스트 내용 변경</p>
</li>
<li><p>이미지 크기 변경</p>
</li>
<li><p><code>offset</code>, <code>scrollTop</code>, <code>scrollLeft</code>와 같은 계산된 스타일 정보 요청</p>
</li>
<li><p>페이지 초기 렌더링</p>
</li>
<li><p>윈도우 리사이징</p>
</li>
</ul>
<h2 id="2-2-repaint">2-2. <code>Repaint</code></h2>
<p><code>Repaint</code>는 렌더 트리가 탐색되고 <code>paint</code> 메서드가 호출되어서 <code>UI</code> 기반의 구성 요소를 사용해서 그리는 과정이다.</p>
<p><code>Repaint</code>가 이루어지기 위해서는 렌더 트리가 있어야 하고 따라서 <code>Reflow</code> 작업이 이루어진 후에 <code>Repaint</code> 작업이 이루어지는 것을 알 수 있다.</p>
<p>화면의 구조가 변경이 될 때는 <code>Reflow</code>와 <code>Repaint</code>가 모두 발생한다.</p>
<p>다만 <code>Repaint</code>가 발생하기 위해서 항상 <code>Reflow</code>가 발생해야 하는 것은 아니다.</p>
<p><code>Reflow</code>가 발생하지 않고 <code>Repaint</code>만 발생하는 경우도 있는데, 예를 들면 레이아웃에 영향을 주지 않는 엘리먼트 개별의 변화에 대해서는 <code>Repaint</code>만 발생한다.</p>
<blockquote>
<p><code>color</code>, <code>background-color</code>, <code>visibility</code> 같은 속성의 경우, 곧바로 <code>Repaint</code> 과정만 발생한다.</p>
</blockquote>
<h2 id="2-3-reflow-최적화">2-3. <code>Reflow</code> 최적화</h2>
<blockquote>
<p><code>Reflow</code>는 비용을 발생시키는 절차이므로 가능한 안 하는 것이 성능 측면에서 유리하며, 아래의 사항을 통해 <code>Reflow</code> 작업을 줄일 수 있다.</p>
</blockquote>
<h3 id="2-3-1-가장-하위-노드의-클래스를-변경을-통한-스타일-변경">2-3-1. 가장 하위 노드의 클래스를 변경을 통한 스타일 변경</h3>
<p><code>DOM</code> 노드의 크기 또는 위치가 변경되면 하위 노드와 상위 노드에도 영향을 미칠 수 있다.</p>
<p>이 때 가장 하위 노드의 스타일을 변경할 경우, 전체 노드가 아닌 일부 노드로 <code>Reflow</code>를 영향을 최소화 할 수 있다.</p>
<blockquote>
<p>전체적으로 큰 노드를 뒤흔드는 것보다 그 하위의 변경할 부분만을 변경하여 <code>Reflow</code>의 규모를 줄이는 방식으로 정리할 수 있다.</p>
</blockquote>
<h3 id="2-3-2-인라인-스타일inline-사용-줄이기">2-3-2. 인라인 스타일(<code>inline</code>) 사용 줄이기</h3>
<p>인라인 스타일은 <code>HTML</code>이 파싱될 때, 레이아웃에 영향을 미쳐 추가 <code>Reflow</code>를 발생시킨다.</p>
<p>또한 관심사 분리가 제대로 이루어지지 않으면 유지 보수가 힘들어 진다.</p>
<h3 id="2-3-3-애니메이션이-있는-노드는-position을-fixed-또는-absolute로-지정">2-3-3. 애니메이션이 있는 노드는 <code>position</code>을 <code>fixed</code> 또는 <code>absolute</code>로 지정</h3>
<p>애니메이션 효과는 많은 <code>Reflow</code> 비용을 발생시킨다.</p>
<p><code>position</code> 속성을 <code>fixed</code> 또는 <code>absolute</code>의 값으로 지정해서 지정된 노드를 전체 노드에서 분리시켜 해당 노드에서만 <code>Reflow</code>가 발생하도록 제한시킬 수 있다.</p>
<p>애니메이션 효과를 줘야 하는 노드에 <code>position</code> 속성이 적용이 되지 않았다면 애니메이션 시작 시 <code>position</code> 속성 값을 <code>fixed</code> 또는 <code>absolute</code>로 변경하였다가 애니메이션 종료 후 다시 원복시켜서 렌더링을 최적화 할 수 있다.</p>
<h3 id="2-3-4-table-레이아웃-사용-줄이기">2-3-4. table 레이아웃 사용 줄이기</h3>
<p><code>&lt;table&gt;</code>은 점진적으로 렌더링 되지 않고, 모두 로드되고 테이블 너비가 계산된 후에 화면에 그려진다.</p>
<p>테이블 안의 컨텐츠의 값에 따라 테이블 너비가 계산된다는 의미로, 테이블 컨텐츠의 작은 변경만 있어도 테이블 너비가 다시 계산되고 테이블의 모든 노드들이 <code>Reflow</code>가 발생한다.</p>
<p>이러한 이유로 <code>&lt;table&gt;</code>을 레이아웃 용도로 사용하는 일은 피해야 한다.</p>
<h3 id="2-3-5-css-하위-선택자-최소화">2-3-5. <code>CSS</code> 하위 선택자 최소화</h3>
<p><code>CSS</code> 하위 선택자를 최소화 하는 것은 <code>Reflow</code> 횟수를 줄이는 방법이 아니라 렌더 트리 계산을 최소화 하는 방법에 대한 내용이다.</p>
<ul>
<li><p>예시 코드</p>
<pre><code class="language-html">&lt;div class=&quot;reflow_box&quot;&gt;
  &lt;ul class=&quot;reflow_list&quot;&gt;
    &lt;li&gt;
      &lt;button type=&quot;button&quot; class=&quot;btn&quot;&gt;버튼&lt;/button&gt;
    &lt;li&gt;
    &lt;li&gt;
      &lt;button type=&quot;button&quot; class=&quot;btn&quot;&gt;버튼&lt;/button&gt;
    &lt;li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</code></pre>
</li>
<li><p><code>CSS</code> 코드</p>
<pre><code class="language-css">/* 잘못된 예 */
.reflow_box .reflow_list li .btn{
  display:block;
}
/* 올바른 예 */
.reflow_list .btn {
  display:block;
}</code></pre>
</li>
</ul>
<p>위의 코드처럼 <code>CSS</code> 하위 선택자를 최소화하는 것 또한 렌더링 성능 향상에 도움이 된다.</p>
<p>렌더 트리는 <code>DOM</code>과 <code>CSSOM</code>이 합쳐져서 만들어지는데, <code>DOM</code>은 <code>HTML</code>이 파싱되어 만들어진 트리이고, <code>CSSOM</code>은 <code>CSS</code>가 파싱되어 만들어진 트리이다.</p>
<p>두 트리를 결합하여 렌더 트리를 만드는데, <code>CSS</code> 하위 선택자가 많아지면 <code>CSSOM</code> 트리의 깊이(<code>Depth</code>)가 깊어지게 되고 결국 렌더 트리를 만드는 시간이 더 오래 걸리게 된다.</p>
<h3 id="2-3-6-숨겨진-노드의-스타일-변경">2-3-6. 숨겨진 노드의 스타일 변경</h3>
<p><code>Reflow</code> 비용을 줄이기 위해서 DOM 노드 사용을 최소화 해야 한다.</p>
<p>한 가지 방법은 <code>DOM Fragment</code>를 사용하여 <code>DOM</code>을 추가할 때 마다 <code>DOM</code> 접근을 최소화 하는 방법이다.</p>
<pre><code class="language-js">const frag = document.createDocumentFragment();
const ul = frag.appendChild(document.createElement(&#39;ul&#39;));

for (let i = 1; i &lt;= 3; i++) {
  li = ul.appendChild(document.createElement(&#39;li&#39;));
  li.textContent = `item ${ i }`;
}

document.body.appendChild(frag);</code></pre>
<p>위의 코드처럼 <code>createDocumentFragment</code>를 사용하여 한 번에 <code>DOM</code>을 추가하여 <code>DOM</code> 자체에 직접적인 접근을 최소화할 수 있다.</p>
<h3 id="2-3-7-캐시-활용">2-3-7. 캐시 활용</h3>
<p>브라우저는 레이아웃 변경을 큐에 저장했다가 한 번에 실행하여 <code>Reflow</code>를 최소화 한다.</p>
<p>하지만 <code>offset</code>, <code>scrollTop</code>과 같은 계산된 스타일 정보를 요청할 때마다 정확한 정보를 제공하기 위해 큐를 비우고 모든 변경 사항을 적용한다.</p>
<pre><code class="language-js">// 안좋은 예시
for (let i = 0; i &lt; len; i++) {
  el.style.top = `${ el.offsetTop + 10 }px`;
  el.style.left = `${ el.offsetLeft + 10 }px`;
}

// 좋은 예시
let top = el.offsetTop, left = el.offsetLeft, elStyle = el.style;

for (let i = 0; i &lt; len; i++) {
  top += 10;
  left += 10;
  elStyle.top = `${ top }px`;
  elStyle.left = `${ left }px`;
}</code></pre>
<p>이런 낭비를 해결하기 위해 위의 코드와 같이 스타일 정보를 변수에 저장하여 <code>offset</code>, <code>scrollTop</code> 등의 값 요청을 최소화해야 한다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://joooing.tistory.com/entry/rendering">joooing - 웹페이지가 사용자에게 보여지기까지 (브라우저 렌더링 과정)</a>
<a href="https://chanyeong.com/blog/post/43">CHANYEONG - 브라우저 렌더링과 최적화</a>
<a href="https://devowen.com/463#3.%20%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98%EC%9D%B4%20%EC%9E%88%EB%8A%94%20%EB%85%B8%EB%93%9C%EB%8A%94%20position%EC%9D%84%20fixed%20%EB%98%90%EB%8A%94%20absolute%EB%A1%9C%20%EC%A7%80%EC%A0%95%ED%95%9C%EB%8B%A4.-1">Web Frontend Developer - Reflow와 Repaint에 대하여</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 호이스팅(Hoisting)이란?]]></title>
            <link>https://velog.io/@hyungjin_han/JavaScript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@hyungjin_han/JavaScript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Fri, 10 Feb 2023 05:42:46 GMT</pubDate>
            <description><![CDATA[<h1 id="1-호이스팅이란">1. 호이스팅이란?</h1>
<p>호이스팅(<code>Hoisting</code>)은 코드를 실행하기 전 변수선언/함수선언을 해당 스코프의 최상단으로 끌어올리는 것이 아닌, <strong>해당 스코프를 최상단으로 끌어 올려진 것 같은 현상</strong>을 말한다.</p>
<p>JavaScript 엔진은 코드를 실행하기 전 실행 가능한 코드를 형상화하고 구분하는 과정(<em>실행 컨텍스트를 위한 과정</em>)을 거친다.</p>
<blockquote>
<p>실행 컨텍스트란?
실행 가능한 <strong>코드가 실행되기 위해 필요한 환경을 의미</strong>하고 실행되기 전, 이러한 실행 컨텍스트 과정(코드를 구분하는 과정)을 거친다.</p>
</blockquote>
<p>JavaScript 엔진은 코드를 실행하기 전 실행 컨텍스트를 위한 과정에서 모든 선언(<code>var</code>, <code>let</code>, <code>const</code>, <code>function</code>, <code>class</code>)을 스코프에 등록한다.</p>
<p>코드 실행 전, 이미 변수선언/함수선언이 저장되어 있기 때문에 선언문보다 참조/호출이 먼저 나와도 오류 없이 동작한다.</p>
<blockquote>
<p>정확히는 <code>var</code> 키워드로 선언한 변수와 함수 선언문일 경우 오류 없이 동작하며, 이는 <strong>선언이 파일의 맨 위로 끌어 올려진 것처럼</strong> 보이게 한다.</p>
</blockquote>
<p>위에서 말한 호이스팅(<code>Hoisting</code>)이라는 현상이란 선언이 코드 실행 보다 먼저 메모리에 저장되는 과정으로 인한 현상을 말한다.</p>
<p>그래서 JavaScript 실행 컨텍스트에 대한 이해하는 것이 호이스팅을 이해하는데 도움이 된다.</p>
<blockquote>
<p><code>scope</code>, <code>hoisting</code>, <code>this</code>, <code>function</code>, <code>closure</code> 등의 동작 원리를 담고 있는 JavaScript 핵심원리이다. 코드를 보고 실행 컨텍스트를 이해할 수 있어야 코드 독해, 디버깅을 할수 있다.</p>
</blockquote>
<hr>
<h1 id="2-변수-호이스팅-var-let-const">2. 변수 호이스팅 (<code>var</code>, <code>let</code>, <code>const</code>)</h1>
<p>JavaScript의 모든 선언에는 호이스팅(<code>Hoisting</code>)이 일어난다.</p>
<p>하지만 <code>let</code>, <code>const</code>, <code>class</code>를 이용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다.</p>
<p><code>var</code> 키워드로 선언된 변수와는 달리 <code>let</code> 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(<code>ReferenceError</code>)가 발생한다.</p>
<p>이러한 현상은 <code>let</code> 키워드로 선언된 변수가 스코프의 시작에서 변수의 선언까지 <strong>일시적 사각지대(<code>Temporal Dead Zone</code>, <code>TDZ</code>)에 빠지기 때문</strong>이다.</p>
<blockquote>
<p><code>TDZ</code>란?
스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말하며, <code>let</code> 키워드로 선언된 변수 또한 선언 전, 실행 컨텍스트 변수 객체에 등록이 되어 호이스팅이 되지만, 이 <code>TDZ</code> 구간에 의해 메모리가 할당이 되질 않아 참조 에러(<code>ReferenceError</code>) 발생하는 현상을 말한다.</p>
</blockquote>
<blockquote>
<p>중요한 점은 이 호이스팅이라는 용어가 <strong>선언이 먼저 메모리에 저장되었다</strong>는 것을 의미하기 때문에 즉, <strong>선언이 끌어올려진다</strong>는 의미이기 때문에 모든 선언은 호이스팅이 일어난다는 말은 참이 된다.</p>
<blockquote>
<p>즉, 호이스팅이 파일의 맨 위로 끌어올려진 것 같은 현상을 의미할 때 선언문 이전에 참조해서 에러를 발생시킨다고 호이스팅이 일어나지 않은 것은 아니라는 의미이다.</p>
</blockquote>
</blockquote>
<p>정확히는 선언이 끌어올려진 현상이지만, 선언이 코드 실행 전에 메모리에 저장되었다는 의미이다.</p>
<p>하지만 이러한 오류가 나는 이유는 <code>var</code> 키워드는 선언과 함께 <code>undefined</code>로 초기화 되어 메모리에 저장되지만, <code>let</code>과 <code>const</code>는 초기화 되지 않은 상태로 선언만 메모리에 저장되기 때문이다.</p>
<p><strong>초기화 되지 않으면 변수를 참조할 수 없으며</strong>, 그렇기 때문에 참조 에러(<code>ReferenceError</code>)를 발생시키며,
<code>let</code>과 <code>const</code>에도 호이스팅이 일어나기 때문에 에러를 일으키는 것이다.</p>
<p>예시로</p>
<pre><code class="language-javascript">let foo = 1;
{
  console.log(foo);
  // Uncaught ReferenceError: Cannot access &#39;foo&#39; before initialization
  let foo = 2;
}</code></pre>
<p>위의 코드에서 만약에 호이스팅이 일어나지 않는다면 에러가 발생하지 않을 것이다.</p>
<p>하지만 선언과 동시에 호이스팅이 되었기 때문에 블록 스코프에서 <code>foo</code>를 찾을 수 없다.</p>
<pre><code class="language-javascript">var foo = 1;
{
  console.log(foo); // 1
  var foo = 2;
  console.log(foo); // 2
}</code></pre>
<p>위의 코드처럼 <code>var</code> 키워드의 경우, 초기 선언과 동시에 <code>undefined</code>로 초기화 되어 메모리에 저장되기 때문에 에러가 나지 않는다.</p>
<hr>
<h1 id="3-변수의-생성의-단계와-호이스팅의-원리">3. 변수의 생성의 단계와 호이스팅의 원리</h1>
<h2 id="3-1-변수의-생성-단계">3-1. 변수의 생성 단계</h2>
<p>변수는 3단계에 걸쳐서 생성된다.</p>
<h4 id="1단계-선언-단계-declaration-phase">1단계: 선언 단계 (<code>Declaration phase</code>)</h4>
<ul>
<li><p>변수를 실행 컨텍스트의 변수 객체에 등록한다.</p>
</li>
<li><p>이 변수 객체는 스코프가 참조하는 대상이 된다.</p>
</li>
</ul>
<h4 id="2단계-초기화-단계initialization-phase">2단계: 초기화 단계(<code>Initialization phase</code>)</h4>
<ul>
<li><p>변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.</p>
</li>
<li><p>이 단계에서 변수는 <code>undefined</code>로 초기화 된다.</p>
</li>
</ul>
<h4 id="3단계-할당-단계assignment-phase">3단계: 할당 단계(Assignment phase)</h4>
<ul>
<li><code>undefined</code>로 초기화된 변수에 실제 값을 할당한다.</li>
</ul>
<h2 id="3-2-호이스팅의-원리">3-2. 호이스팅의 원리</h2>
<h3 id="3-2-1-var-키워드의-변수-선언">3-2-1. <code>var</code> 키워드의 변수 선언</h3>
<p><code>var</code> 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이뤄지며, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보한 후, <code>undefined</code>로 초기화한다.</p>
<p>따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않지만, <code>undefined</code>를 반환한다.</p>
<p>이후 변수 할당문에 도달하면 비로소 값이 할당된다.</p>
<h3 id="3-2-2-let-const-class-키워드의-변수-선언">3-2-2. <code>let</code>, <code>const</code>, <code>class</code> 키워드의 변수 선언</h3>
<p><code>let</code>, <code>const</code>, <code>class</code> 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행되며, 스코프에 변수를 등록(선언 단계)하지만, 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후) 이뤄진다.</p>
<p>초기화 이전에 변수에 접근하려고 하면 참조 에러(<code>ReferenceError</code>)가 발생하며, 이는 아직 변수가 초기화됮 않았기 때문이다.</p>
<p>즉, 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문에 스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다.</p>
<hr>
<h1 id="4-호이스팅-예제">4. 호이스팅 예제</h1>
<h2 id="4-1-변수-선언에서의-호이스팅-예시">4-1. 변수 선언에서의 호이스팅 예시</h2>
<h3 id="4-1-1-var-키워드의-호이스팅-예제">4-1-1. <code>var</code> 키워드의 호이스팅 예제</h3>
<pre><code class="language-javascript">// 선언이 끌어올려 지는 것이지 할당이 끌어 올려지는 것이 아니다.

name = &#39;HHJ&#39;;
// 선언 없으면 var로 선언한 것과 동일

console.log(name); // &quot;HHJ&quot;
// 별도의 var 선언 없이도 작동

var name;</code></pre>
<h3 id="4-1-2-let-키워드의-호이스팅-예제">4-1-2. <code>let</code> 키워드의 호이스팅 예제</h3>
<pre><code class="language-javascript">name = &#39;HHJ&#39;;
// 선언 없으면 var로 선언한 것과 동일하게 작동하지만, let의 호이스팅으로 인해 오류

let name;

console.log(name);
// Uncaught ReferenceError: Cannot access &#39;text&#39; before initialization</code></pre>
<hr>
<h3 id="4-1-3-함수-선언의-호이스팅-예제">4-1-3. 함수 선언의 호이스팅 예제</h3>
<pre><code class="language-javascript">foo1(); // 함수 선언문에서는 호이스팅 일어남
foo2(); // 함수 표현식이라서 호이스팅이 일어나지 않음

function foo1() {
  console.log(&#39;Hello&#39;); // &quot;Hello&quot;
}

var foo2 = function() {
  console.log(&#39;world&#39;);
  // Uncaught TypeError: foo2 is not a function
}</code></pre>
<hr>
<blockquote>
<p>참고 사이트</p>
</blockquote>
<p><a href="https://hanamon.kr/javascript-%ed%98%b8%ec%9d%b4%ec%8a%a4%ed%8c%85%ec%9d%b4%eb%9e%80-hoisting/">HANAMON - [JavaScript] 호이스팅(Hoisting)이란?</a>
<a href="https://noogoonaa.tistory.com/78">우주개발자 블로그 - TDZ(Temporal Dead Zone)이란?</a>
<a href="https://tecoble.techcourse.co.kr/post/2021-04-25-hoisting/">호이스팅에 대한 오해와 진실</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] REST? REST API? RESTful?]]></title>
            <link>https://velog.io/@hyungjin_han/REST-API-RESTful</link>
            <guid>https://velog.io/@hyungjin_han/REST-API-RESTful</guid>
            <pubDate>Thu, 09 Feb 2023 09:50:21 GMT</pubDate>
            <description><![CDATA[<h1 id="1-rest란">1. <code>REST</code>란?</h1>
<p><code>REST</code>는 <code>Representational State Transfer</code>의 약자로 자원의 이름으로 구분하여 해당 자원의 상태를 주고 받는 모든 것을 의미한다.</p>
<p><strong>즉 <code>REST</code>란</strong></p>
<ol>
<li><p>HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고,</p>
</li>
<li><p>HTTP Method(POST, GET, PUT, DELETE, PATCH 등)를 통해</p>
</li>
<li><p>해당 자원(URI)에 대한 CRUD Operation을 적용하는 것을 의미한다.</p>
</li>
</ol>
<blockquote>
<p><strong>CRUD Operation이란</strong>
CRUD는 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능인 Create(생성), Read(읽기), Update(갱신), Delete(삭제)를 묶어서 일컫는 말로 REST에서의 CRUD Operation 동작 예시는 다음과 같다.</p>
<ul>
<li><code>Create</code> : 데이터 생성(POST)</li>
</ul>
<ul>
<li><code>Read</code> : 데이터 조회(GET)</li>
</ul>
<ul>
<li><code>Update</code> : 데이터 수정(PUT, PATCH)</li>
</ul>
<ul>
<li><code>Delete</code> : 데이터 삭제(DELETE)</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/3fbced2d-06db-4c88-bbc6-72934b70ffc2/image.png" alt=""></p>
<h2 id="1-1-rest-구성-요소">1-1. <code>REST</code> 구성 요소</h2>
<p><code>REST</code>는 다음과 같은 3가지로 구성이 되어있다. </p>
<ul>
<li><p>자원 (Resource) : HTTP URI</p>
</li>
<li><p>자원에 대한 행위 (Verb) : HTTP Method</p>
</li>
<li><p>자원에 대한 행위의 내용 (Representations) : HTTP Message Pay Load</p>
</li>
</ul>
<h2 id="1-2-rest-특징">1-2. <code>REST</code> 특징</h2>
<ul>
<li><p>Server-Client (서버-클라이언트 구조)</p>
</li>
<li><p>Stateless (무상태)</p>
</li>
<li><p>Cacheable (캐시 처리 가능)</p>
</li>
<li><p>Layered System (계층화)</p>
</li>
<li><p>Uniform Interface (인터페이스 일관성)</p>
</li>
</ul>
<h2 id="1-3-rest의-장단점">1-3. <code>REST</code>의 장단점</h2>
<h3 id="1-3-1-장점">1-3-1. 장점</h3>
<ul>
<li><p>HTTP 프로토콜의 인프라를 그대로 사용하므로 REST API 사용을 위한 별도의 인프라를 구출할 필요가 없다.</p>
</li>
<li><p>HTTP 프로토콜의 표준을 최대한 활용하여 여러 추가적인 장점을 함께 가져갈 수 있게 해 준다.</p>
</li>
<li><p>HTTP 표준 프로토콜에 따르는 모든 플랫폼에서 사용이 가능하다.</p>
</li>
<li><p>Hypermedia API의 기본을 충실히 지키면서 범용성을 보장한다.</p>
</li>
<li><p>REST API 메시지가 의도하는 바를 명확하게 나타내므로 의도하는 바를 쉽게 파악할 수 있다.</p>
</li>
<li><p>여러 가지 서비스 디자인에서 생길 수 있는 문제를 최소화한다.</p>
</li>
<li><p>서버와 클라이언트의 역할을 명확하게 분리한다.</p>
</li>
</ul>
<h3 id="1-3-2-단점">1-3-2. 단점</h3>
<ul>
<li><p>표준이 자체가 존재하지 않아 정의가 필요하다.</p>
</li>
<li><p>HTTP Method 형태가 제한적이다.</p>
</li>
<li><p>브라우저를 통해 테스트할 일이 많은 서비스라면 쉽게 고칠 수 있는 URL보다 Header 정보의 값을 처리해야 하므로 전문성이 요구된다.</p>
</li>
<li><p>구형 브라우저에서 호환이 되지 않아 지원해주지 못하는 동작이 많다.(ex : 익스플로어)</p>
</li>
</ul>
<hr>
<h1 id="2-rest-api란">2. <code>REST API</code>란?</h1>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/46e57325-9ba1-4b22-8cb4-9fe9eb4c14f3/image.png" alt=""></p>
<p><code>RESPT API</code>란 <code>REST</code>의 원리를 따르는 <code>API</code>를 의미한다.</p>
<p>하지만 <code>REST API</code>를 올바르게 설계하기 위해서는 지켜야 하는 몇가지 규칙이 있으며</p>
<ul>
<li><p><code>URI</code>는 동사보다는 명사를, 대문자보다는 소문자를 사용하여야 한다.</p>
<blockquote>
<p>⭕ <a href="http://localhost:3000/test">http://localhost:3000/test</a>
❌ <a href="http://localhost:3000/testing">http://localhost:3000/testing</a>
❌ <a href="http://localhost:3000/Test">http://localhost:3000/Test</a></p>
</blockquote>
</li>
<li><p>마지막에 슬래시(<code>/</code>)를 포함하지 않는다.</p>
<blockquote>
<p>⭕ <a href="http://localhost:3000/test">http://localhost:3000/test</a>
❌ <a href="http://localhost:3000/test/">http://localhost:3000/test/</a></p>
</blockquote>
</li>
<li><p>언더바(<code>_</code>) 대신 하이폰(<code>-</code>)을 사용한다.</p>
<blockquote>
<p>⭕ <a href="http://localhost:3000/test-write">http://localhost:3000/test-write</a>
❌ <a href="http://localhost:3000/test_write">http://localhost:3000/test_write</a></p>
</blockquote>
</li>
<li><p>파일 확장자는 <code>URI</code>에 포함하지 않는다.</p>
<blockquote>
<p>⭕ <a href="http://localhost:3000/picture">http://localhost:3000/picture</a>
❌ <a href="http://localhost:3000/picture.jpg">http://localhost:3000/picture.jpg</a></p>
</blockquote>
</li>
<li><p>행위를 포함하지 않는다.</p>
<blockquote>
<p>⭕ <a href="http://localhost:3000/article/1">http://localhost:3000/article/1</a>
❌ <a href="http://localhost:3000/update-article/1">http://localhost:3000/update-article/1</a></p>
</blockquote>
</li>
</ul>
<p>등의 규칙이 있다.</p>
<hr>
<h1 id="3-restful이란">3. <code>RESTful</code>이란?</h1>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/05d9bfed-e4f3-4653-9df0-80dff55022b4/image.png" alt=""></p>
<p><code>RESTful</code>이란 <code>REST</code>의 원리를 따르는 시스템을 의미한다.</p>
<p>하지만 REST를 사용했다 하여 모두가 RESTful 한 것은 아니며, REST API의 설계 규칙을 올바르게 지킨 시스템을 RESTful하다 말할 수 있으며 모든 CRUD 기능을 POST로 처리 하는 API 혹은 URI 규칙을 올바르게 지키지 않은 API는 REST API의 설계 규칙을 올바르게 지키지 못한 시스템은 REST API를 사용하였지만 RESTful 하지 못한 시스템이라고 할 수 있다.</p>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://khj93.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-REST-API%EB%9E%80-REST-RESTful%EC%9D%B4%EB%9E%80">히진쓰의 서버사이드 기술 블로그 - REST API란? REST, RESTful이란?</a>
<a href="https://velog.io/@yhko1992/REST-API%EC%97%90-%EB%8C%80%ED%95%B4-%EC%84%A4%EB%AA%85%ED%95%B4%EB%B3%B4%EC%9E%90">컴퓨터는 나의 친구 - REST API에 대해 설명해보자</a>
<a href="https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html">Heee&#39;s Development Blog - REST란? REST API란? RESTful이란?</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] MVC 패턴]]></title>
            <link>https://velog.io/@hyungjin_han/MVC-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@hyungjin_han/MVC-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 08 Feb 2023 06:31:16 GMT</pubDate>
            <description><![CDATA[<h1 id="1-mvc-패턴이란">1. MVC 패턴이란?</h1>
<p><code>MVC(모델-뷰-컨트롤러)</code>는 사용자 인터페이스, 데이터 및 논리 제어를 구현하는데 널리 사용되는 소프트웨어 디자인 패턴이다.
소프트웨어의 비즈니스 로직과 화면을 구분하는데 중점을 두고 있으며, 이러한 &quot;관심사 분리&quot; 는 더나은 업무의 분리와 향상된 관리를 제공한다.
<code>MVC</code> 에 기반을 둔 몇 가지 다른 디자인 패턴으로 <code>MVVM(모델-뷰-뷰모델)</code>, <code>MVP(모델-뷰-프리젠터)</code>, <code>MVW(모델-뷰-왓에버)</code> 가 있습니다.</p>
<p><code>MVC</code> 소프트웨어 디자인 패턴의 세 가지 부분은 다음과 같이 설명할 수 있다.</p>
<blockquote>
<ul>
<li><code>Model</code> : 데이터와 비즈니스 로직을 관리</li>
<li><code>View</code> : 레이아웃과 화면을 처리</li>
<li><code>Controller</code> : 명령을 모델과 뷰 부분으로 라우팅</li>
</ul>
</blockquote>
<hr>
<h1 id="2-모델-뷰-컨트롤러-예시">2. 모델-뷰-컨트롤러 예시</h1>
<p>간단한 쇼핑몰을 예시로 하는 자료
<img src="https://velog.velcdn.com/images/hyungjin_han/post/bd023f76-2c1e-4a7a-866d-1ca25ab45aa4/image.PNG" alt=""></p>
<h2 id="2-1-모델-model">2-1. 모델 (<code>Model</code>)</h2>
<p>모델은 앱이 포함해야할 데이터가 무엇인지를 정희하며, 데이터의 상태가 변경되면 모델을 일반적으로 뷰에게 알리며(필요에 따라 화면을 변경할 수도 있음) 가끔 컨트롤러에게 알리기도 한다. (업데이트 된 뷰를 제거하기 위해 다른 로직이 필요한 경우)</p>
<h2 id="2-2-뷰-view">2-2. 뷰 (<code>View</code>)</h2>
<p>뷰는 앱의 데이터를 보여주는 방식을 정의한다.</p>
<p>쇼핑 리스트 앱에서, 뷰는 항목이 사용자에게 보여지는 방식을 정의하며, 표시할 데이터를 모델로부터 받는다.</p>
<h2 id="2-3-컨트롤러-controller">2-3. 컨트롤러 (<code>Controller</code>)</h2>
<p>컨트롤러는 앱의 사용자로부터의 입력에 대한 응답으로 모델 및 뷰를 업데이트하는 로직을 포함한다.</p>
<p>예를 들어, 쇼핑 리스트는 항목을 추가하거나 제거할 수 있게 해주는 입력 폼과 버튼을 갖으며, 이러한 액션들은 모델이 업데이트 되는 것이므로, 입력이 컨트롤러에게 전송되고, 모델을 적당하게 처리한 다음, 업데이트 된 데이터를 뷰로 전송한다.</p>
<p>단순히 데이터를 다른 형태로 나타내기 위해 뷰를 업데이트를 해야 하는 경우(예를 들면, 항목을 알파벳순서로 정렬한다거나, 가격이 낮은 순서 또는 높은 순서로 정렬), 컨트롤러는 모델을 업데이트 할 필요 없이 바로 처리가 가능하다.</p>
<hr>
<h1 id="3-web에서의-mvc">3. Web에서의 MVC</h1>
<p>웹의 초창기에, <code>MVC</code> 구조는 클라이언트가 폼이나 링크를 통해 업데이트를 요청하거나 업데이트된 뷰를 받아 다시 브라우저에 표시하기 위해 대부분 서버 사이드에서 구현되었다.</p>
<p>반면, 요즘에는 클라이언트 사이드 데이터 저장소의 출현과 필요에 따라 페이지의 일부만 업데이트를 허용하는 <code>XMLHttpRequest</code> 를 포함해 더 많은 로직이 클라이언트 사이드에 추가되었다.</p>
<p><code>AngularJS</code> 및 <code>Ember.js</code> 와 같은 웹 프레임워크들은 약간씩은 방식이 다르지만, 모두 <code>MVC</code> 구조를 구현한다.</p>
<h2 id="3-1-대표적인-mvc-프레임워크">3-1. 대표적인 <code>MVC</code> 프레임워크</h2>
<table>
<thead>
<tr>
<th>프레임워크</th>
<th>언어</th>
</tr>
</thead>
<tbody><tr>
<td><code>Spring</code></td>
<td><code>Java</code></td>
</tr>
<tr>
<td><code>django</code></td>
<td><code>Python</code></td>
</tr>
<tr>
<td><code>ASP.NET</code></td>
<td><code>C#</code></td>
</tr>
<tr>
<td><code>Express</code></td>
<td><code>JavaScript</code></td>
</tr>
<tr>
<td><code>Ruby on Rails</code></td>
<td><code>Ruby</code></td>
</tr>
<tr>
<td><code>Laravel</code></td>
<td><code>PHP</code></td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>참고 사이트</p>
<p><a href="https://developer.mozilla.org/ko/docs/Glossary/MVC">MDN Web Docs - MVC</a>
<a href="https://www.yalco.kr/12_mvc_framework/">얄코 - MVC 프레임워크가 뭔가요?</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Computer Science] Stack VS Queue]]></title>
            <link>https://velog.io/@hyungjin_han/Stack-VS-Queue</link>
            <guid>https://velog.io/@hyungjin_han/Stack-VS-Queue</guid>
            <pubDate>Tue, 07 Feb 2023 05:27:49 GMT</pubDate>
            <description><![CDATA[<h1 id="1-stack-lifo">1. Stack (LIFO)</h1>
<h2 id="1-1-stack의-개념">1-1. Stack의 개념</h2>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/b9ad8049-018a-4e63-b574-34b73a5d3fa5/image.png" alt=""></p>
<h3 id="1-1-1-스택stack이란">1-1-1. 스택(Stack)이란?</h3>
<p>쌓아 올린다는 것을 의미하며, 스택 자료구조라는 것은 책을 쌓는 것처럼 <strong>차곡차곡 쌓아 올린 형태의 자료구조</strong>를 말한다.</p>
<h2 id="1-2-stack의-특징">1-2. Stack의 특징</h2>
<p>스택은 위의 사진과 같이 <strong>구조와 크기의 자료를 정해진 방향으로만 쌓을 수 있고</strong>, <strong>Top으로 정한 곳을 통해서만 접근</strong>할 수 있다.
Top에는 가장 위에 있는 자료는 가장 최근에 들어온 자료를 가리키고 있으며, 삽입되는 새 자료는 top이 가리키는 자료의 위에 쌓인다.
스택에서 자료를 삭제할 때도 Top을 통해서만 가능하다.
스택에서 Top을 통해 삽입하는 연산을 <code>push</code>, Top을 통한 삭제하는 연산을 <code>pop</code>이라고 한다.</p>
<p>따라서 스택은 시간 순서에 따라 자료가 쌓여서 <strong>가장 마지막에 삽입된 자료가 가장 먼저 삭제</strong>되는 <strong>후입선출(<code>LIFO, Last-In-First-Out</code>)의 구조</strong>를 갖고 있다.</p>
<p>비어있는 스택에서 원소를 추출하려고 할 때, <code>stack underflow</code>라고 하며, 스택이 넘치는 경우, <code>stack overflow</code>라고 한다.</p>
<blockquote>
<p>여기서 유래된 사이트가 바로 <a href="https://stackoverflow.com/"><code>Stack Overflow</code></a> 사이트이다.
프로그래밍을 하며 궁금한 것, 막히는 것은 거의 모두 들어있다고 생각해도 과장이 아닌
<strong>코딩계의 지식인 느낌.</strong></p>
</blockquote>
<h2 id="1-3-stack의-활용">1-3. Stack의 활용</h2>
<p>스택의 특징인 후입선출을 활용하여 여러 분야에서 활용이 가능한데,</p>
<ul>
<li>웹 스라우저 방문기록 (뒤로가기) : 가장 나중에 열린 페이지부터 다시 보여줌</li>
<li>역순 문자열 만들기 : 가장 나중에 입력된 문자부터 출력</li>
<li>실행 취소 (undo) : 가장 나중에 실행된 것부터 실행을 취소</li>
<li>후위 표기법 계산</li>
<li>수식의 괄호 검사 : 연산자 우선순위 표현을 위한 괄호 검사</li>
</ul>
<p>등의 활용이 있다.</p>
<h2 id="1-4-stack의-장단점">1-4. Stack의 장단점</h2>
<ul>
<li><code>Top</code> 을 통해 접근하기 때문에 데이터 접근, 삽입, 삭제가 빠르다</li>
<li><code>Top</code> 위치 이외의 데이터에 접근할 수 없기 때문에 탐색이 불가능하다. 탐색하려면 모든 데이터를 꺼내면서 진행해야 한다.</li>
</ul>
<h1 id="2-queue-fifo">2. Queue (FIFO)</h1>
<h2 id="2-1-queue의-개념">2-1. Queue의 개념</h2>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/cbb72de7-2d83-4bc5-98d7-eead7cdd924b/image.png" alt=""></p>
<h3 id="큐queue란">큐(Queue)란?</h3>
<p>사전적인 의미로는 <strong>(무엇을 기다리는 사람, 자동차 등의) 줄, 혹은 줄을 서서 기다리는 것</strong>을 의미하며, 일상 생활에서 줄을 서서 기다리거나, 먼저 온 사람의 업무를 처리해주는 것과 같이 <strong>선입선출(FIFO, First-In-First-Out) 방식의 자료구조</strong>를 말한다.</p>
<h2 id="2-2-queue의-특징">2-2. Queue의 특징</h2>
<p>정해진 한 곳(Top)을 통해서 삽입, 삭제가 이루어지는 스택과는 달리, 큐는 한쪽 끝에서 삽입 작업이, 다른 쪽 끝에서는 살제 작업이 양쪽으로 이루어진다.
이때 삭제 연산만 수행되는 곳을 프론트(<code>front</code>), 삽입 연산만 이루어지는 곳을 리어(<code>rear</code>)로 정하여 각각의 연산 작업만 수행된다.
이때, 큐의 리어에서 이루어지는 삽입 연산을 인큐(<code>enQueue</code>), 프론트에서 이루어지는 삭제 연산을 디큐(<code>dnQueue</code>)라고 한다.</p>
<ul>
<li>큐의 가장 첫 원소를 <code>front</code> / 가장 끝 원소를 <code>rear</code></li>
<li>큐는 들어올 때 <code>rear</code>로 들어오지만 나올때는 <code>front</code>부터 빠지는 특성</li>
<li>접근방법은 가장 첫 원소와 끝 원소로만 가능</li>
<li>가장 먼저 들어온 프론트 원소가 가장 먼저 삭제</li>
</ul>
<p>즉, 큐에서 프론트 원소는 가장 먼저 큐에 들어왔던 첫 번째 원소가 되는 것이며, 리어 원소는 가장 늦게 큐에 들어온 마지막 원소가 된다.</p>
<h2 id="2-3-queue의-활용">2-3. Queue의 활용</h2>
<p>큐는 주로 데이터가 입력된 시간 순서대로 처리해야 할 필요가 있는 상황에 이용한다.</p>
<ul>
<li>우선순위가 같은 작업 예약 (프린터의 인쇄 대기열)</li>
<li>은행 업무</li>
<li>콜센터 고객 대기시간</li>
<li>프로세스 관리</li>
<li>너비 우선 탐색(BFS, Breadth-First Search) 구현</li>
<li>캐시(Cache) 구현</li>
</ul>
<h2 id="2-4-queue의-장단점">2-4. Queue의 장단점</h2>
<ul>
<li>데이터 접근, 삽입, 삭제가 빠르다.</li>
<li>큐 역시 스택과 마찬가지로 중간에 위치한 데이터에 대한 접근이 불가능하다.</li>
</ul>
<blockquote>
<p>두 자료구조를 비교하여 하나만 사용하기보다는 활용 방안에 따라서 적절한 자료구조를 선택하여 사용하는 것이 최고로 좋은 프로그래밍인 것 같다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[동물상 테스트 웹, 앱 만들기! (4편)]]></title>
            <link>https://velog.io/@hyungjin_han/animalTest4</link>
            <guid>https://velog.io/@hyungjin_han/animalTest4</guid>
            <pubDate>Mon, 20 Jun 2022 14:24:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><em><strong><a href="https://www.youtube.com/playlist?list=PLU9-uwewPMe2-vtJAgWB6SNhHcTjJDgEO">실전 수익형 웹, 앱 서비스 동물상 테스트 만들기</a>의
3번쨰 영상을 통해 제작된 코드입니다.</strong>
해당 내용에 도움이 되는 부분은 링크를 걸어두었습니다!</em></p>
</blockquote>
<p><strong>그럼 시작하도록 하겠습니다!</strong></p>
<hr>
<p><br>저번 시간의 경우, <code>Crawling</code>에 대한 이해와 원하는 키워드에 맞춰
<br>이미지 다운로드 자동화 등을 제작해보고 이해하는 포스팅을 했다.
<br>이제 본격적으로 동물상 테스트를 위한 머신러닝을 시도해 볼 차례다.</p>
<blockquote>
<p><em>결국에는 정말 훌륭하게 만들어진 머신러닝 사이트를 사용하여 큰 틀을 짜고
작은 부분들을 내 입맛에 맞게 고치는 작업이다...
머신러닝을 처음부터 끝까지 필자가 만든다?? 1년 밤새도 할 수 있을까 싶다...</em></p>
</blockquote>
<hr>
<h1 id="1-teachable-machine을-이용한-머신러닝">1. Teachable Machine을 이용한 머신러닝</h1>
<p>우선 머신러닝을 위한 사이트를 이용해야 한다.
<br>위에서도 언급했듯이, 훌륭하게 만들어진 코드를 가져와
<br>수정하는 작업을 거칠 것이기 때문이다.
<br>구글에서 지원받아 운영하고 있는 <a href="https://teachablemachine.withgoogle.com/">Teachable Machine</a>이라는 사이트가 있다.
<br>이곳이 필자가 머신러닝을 위해 사용할 사이트이다.
<br>사이트에 들어가보자.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/d52b7f00-bb68-4e7a-be68-2724f723b1ae/image.PNG" alt="">
사이트의 메인 화면에 보이는 <code>시작하기</code>를 클릭하면,
<img src="https://velog.velcdn.com/images/hyungjin_han/post/87962f8b-e36a-4714-b1f0-ad9f8f1ccf9c/image.PNG" alt="">
프로젝트를 생성할 수 있다.
<br>필자의 작업은 저번 1편에서 다운받았던 동물상 별 연예인의
<br>사진을 데이터로 사용해서 자신의 얼굴을 테스트하는 프로젝트이기 때문에
<br><code>이미지 프로젝트</code>로 생성했다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/49c39ed5-27b8-47ba-b082-a1930eb59f28/image.PNG" alt="">
프로젝트 생성 후의 모습이다.
<br>우선 클래스의 이름을 정해야 한다.
<br>클래스의 이름은 쉽게 말하자면 컴퓨터로 따지면 폴더이다.
<br>필자는 클래스 추가를 통해 5개의 클래스를 만들고,
<br>각 클래스에 <code>강아지 상</code>, <code>고양이 상</code>, <code>곰 상</code>, <code>공룡 상</code>, <code>토끼 상</code>
<br>이렇게 지정을 했다.
<br>그리고 조코딩님이 미리 정리해놓은 정보를 토대로
<br><code>강아지 상 : 워너원 강다니엘, 엑소 백현, 박보검, 송중기</code>
<br><code>고양이 : 워너원 황민현, 엑소 시우민, 강동원, 이종석, 이준기</code>
<br><code>곰 : 마동석, 조진웅, 조세호, 안재홍</code>
<br><code>공룡 : 김우빈, 윤두준, 이민기, 육성재, 공유</code>
<br><code>토끼 : 방탄소년단 정국, 아이콘 바비, 워너원 박지훈, 엑소 수호</code>
<br>이렇게 정해주고 각 클래스에 사진을 넣어주었다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/1df8b143-5f61-45e4-8f64-c88e6117f083/image.PNG" alt="">
이렇게 정리된 폴더를 통째로 넣으면 끝난다.
<br>굉장히 편리한 사이트였다.
<br>이렇게 각 클래스에 사진을 업로드를 했다면 자료를 다듬어야 한다.
<br>즉, <code>데이터 클렌징</code>이라는 작업을 시작할 것이다.
<br><code>데이터 클렌징</code>이란, 사진이나 기타 데이터가 될 자료들 중에
<br>필요없거나, 있으면 오히려 정확도가 저하될만한 자료들을
<br>삭제해 줌으로써 정확도의 향상을 위해 일종의 자료 필터링을 하는 것이다.
<br>특히, 필자의 경우에는 <code>BeautifulSoup</code>를 통해 키워드에 맞춰 일괄적으로
<br>이미지를 다운받았기 때문에 더더욱 필요한 작업이다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/88ab0114-0e0d-4b42-807c-8551896b80d0/image.PNG" alt="">
위의 이미지에서 빨간 네모 부분에 있는 <code>🗑️</code> 이런 모양의 휴지통을 클릭하고
<br>이미지 확인 후, 삭제를 시작하면 된다.
<br>필자는 삭제할 이미지의 기준을 잡을 때,
<br><code>물건에 얼굴이 가려진 사진</code>, <code>키워드와 맞지 않은 사진</code>, <code>얼굴이 한 개 이상인 사진</code>, <code>얼굴이 나오지 않은 사진</code>
<br>이렇게만 걸러도 나쁘지 않은 결과를 얻을 수 있을 것이다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/e64d6563-5eeb-41fb-b4ac-eb62e015768d/image.PNG" alt="">
이렇게 <code>데이터 클렌징</code> 작업을 마치고 각 클래스에 담겨있는 사진들을
<br>참고할 모델로써 학습을 시키도록 해보자.
<br><code>모델 학습시키기</code>를 클릭하면,
<img src="https://velog.velcdn.com/images/hyungjin_han/post/4ab97f53-cb21-4bc6-83db-1199098f641c/image.PNG" alt="">
이렇게 <code>학습 중...</code>이라는 문구와 함께 열심히 학습을 한다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/3d638aee-368a-4598-af9d-e111487f65fc/image.PNG" alt="">
학습을 끝낸 후의 모습이다.
<br>우측을 qhaus <code>Webcam</code> 부분을 <code>파일</code>로 바꿔주어야 테스트를 진행할 때
<br>이미지 업로드를 통해 테스트를 할 수 있다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/c31709fa-500b-4374-a0e1-25dce97d7a89/image.PNG" alt="">
대표적인 고양이 상인 가수 GD의 테스트 결과이다.
<br>비교적 사진이 잘 나와서 그런지 고양이 상이 83%로 높게 나왔다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/2cf202b8-84c2-4285-a0ea-e32c5f901325/image.PNG" alt="">
다음으로는 곰 상으로 알려진 배우 곽도원의 테스트 결과이다.
<br>그냥 곰 상으로 나와버렸다.
<br><em>어? 그럼 무난하게 성공한거네?</em> 라고 생각하고 정말 대표적인 공룡 상,
<br>가수 TOP를 넣어봤다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/d4d04611-caad-4ebc-80ba-d0215115dd58/image.PNG" alt="">
??????
<br>아...아닌가?
<br>그럼 더 공룡 상으로 알려진 배우 류준열로 해보았다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/d0a326f6-d65d-4935-b8e9-e3f60144bb8f/image.PNG" alt="">
<img src="https://velog.velcdn.com/images/hyungjin_han/post/807c6b9a-8208-4d4f-8655-c6bbe278ffc3/image.gif" alt="">
이게 무슨 일이지....
<br>사실 오류가 아니고 동물 상이라는 것은 지극히 주관적이기도 하고,
<br>헤어스타일, 옷차림, 조명, 표정 등을 학습하게 되면서
<br>수많은 변수에 따라 결과가 정확하지 않을 수 밖에 없다.
<br>어찌보면 당연하다.
<br>해당 편의 영상에서 조코딩님의 설명을 덧붙이자면,
<br>사진의 색을 전부 흑백으로 처리하고, 얼굴 부분만을 학습시킨다면
<br>보다 정확한 결과가 나올 것이라고 한다.
<br>하지만 그렇게까지는 하지 않을 예정이다.
<br>추후에 다른 주제로 해볼법 한 작업임은 틀림없다.
<br>이제 이렇게 머신러닝은 끝났고, 이제 해당 링크와 코드를 불러와야 한다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/e2294d8a-b95a-4e2f-b9c4-d178ca849fde/image.PNG" alt="">
위의 이미지처럼 모델 업로드를 클릭하고,
<img src="https://velog.velcdn.com/images/hyungjin_han/post/eaed18b7-e096-480d-bffb-1543b15bf145/image.PNG" alt="">
모델 업로드가 끝나면 링크와 함께 <code>JavaScript</code> 코드가 나온다.
<br>위의 링크의 경우 타인이 언제든지 이 링크를 들어와서
<br>필자가 만든 동물상 테스트를 할 수 있는 링크이다.
<br><a href="https://teachablemachine.withgoogle.com/models/WXmTZBNlH/">동물상 테스트 사이트</a> 👈 여기로 들어가면 된다.
<br>하지만 필자는 그 밑의 <code>JavaScript</code> 코드를 수정해서 웹을 만들 예정이다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/442e778b-3dc8-4033-8844-8490e6ed39c4/image.PNG" alt="">
위의 이미지에서 빨간 네모 부분의 <code>복사📃</code>를 클릭해 코드를 복사하고,
<br>미리 만들어둔 <code>HTML</code> 파일에 에디터를 통해 <code>&lt;body&gt;</code> 태그 안에 붙여넣어 준다.
<br>필자의 경우, <code>HTML</code>이 너무 복잡해질 것 같아서 <code>js</code> 파일을 따로 만들고
<br><code>&lt;script&gt;</code> 부분을 <code>js</code> 파일에 따로 넣어주었다.
<br>그 후에 저장을 하고 실행을 시키면?
<img src="https://velog.velcdn.com/images/hyungjin_han/post/615be1eb-4d11-4408-8a94-b24c4ac42f0e/image.PNG" alt="">
초라하지만 일단 성공은 한 셈이다.
<br><code>Start</code>를 클릭하면 학습한 모델을 불러오면서 웹캠이 켜지고,
<br>웹캠에 비춰지는 얼굴에 따라 동물상을 수치로 나타내는 웹이다.
<br>하지만 필자는 웹캠이 없어서 그런지 반응을 하지 않았다.
<br>뭐 문제될 것은 없는 것이 웹캠은 쓰지 않을 예정이고,
<br>이미지 업로드를 하고 그에 맞춰서 테스트를 하는 것에만 신경쓰자!</p>
<hr>
<h1 id="2-웹캠에서-이미지-업로드-형식으로">2. 웹캠에서 이미지 업로드 형식으로</h1>
<p>앞서 설명했듯이 웹캠을 사용하지 않고 이미지 업로드를 통해
<br>동물상 테스트를 할 예정이다.
<br>이미지 업로드를 위한 코드를 작성해야 하지만...
<br>구글링을 통해 템플릿을 찾아보도록 했다.</p>
<h2 id="2-1-이미지-업로드-템플릿-사용">2-1. 이미지 업로드 템플릿 사용</h2>
<p>우선 키워드는 <code>image upload template</code>로 검색했다.
<br>그렇게 뜨는 사이트인 <a href="https://colorlib.com/wp/bootstrap-file-uploads/">colorlib</a>의 <a href="https://codepen.io/aaronvanston/details/yNYOXR">File Upload Input</a>를 들어가봤다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/cbe42ea3-707d-4642-9ddd-79a94e06cfad/image.png" alt="">
이런 식으로 간단한 프리뷰가 가능한 사이트가 나왔으며,
<br>이미지의 빨간 네모로 체크된 곳을 클릭해서 각 <code>HTML</code> 코드와
<br><code>CSS</code> 코드, <code>JS</code> 코드 등을 복사해서 사용하면 된다.
<br>만약에 이 코드를 사용하여 수익을 창출한다고 하면,
<br>쭉 스크롤을 내려서 <code>License</code>를 유심히 주의 깊게 봐야 한다.
<br>해당 코드의 <code>License</code>를 보자면,</p>
<pre><code>Copyright (c) 2022 by Aaron Vanston (https://codepen.io/aaronvanston/pen/yNYOXR)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</code></pre><p>영어라 보기 힘들다면 번역기를 통해 좀 더 쉽게 알아보자!</p>
<pre><code>Copyright (c) 2022 by Aaron Vanston (https://codepen.io/aaronvanston/pen/yNYOXR)

이에 따라 이 소프트웨어 및 관련 문서 파일(&quot;소프트웨어&quot;)의 사본을 입수한 사람에게 사용, 복사, 수정, 병합 권한을 포함하되 이에 국한되지 않는 제한 없이 소프트웨어를 취급할 수 있는 권한이 무료로 부여됩니다. 다음 조건에 따라 소프트웨어 사본을 게시, 배포, 재라이센스 부여 및/또는 판매하고 소프트웨어가 제공된 사람에게 그렇게 하도록 허용합니다.

위의 저작권 표시 및 이 허가 표시는 소프트웨어의 모든 사본 또는 상당 부분에 포함되어야 합니다.

소프트웨어는 상품성, 특정 목적에의 적합성 및 비침해에 대한 보증을 포함하되 이에 국한되지 않는 어떠한 종류의 명시적 또는 묵시적 보증 없이 &quot;있는 그대로&quot; 제공됩니다. 어떤 경우에도 저자 또는 저작권자는 계약, 불법 행위 또는 기타의 행위로 인해 소프트웨어 또는 다른 거래와 관련하여 발생하는 청구, 손해 또는 기타 책임에 대해 책임을 지지 않습니다. 소프트웨어.
</code></pre><p><code>제한 없이 소프트웨어를 취급할 수 있는 권한이 무료로 부여됩니다.</code>
<br>제한없이 사용은 가능하다는 뜻인데,</p>
<pre><code>소프트웨어 사본을 게시, 배포, 재라이센스 부여 및/또는 판매하고 소프트웨어가 제공된 사람에게 그렇게 하도록 허용합니다.

위의 저작권 표시 및 이 허가 표시는 소프트웨어의 모든 사본 또는 상당 부분에 포함되어야 합니다.</code></pre><p>위의 문구를 보면 <code>위의 저작권 표시 및 이 허가 표시는 소프트웨어의 모든 사본 또는 상당 부분에 포함</code>
<br>이 부분이 눈에 띈다.
<br>결국 이 코드를 사용하기 위해서는 저 <code>License</code> 전체를
<br>코드에 삽입해야 한다는 의미이다.
<br>그렇다면
<img src="https://velog.velcdn.com/images/hyungjin_han/post/ae49a15e-8a05-4508-9627-f889426a21be/image.PNG" alt="">
위의 이미지에 있는 빨간 네모 부분의 <code>Copy</code>를 눌러 복사 후,
<br>사용할 코드의 <code>HTML</code> 부분에 <code>&lt;!--  --&gt;</code> 이렇게 주석처리를 통해
<br>어딘가에 붙여넣어주면 된다.
<br>꼭 보이는 화면에 출력될 필요는 없기에 주석을 사용한 것이다.
<br>이제 웹을 열어보면?
<img src="https://velog.velcdn.com/images/hyungjin_han/post/03f46883-8305-4b0b-a5f4-eb8fec1aae52/image.PNG" alt="">
아주 수월하게 진행되고 있는 느낌이 든다.</p>
<blockquote>
<p><em>당연하게 수월한 것이, 다른 사람들이 만들어 놓은 코드를 어떻게 보면
짜집기를 통해서 만들고 있기 때문에 수월할 수 밖에 없다는 걸
지금 블로그에 포스팅을 하면서 뼈저리게 깨닫게 된다.
하지만 이러한 과정도 성장의 일부라고 생각하고 열심히 해보자!</em></p>
</blockquote>
<p>자! 그럼 여기서 코드의 중간점검을 할 시간이다.</p>
<pre><code class="language-HTML">&lt;!-- HTML 코드 --&gt;

&lt;html lang=&quot;kor&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot;&gt;
    &lt;title&gt;Animal Test&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
      &lt;!-- Teachable Machine Start 버튼 --&gt;
    &lt;div&gt;Teachable Machine Image Model&lt;/div&gt;
    &lt;button type=&quot;button&quot; onclick=&quot;init()&quot;&gt;Start&lt;/button&gt;

      &lt;!-- 이미지 업로드 코드 --&gt;
    &lt;script class=&quot;jsbin&quot; src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js&quot;&gt;&lt;/script&gt;
    &lt;div class=&quot;file-upload&quot;&gt;
        &lt;button class=&quot;file-upload-btn&quot; type=&quot;button&quot; onclick=&quot;$(&#39;.file-upload-input&#39;).trigger( &#39;click&#39; )&quot;&gt;AddImage&lt;/button&gt;
        &lt;div class=&quot;image-upload-wrap&quot;&gt;
            &lt;input class=&quot;file-upload-input&quot; type=&#39;file&#39; onchange=&quot;readURL(this);&quot; accept=&quot;image/*&quot; /&gt;
            &lt;div class=&quot;drag-text&quot;&gt;
                &lt;h3&gt;Drag and drop a file or select add Image&lt;/h3&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class=&quot;file-upload-content&quot;&gt;
            &lt;!-- &lt;img class=&quot;file-upload-image&quot; src=&quot;#&quot; alt=&quot;your image&quot; /&gt; --&gt;
            &lt;img class=&quot;file-upload-image&quot; id=&quot;upload-image&quot; src=&quot;#&quot; alt=&quot;your image&quot; /&gt;
            &lt;div class=&quot;image-title-wrap&quot;&gt;
                &lt;button type=&quot;button&quot; onclick=&quot;removeUpload()&quot; class=&quot;remove-image&quot;&gt;Remove &lt;span class=&quot;image-title&quot;&gt;Uploaded Image&lt;/span&gt;&lt;/button&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- 웹캠, 테스트 결과 창 --&gt;
    &lt;div id=&quot;webcam-container&quot;&gt;&lt;/div&gt;
    &lt;div id=&quot;label-container&quot;&gt;&lt;/div&gt;

      &lt;!-- jsdelivr의 src --&gt;
    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.3.1/dist/tf.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://cdn.jsdelivr.net/npm/@teachablemachine/image@0.8/dist/teachablemachine-image.min.js&quot;&gt;&lt;/script&gt;

      &lt;!-- 따로 생성한 js 파일의 src --&gt;
    &lt;script src=&quot;scripts.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;

&lt;!-- Copyright (c) 2022 by Aaron Vanston (https://codepen.io/aaronvanston/pen/yNYOXR)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the &quot;Software&quot;), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
Software.

THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --&gt;

&lt;/html&gt;</code></pre>
<br>

<pre><code class="language-css">/* CSS 파일 */

body {
    font-family: sans-serif;
    background-color: #eeeeee;
}

.file-upload {
    background-color: #ffffff;
    width: 600px;
    margin: 0 auto;
    padding: 20px;
}

.file-upload-btn {
    width: 100%;
    margin: 0;
    color: #fff;
    background: #1FB264;
    border: none;
    padding: 10px;
    border-radius: 4px;
    border-bottom: 4px solid #15824B;
    transition: all .2s ease;
    outline: none;
    text-transform: uppercase;
    font-weight: 700;
}

.file-upload-btn:hover {
    background: #1AA059;
    color: #ffffff;
    transition: all .2s ease;
    cursor: pointer;
}

.file-upload-btn:active {
    border: 0;
    transition: all .2s ease;
}

.file-upload-content {
    display: none;
    text-align: center;
}

.file-upload-input {
    position: absolute;
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    outline: none;
    opacity: 0;
    cursor: pointer;
}

.image-upload-wrap {
    margin-top: 20px;
    border: 4px dashed #1FB264;
    position: relative;
}

.image-dropping,
.image-upload-wrap:hover {
    background-color: #1FB264;
    border: 4px dashed #ffffff;
}

.image-title-wrap {
    padding: 0 15px 15px 15px;
    color: #222;
}

.drag-text {
    text-align: center;
}

.drag-text h3 {
    font-weight: 100;
    text-transform: uppercase;
    color: #15824B;
    padding: 60px 0;
}

.file-upload-image {
    max-height: 200px;
    max-width: 200px;
    margin: auto;
    padding: 20px;
}

.remove-image {
    width: 200px;
    margin: 0;
    color: #fff;
    background: #cd4535;
    border: none;
    padding: 10px;
    border-radius: 4px;
    border-bottom: 4px solid #b02818;
    transition: all .2s ease;
    outline: none;
    text-transform: uppercase;
    font-weight: 700;
}

.remove-image:hover {
    background: #c13b2a;
    color: #ffffff;
    transition: all .2s ease;
    cursor: pointer;
}

.remove-image:active {
    border: 0;
    transition: all .2s ease;
}</code></pre>
<br>

<pre><code class="language-js">// JavaScript 파일

// Teachable Machine 코드
// More API functions here:
// https://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/image
// the link to your model provided by Teachable Machine export panel
const URL = &quot;https://teachablemachine.withgoogle.com/models/WXmTZBNlH/&quot;;

let model, webcam, labelContainer, maxPredictions;

// Load the image model and setup the webcam
async function init() {
        const modelURL = URL + &quot;model.json&quot;;
const metadataURL = URL + &quot;metadata.json&quot;;

// load the model and metadata
// Refer to tmImage.loadFromFiles() in the API to support files from a file picker
// or files from your local hard drive
// Note: the pose library adds &quot;tmImage&quot; object to your window (window.tmImage)
model = await tmImage.load(modelURL, metadataURL);
maxPredictions = model.getTotalClasses();

// Convenience function to setup a webcam
const flip = true; // whether to flip the webcam
webcam = new tmImage.Webcam(200, 200, flip); // width, height, flip
await webcam.setup(); // request access to the webcam
await webcam.play();
window.requestAnimationFrame(loop);

// append elements to the DOM
document.getElementById(&quot;webcam-container&quot;).appendChild(webcam.canvas);
labelContainer = document.getElementById(&quot;label-container&quot;);
for (let i = 0; i &lt; maxPredictions; i++) { // and class labels
    labelContainer.appendChild(document.createElement(&quot;div&quot;));
        }
    }

async function loop() {
    webcam.update(); // update the webcam frame
await predict();
window.requestAnimationFrame(loop);
    }

// run the webcam image through the image model
async function predict() {
        // predict can take in an image, video or canvas html element
        const prediction = await model.predict(webcam.canvas);
for (let i = 0; i &lt; maxPredictions; i++) {
            const classPrediction =
prediction[i].className + &quot;: &quot; + prediction[i].probability.toFixed(2);
labelContainer.childNodes[i].innerHTML = classPrediction;
        }
    }

// 이미지 업로드 JavaScript 코드
function readFile(input) {
    if (input.files &amp;&amp; input.files[0]) {
        var reader = new FileReader();

        reader.onload = function (e) {
            var htmlPreview =
                &#39;&lt;img width=&quot;200&quot; src=&quot;&#39; + e.target.result + &#39;&quot; /&gt;&#39; +
                &#39;&lt;p&gt;&#39; + input.files[0].name + &#39;&lt;/p&gt;&#39;;
            var wrapperZone = $(input).parent();
            var previewZone = $(input).parent().parent().find(&#39;.preview-zone&#39;);
            var boxZone = $(input).parent().parent().find(&#39;.preview-zone&#39;).find(&#39;.box&#39;).find(&#39;.box-body&#39;);

            wrapperZone.removeClass(&#39;dragover&#39;);
            previewZone.removeClass(&#39;hidden&#39;);
            boxZone.empty();
            boxZone.append(htmlPreview);
        };

        reader.readAsDataURL(input.files[0]);
    }
}

function reset(e) {
    e.wrap(&#39;&lt;form&gt;&#39;).closest(&#39;form&#39;).get(0).reset();
    e.unwrap();
}

$(&quot;.dropzone&quot;).change(function () {
    readFile(this);
});

$(&#39;.dropzone-wrapper&#39;).on(&#39;dragover&#39;, function (e) {
    e.preventDefault();
    e.stopPropagation();
    $(this).addClass(&#39;dragover&#39;);
});

$(&#39;.dropzone-wrapper&#39;).on(&#39;dragleave&#39;, function (e) {
    e.preventDefault();
    e.stopPropagation();
    $(this).removeClass(&#39;dragover&#39;);
});

$(&#39;.remove-preview&#39;).on(&#39;click&#39;, function () {
    var boxZone = $(this).parents(&#39;.preview-zone&#39;).find(&#39;.box-body&#39;);
    var previewZone = $(this).parents(&#39;.preview-zone&#39;);
    var dropzone = $(this).parents(&#39;.form-group&#39;).find(&#39;.dropzone&#39;);
    boxZone.empty();
    previewZone.addClass(&#39;hidden&#39;);
    reset(dropzone);
});

function readURL(input) {
    if (input.files &amp;&amp; input.files[0]) {
        var reader = new FileReader();
        reader.onload = function (e) {
            $(&#39;.image-upload-wrap&#39;).hide();
            $(&#39;.file-upload-image&#39;).attr(&#39;src&#39;, e.target.result);
            $(&#39;.file-upload-content&#39;).show();
            $(&#39;.image-title&#39;).html(input.files[0].name);
        };
        reader.readAsDataURL(input.files[0]);
    } else {
        removeUpload();
    }
}

function readURL(input) {
    if (input.files &amp;&amp; input.files[0]) {

        var reader = new FileReader();

        reader.onload = function (e) {
            $(&#39;.image-upload-wrap&#39;).hide();

            $(&#39;.file-upload-image&#39;).attr(&#39;src&#39;, e.target.result);
            $(&#39;.file-upload-content&#39;).show();

            $(&#39;.image-title&#39;).html(input.files[0].name);
        };

        reader.readAsDataURL(input.files[0]);

    } else {
        removeUpload();
    }
}

function removeUpload() {
    $(&#39;.file-upload-input&#39;).replaceWith($(&#39;.file-upload-input&#39;).clone());
    $(&#39;.file-upload-content&#39;).hide();
    $(&#39;.image-upload-wrap&#39;).show();
}
$(&#39;.image-upload-wrap&#39;).bind(&#39;dragover&#39;, function () {
    $(&#39;.image-upload-wrap&#39;).addClass(&#39;image-dropping&#39;);
});
$(&#39;.image-upload-wrap&#39;).bind(&#39;dragleave&#39;, function () {
    $(&#39;.image-upload-wrap&#39;).removeClass(&#39;image-dropping&#39;);
});
</code></pre>
<h2 id="2-2-전체적인-코드-리뷰">2-2. 전체적인 코드 리뷰</h2>
<p>앞서 템플릿을 통해 이미지 업로드까지 구현했다.
<br>이제는 업로드 된 이미지를 동물상 테스트에 적용해야 한다.
<br>우선 코드에 사용된 웹캠의 잔재를 전부 없애야 한다.
<br>그럼 간단히 코드 리뷰를 해야 하는데,</p>
<pre><code class="language-html">&lt;button type=&quot;button&quot; onclick=&quot;init()&quot;&gt;Start&lt;/button&gt;</code></pre>
<p>위의 코드는 <code>index</code> 파일의 <code>HTML</code> 코드의 일부분이다.
<br>작동되는 순서에 따라 리뷰를 하자면, 우선 만들어진 웹의 <code>Start</code> 버튼을
<br>클릭하게 되면, 임의의 함수인 <code>init</code> 함수가 실행된다.
<br><code>init</code> 함수는 <code>JavaScript</code> 코드의 함수이기에
<br><code>JavaScript</code> 파일로 넘어가도록 한다.</p>
<pre><code class="language-js">async function init() {
        const modelURL = URL + &quot;model.json&quot;;
const metadataURL = URL + &quot;metadata.json&quot;;</code></pre>
<p>우선 위의 코드는 <code>Start</code> 버튼을 클릭하면서 <code>init</code> 함수가 실행되고,
<br><code>Teachable Machine</code>에서 학습시켰던 <code>model.json</code>와 <code>metadata.json</code>을
<br>초기값으로 불러오게 된다.</p>
<blockquote>
<p><em><code>init</code> 자체가 초기화라는 의미로 곧 잘 사용되는 것을 보면,
임의의 함수를 만드는 작업에 쓰이는 <code>init</code>은 초기값을 의미하는 함수로 보인다.
예를 들면, 에디터 툴과 <code>Git</code>의 연동 작업에서 <code>git init</code> 명령어를 통해
<code>GitHub</code>의 로컬 저장소를 초기화할 때 사용하는 단어가 바로 <code>init</code>의 경우다.</em></p>
</blockquote>
<p>여담은 이제 그만하도록 하고, 다음 코드를 보겠다.</p>
<pre><code class="language-js">model = await tmImage.load(modelURL, metadataURL);
maxPredictions = model.getTotalClasses();</code></pre>
<p>한 줄씩 리뷰를 하자면,
<br><code>init</code> 함수를 실행시키면서 <code>model.json</code>와 <code>metadata.json</code>을 <code>load</code>하는 작업을
<br><code>model</code>이라는 변수에 담아두고, <code>model</code>에 해당하는 앞서 지정한 모든 <code>Class</code>들을
<br>예측할 수 있도록 불러오는 작업을 하고,</p>
<pre><code class="language-js">const flip = true;
webcam = new tmImage.Webcam(200, 200, flip);
await webcam.setup();
await webcam.play();
window.requestAnimationFrame(loop);</code></pre>
<p>웹캠을 좌우 반전시키고 넓이 등을 설정, 웹캠에 접근해서 실행시키도록 하고,
<br>웹캠이 실행되면서 <code>loop</code> 반복문을 실행시키는 코드로 이해했다.</p>
<pre><code class="language-js">document.getElementById(&quot;webcam-container&quot;).appendChild(webcam.canvas);
labelContainer = document.getElementById(&quot;label-container&quot;);
for (let i = 0; i &lt; maxPredictions; i++) {
    labelContainer.appendChild(document.createElement(&quot;div&quot;));
        }
    }</code></pre>
<p>다음 위의 코드를 간단하게 보자면,
<br>웹캠을 출력할 <code>container</code>를 만들어주고, 자식요소로 웹캠을 띄울 <code>canvas</code>를
<br>생성해준다!!..라고 이해했다...
<br>그럼 웹캠의 실행으로 작동하는 <code>loop</code> 반복문 부분을 보자면,</p>
<pre><code class="language-js">async function loop() {
    webcam.update();
await predict();
window.requestAnimationFrame(loop);
    }</code></pre>
<p>웹캠이 업데이트가 되면 반복해서 동물상 예측을 하고,
<br>웹캠의 움직임에 따라 계속해서 <code>loop</code> 함수를 실행하는 코드이다.
<br>그럼 여기서 나오는 예측이라는 <code>predict</code>는 무엇인가?
<br>다음 코드에서 등장한다.</p>
<pre><code class="language-js">async function predict() {
        const prediction = await model.predict(webcam.canvas);
for (let i = 0; i &lt; maxPredictions; i++) {
            const classPrediction =
prediction[i].className + &quot;: &quot; + prediction[i].probability.toFixed(2);
labelContainer.childNodes[i].innerHTML = classPrediction;
        }
    }</code></pre>
<p>위의 코드는 <code>predict</code>라는 동물상 예측 함수이다.
<br>이해한 바로 간단하게 리뷰해 보자면,
<br>하나의 영상이라는 차원의 <code>webcam.canvas</code>를 이미지로써 예측하도록 지정하고,
<br>앞서 <code>model.json</code>와 <code>metadata.json</code>을 모든 클래스에서 예측하도록 지정해 둔
<br><code>maxPredictions</code>를 <code>for</code>문을 사용하여 예측을 반복해서 결과를
<br>도출할 수 있도록 코드가 짜여져 있다.
<br>그렇게 나온 동물상 예측 결과를
<br>&lt;예측 결과의 <code>className</code>&gt; : &lt;예측 결과의 확률&gt; 형식으로
<br><code>HTML</code>에 출력하면서 결과가 나온다.
<br>예시로 들자면, <code>곰 상 : 0.845</code> 이런 식이다.</p>
<h2 id="2-3-업로드된-이미지-적용하기">2-3. 업로드된 이미지 적용하기</h2>
<p>본격적으로 앞서 리뷰했던 코드에서 웹캠 부분을 이미지로 변경하거나,
<br>아예 사용되지 않는 웹캠은 삭제하는 작업을 하도록 하겠다.
<br>일단 간단하게 생각할 수 있는 부분은 바로 반복문의 필요성이다.
<br>웹캠의 경우 계속해서 움직이는 모습을 반복적으로 예측을 해야 하기 때문에
<br>반복문을 사용해서 끊임없이 값이 변동한다.
<br>하지만 이미지는?
<br>그런거 없다. 깔끔하게 멈춰있다.
<br>그럼 당연히! 반복문은 OUT!
<br>당연히 웹캠이라는 단어도 전부 지워보도록 하겠다.</p>
<pre><code class="language-js">const URL = &quot;https://teachablemachine.withgoogle.com/models/WXmTZBNlH/&quot;;

let model, webcam, labelContainer, maxPredictions;

async function init() {
        const modelURL = URL + &quot;model.json&quot;;
const metadataURL = URL + &quot;metadata.json&quot;;

model = await tmImage.load(modelURL, metadataURL);
maxPredictions = model.getTotalClasses();

// 웹캠, loop 부분 삭제
/*const flip = true;
webcam = new tmImage.Webcam(200, 200, flip);
await webcam.setup();
await webcam.play();
window.requestAnimationFrame(loop);*/

// 웹캠 부분 삭제
// document.getElementById(&quot;webcam-container&quot;).appendChild(webcam.canvas);
labelContainer = document.getElementById(&quot;label-container&quot;);
for (let i = 0; i &lt; maxPredictions; i++) {
    labelContainer.appendChild(document.createElement(&quot;div&quot;));
        }
    }

// 반복문 삭제
/*async function loop() {
    webcam.update();
await predict();
window.requestAnimationFrame(loop);
    }*/

// 웹캠 부분 삭제
async function predict() {
        // const prediction = await model.predict(webcam.canvas);
          // 이 부분에 이미지를 예측하도록 수정한다.
for (let i = 0; i &lt; maxPredictions; i++) {
            const classPrediction =
prediction[i].className + &quot;: &quot; + prediction[i].probability.toFixed(2);
labelContainer.childNodes[i].innerHTML = classPrediction;
        }
    }</code></pre>
<p>위의 코드에서 이제 해야 할 것은 이미지 업로드!
<br>우선 웹캠의 <code>id</code>값을 <code>getElementById</code>로 불러와서 예측했다는 것을
<br>위의 코드에서 삭제한 웹캠 부분을 통해서 볼 수 있다.</p>
<pre><code class="language-js">document.getElementById(&quot;webcam-container&quot;).appendChild(webcam.canvas);</code></pre>
<p>바로 이 부분이다!
<br>웹캠은 자식요소로 <code>canvas</code>를 <code>HTML</code>에 띄워주는 작업을 했지만,
<br>이미지는 그런거 필요 없다.
<br>자식요소 생성의 <code>appendChild</code>부분은 과감하게 없애주도록 하고,
<br>이미지를 사용할 수 있는 코드를 구글링으로 찾아보도록 하자!
<br>전체적으로 코드를 쭉 보다가 주석에 <code>GitHub</code> 주소를 찾았다.
<br><a href="https://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/image">teachable machine GitHub</a> 이 링크이며,
<br><code>Teachable Machine</code> 공식 <code>GitHub</code>이다.
<br>사용 설명서와 같은 느낌으로 작성되어 있어서 쭉 내리며 찾던 중,</p>
<pre><code class="language-js">model.predict(
  image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ImageBitmap,
  flipped = false
)</code></pre>
<p>이러한 코드를 찾았다.
<br>내용은 <code>model.predict()</code>의 인자로 이미지나, 캔ㄴ버스, 비디오 등이 들어갈 수 있고,
<br>좌, 우 반전을 할지의 여부를 인자로 입력하면 된다고 한다.</p>
<pre><code class="language-js">model.predict(image, false);</code></pre>
<p>이렇게 말이다.
<br>웹캠 대신, 이미지를 넣기는 했지만, 이미지의 해당 <code>id</code>를 불러도록 <code>id</code>값을 찾는
<br>작업을 시작하도록 한다.
<br>간단하다. 아주.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/9cb0c47f-61c4-4b82-8435-26a4c9fede5b/image.PNG" alt="">
개발자 메뉴를 통해 이미지의 <code>id</code>값은 <code>upload-image</code>라는 것을 알아냈다.
<br>정리해서 코드를 보자면,</p>
<pre><code class="language-js">async function predict() {
          var image = document.getElementById(&quot;upload-image&quot;);
          // 해당 이미지의 id 가져오기
        const prediction = await model.predict(image, false);
          // 이미지로써의 예측을 실행하도록 수정
for (let i = 0; i &lt; maxPredictions; i++) {
            const classPrediction =
prediction[i].className + &quot;: &quot; + prediction[i].probability.toFixed(2);
labelContainer.childNodes[i].innerHTML = classPrediction;
        }
    }</code></pre>
<p>일단 필자가 이해한 바로만 주절주절 설명했다.
<br>기타 <code>CSS</code>, 이미지 템플릿 관련된 사항은 생략하도록 하겠다...
<br>마지막으로 웹캠을 이용할 시에 자동으로 예측되는 것을
<br>사진을 올리고, 버튼을 클릭하는 방식으로 바꿔야 한다.
<br>다시 <code>HTML</code> 코드로 돌아와서 <code>Start</code> 버튼 옆에</p>
<pre><code class="language-html">&lt;button type=&quot;button&quot; onclick=&quot;predict()&quot;&gt;Predict&lt;/button&gt;</code></pre>
<p>이렇게 <code>predict()</code> 함수를 실행시키는 버튼을 만들어
<br><code>Start</code> 버튼 클릭 → 얼굴 사진 올리기 → <code>Predict</code> 버튼으로 결과 출력
<br>이러한 순서로 동물상 테스트를 할 수 있는 웹을 만들었다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/584741cd-5f8c-4144-8201-6bd23d1a9170/image.png" alt="">
<img src="https://velog.velcdn.com/images/hyungjin_han/post/00ec00ad-29cd-4c9d-a27a-ce1c7f543b2a/image.jpg" alt="">
필자는 공룡 상 98%가 나왔다.
<br>난생 처음 들어봤다... 공룡 상...
<img src="https://velog.velcdn.com/images/hyungjin_han/post/8b0e5a80-cc05-44d5-8ba4-40e8e9a04588/image.PNG" alt="">
뭐... 결과는 나왔다! 아마 데이터로써의 자료가 부족했던 것 같다.
<br>안일하게 너무 적은 데이터를 사용하긴 했다.
<br>여러가지로 어려운 시간이었다.</p>
<blockquote>
<p><em>물론 프로그래밍 코드를 짠 것에 대한 것보다도, 이해하고 해석하는 부분이
굉장히 어려운 부분이 많았다.
하나씩 차근차근 영어 뜻 생각하며 해석을 해보고 이해하려고 노력은 했다...노력은...
사실 위의 내용이 맞는 지도 작성하면서도 긴가민가한 부분이 많았다.
추후에 다른 수업을 통해 늘도록 열심히 하는 수 밖에...</em></p>
</blockquote>
<hr>
<h1 id="마치며">마치며...</h1>
<p>우선 위의 과정을 거치며 만들어진 웹을 보고 느낀점은...
<br>프로젝트 구상을 처음부터 다시 해서 다른 데이터를 통해 다른 결과를
<br>도출하는, 코드는 같을 수 있지만, 학습된 데이터를 다르게 하고
<br>다른 결과물이 나오는 음...예를 들면 동안 테스트? 이런 것을 다시 만들어 보고 싶다.
<br>아니 만들어야겠다.
<br>이렇게 쭉 이어간다면 충분히 가능할 것 같다.
<br>일단 인터페이스를 좀 꾸미고 편의성을 갖춘 완성된 웹을 만들고
<br>추후에 도전해봐야겠다.
<br>다음 시간에는 인터페이스, 편의성을 고려해서 웹을 좀 꾸밀 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[GitHub] GitHub Repository 합치기]]></title>
            <link>https://velog.io/@hyungjin_han/repositoryMerge</link>
            <guid>https://velog.io/@hyungjin_han/repositoryMerge</guid>
            <pubDate>Thu, 16 Jun 2022 11:54:10 GMT</pubDate>
            <description><![CDATA[<p>문득 GitHub에 Commit을 하던 중, 아예 쓸 줄도 모르고 그냥 공부한 것들을
<br>무지성으로 Commit 한 것들이 너무 거슬리고 지저분하게 느껴졌다.</p>
<blockquote>
<p><em>물론 지금도 잘 관리하고 있다고는 전혀 말할 수 없는 입장이다...
그래도 무지성 삭제를 해서 탈모에 걸린 잔디를 보고 싶지는 않았다.
적어도 Repository를 합치면 기존에 Commit 했던 것들이 사라지지는 않기 때문에
PC 디렉토리 정리하는 것처럼 쉽게 생각해서 도전했지만 어렵다보니까 글로 남겼다...</em></p>
</blockquote>
<hr>
<h1 id="1-새로운-repository-생성">1. 새로운 Repository 생성</h1>
<p>우선 GitHub에 접속해서 Repository를 먼저 생성한다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/93a966b4-f4ae-40c0-b1ef-c0cf4e7272b9/image.PNG" alt="">
생성은 위의 이미지에서 <code>📔New</code> 부분을 클릭해서 생성하면 된다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/4f1e8d1b-9f93-4e51-a4e5-4a1156648ccc/image.PNG" alt="">
<code>📔New</code>를 클릭한 후,
<br>위의 이미지처럼 <code>Repository Name</code>을 작성한다.
<br>물론 <code>Repository Name</code>은 개인의 취향대로 입력하면 된다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/db67e0ca-b9ae-4992-9902-f0b73a4592c8/image.PNG" alt="">
위의 이미지처럼 <code>Public</code>으로 설정해주면 된다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/aea8e50b-fd68-4ba7-ad14-98e0f38dc631/image.PNG" alt="">
위에 보이는 <code>Add a README file</code>을 체크해주면서 Repository 내에 파일을 하나 생성해준다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/3c77c824-359c-44e9-97cf-00d406368f31/image.PNG" alt=""></p>
<hr>
<h1 id="2-생성한-repository-로컬-저장소로-clone">2. 생성한 Repository 로컬 저장소로 Clone</h1>
<p>이제 위에 보이는 <code>Code ▼</code>를 클릭하면 보이는
<img src="https://velog.velcdn.com/images/hyungjin_han/post/76069141-99cb-4658-8681-84b7c0be8e79/image.PNG" alt="">
<code>https</code> 주소를 복사한다.
<br>그 후로 로컬 저장소에 Clone(복사의 개념)할 차례이다.
<br><code>cmd</code>를 통해서</p>
<pre><code class="language-bash">git clone https://복사한/git/주소.git</code></pre>
<p>만약에 로컬 저장소가 없다면 <code>git init</code>을 입력해준다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/f92462a1-717d-4a07-a871-15fe85c3aafc/image.PNG" alt="">
성공한 모습이다.</p>
<pre><code class="language-bash">cd Clone한\디렉토리\경로\생성한Repository이름

#Example
cd C:\Users\ADMIN\merge_test</code></pre>
<p><br>그 후, 위의 코드를 통해 Clone한 폴더로 이동한다.</p>
<hr>
<h1 id="3-기존의-repository-옮기기">3. 기존의 Repository 옮기기</h1>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/eaf916bf-0bf7-426c-b1e5-38a8c6882075/image.PNG" alt="">
새로 생성한 Repository로 들어갈 <u><strong>기존의 Repository의 주소</strong></u>를 복사한다.</p>
<pre><code class="language-bash">git subtree add --prefix=기존Repository이름 기존Repository주소 기존RepositoryBranch

# Example
git subtree add --prefix=test_son https://github.com/HyungJinHan/test_son.git main</code></pre>
<p><img src="https://velog.velcdn.com/images/hyungjin_han/post/1580048b-7647-4f58-891b-f9aa143acc83/image.PNG" alt="">
성공한 모습이다.
<br>현재의 진행 상황은 생성한 Repository를 로컬 저장소에 Clone했고,
<br>로컬 저장소의 Clone 디렉토리에 옮겨질 기존의 Repository가 들어가 있는 상황이다.
<br>또한 <code>cmd</code> 상으로는 생성한 Repository의 로컬 저장소의
<br>디렉토리에 머물러있는 상태이다.
<br>물론 로컬 저장소에서만의 진행 상황이다.
<br>GitHub에는 아직 동기화를 하지 않은 상태이다.</p>
<hr>
<h1 id="4-github와-로컬-저장소-동기화">4. GitHub와 로컬 저장소 동기화</h1>
<p>마지막으로 GitHub와 로컬 저장소를 동기화 할 차례이다.
<br>다른 말로 표현하자면 <code>push</code>라고 한다.</p>
<pre><code class="language-bash">git push</code></pre>
<p>위의 코드를 입력해서 GitHub에 <code>push</code>를 해주면 동기화가 된다.
<img src="https://velog.velcdn.com/images/hyungjin_han/post/11ca652b-6604-4c86-8c0e-2890dd850232/image.PNG" alt="">
성공한 모습이다.
<br>모든 작업이 끝났다면, GitHub에 접속해서 결과를 확인한다.
<br>새롭게 생성한 Repository를 확인해보면,
<img src="https://velog.velcdn.com/images/hyungjin_han/post/960457cc-a7f8-40b1-8f6f-f6b79f3339da/image.PNG" alt="">
Good! 👍
<br>결과물을 확인했다면, 기존의 지저분한 Repository를 삭제하면 된다.
<br>로컬 저장소의 Clone한 디렉토리를 더이상 사용하지 않는다면,
<br>삭제해도 무방하지만, 계속해서 원격으로 GitHub를 관리하고 싶다면
<br>삭제하지 않고 사용하면 된다.</p>
]]></description>
        </item>
    </channel>
</rss>