<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>DevSeong2</title>
        <link>https://velog.io/</link>
        <description>차근차근</description>
        <lastBuildDate>Wed, 25 Oct 2023 04:18:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. DevSeong2. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/code_newb" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[팀 프로젝트 협업하기 (git 전략)]]></title>
            <link>https://velog.io/@code_newb/%ED%8C%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-github</link>
            <guid>https://velog.io/@code_newb/%ED%8C%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-github</guid>
            <pubDate>Wed, 25 Oct 2023 04:18:33 GMT</pubDate>
            <description><![CDATA[<h1 id="팀-프로젝트-협업하기">팀 프로젝트 협업하기</h1>
<blockquote>
<p>공유용으로 작성. Organization을 사용하려면 github 블로그에 작성한 글 참고 <a href="https://scseong.github.io/til/231024TIL/">TIL 23-10-24</a></p>
</blockquote>
<h2 id="목차">목차</h2>
<ul>
<li>깃 전략 수립<ul>
<li>커밋</li>
<li>Issue</li>
<li>Projects</li>
<li>PR</li>
<li>Wiki</li>
<li>브랜치 전략</li>
</ul>
</li>
</ul>
<h2 id="깃-전략-수립">깃 전략 수립</h2>
<p>github으로 협업하며 프로젝트 전반을 관리하기 위해 제공하는 기능들을 사용한다. 순서대로 기록해보았다.</p>
<h3 id="커밋">커밋</h3>
<p>커밋 메시지도 각자 작성하는 방식이 다르다. 특정 커밋을 보고 어떤 내용인지 충분히 추측 가능해야 한다. 그래야 가독성이 높아지고 개발 속도가 빨라지며 코드에 대한 리뷰도 수월해진다. 따라서, 공통적인 커밋 메시지 규칙을 정한다. </p>
<h4 id="커밋-유형-작업-내용-이슈-넘버">커밋 유형: 작업 내용 (#이슈 넘버)</h4>
<pre><code>type: subject (#issue_number)</code></pre><h4 id="커밋-유형">커밋 유형</h4>
<ul>
<li>feat : 새로운 기능 추가</li>
<li>fix : 버그 수정</li>
<li>docs : 문서 수정</li>
<li>style : 코드 포맷팅, 세미콜론 누락, 코드 변경이 없는 경우</li>
<li>refactor : 코드 리펙토링</li>
<li>test : 테스트 코드, 리펙토링 테스트 코드 추가</li>
<li>chore : 빌드 업무 수정, 패키지 매니저 수정</li>
</ul>
<h4 id="규칙">규칙</h4>
<ul>
<li>type은 소문자로 작성</li>
<li>제목 끝에 마침표 넣지 않기</li>
<li>명사형으로 작성</li>
</ul>
<h3 id="issue">Issue</h3>
<p>이슈(Issue)란 프로젝트 작업 단위이다. 개발, 오류, 건의 등 프로젝트에서 발생한 문제들을 이슈로 생성하여 관리한다. 커밋 메시지에 이슈 번호를 포함하면 이슈에 대한 커밋 내역들을 해당 페이지에서 확인할 수 있다. 작업을 시작하기 전 이슈를 생성하는 것이 가장 먼저 하는 일이다. 작업할 일을 명시하는 작업.</p>
<p>이슈 템플릿을 사용하면 일관된 양식으로 작성할 수 있다. 템플릿을 등록하면 이슈를 기능 구현과 버그 수정으로 구분하여 선택할 수 있다.  </p>
<p><img src="https://velog.velcdn.com/images/code_newb/post/876aa79c-67ee-47e5-a3e7-b992362160fd/image.png" alt=""></p>
<p>이슈를 생성할 때는 담당자(assignees)를 지정하고 Labels을 사용해 작업 유형을 구분한다. 그리고 Projects를 지정하면 프로젝트에서 이슈들을 한 눈에 확인할 수 있다. 제목은 다음과 같이 작성한다. <code>[작업유형/기능명] 내용</code> 작업유형은 커밋 메시지 컨벤션을 따른다.</p>
<blockquote>
<p><a href="https://velog.io/@yulhee741/Github-Issue-Templates%EC%9C%BC%EB%A1%9C-Issue-%EC%89%BD%EA%B3%A0-%EC%B2%B4%EA%B3%84%EC%A0%81%EC%9D%B4%EA%B2%8C-%EC%9E%91%EC%84%B1%ED%95%B4%EB%B3%B4%EA%B8%B0">Github Issue Templates으로 Issue 쉽고 체계적이게 작성해보기</a></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/code_newb/post/41bc10ee-11f5-4657-905e-81f191648a2a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/code_newb/post/f89de3b0-519e-4fa9-a61d-495851b855c0/image.png" alt=""></p>
<h4 id="issue-작성법">Issue 작성법</h4>
<ol>
<li>템플릿에 맞게 Issue 내용 작성</li>
<li>담당자(Assignee)를 지정</li>
<li>라벨 달기</li>
<li>프로젝트 지정</li>
</ol>
<h3 id="projects">Projects</h3>
<p>잠시 살펴봤지만 Projects는 프로젝트의 작업 내용과 진행 사항을 볼 수 있는 페이지다. 이슈들과 PR(Pull Request)를 한 눈에 볼 수 있다. PR을 생성할 때도 Projects에 추가할 수 있다. Projects를 사용하면 작업을 추적하고 프로젝트를 직관적으로 관리할 수 있다.</p>
<ul>
<li>To Do: 해야할 작업</li>
<li>In Progress: 진행 중인 작업</li>
<li>Done: 완료된 작업</li>
</ul>
<p>노션에도 동일한 기능이 있지만 github에서 전반적으로 관리할 수 있다는 장점이 있어 사용한다. 템플릿은 변경할 수 있지만 칸반 보드 형식이 자주 사용되므로 Board를 사용한다.</p>
<h3 id="pr">PR</h3>
<p>이슈를 기반으로 작업을 수행한 뒤 PR을 생성한다. 마찬가지로 정의된 템플릿을 활용해 PR을 생성하고 git-flow 개발 프로세스에 따라 개발한다. 커밋과 PR은 최대한 작은 단위로 쪼개는 것이 좋다. </p>
<h4 id="규칙-1">규칙</h4>
<ul>
<li>제목은 이슈 제목과 동일하게 하고 이슈 번호 붙이기<ul>
<li><code>[feature/search] 검색 기능 구현 (#1)</code></li>
</ul>
</li>
<li>Reviewers, Assignees, Labels, Projects, Linked issues 지정</li>
<li>검토가 끝나면 본인이 직접 PR을 merge하고 브랜치 삭제</li>
</ul>
<p>▶ git 연습 레포에서 이미 생성된 PR을 가지고 왔다.</p>
<p><img src="https://velog.velcdn.com/images/code_newb/post/fb5fef0a-11f8-4535-9847-91034eb3531c/image.png" alt=""></p>
<p>develop 브랜치와 main 브랜치는 브랜치 보호 규칙을 설정해 3명 이상 approve가 있어야 merge할 수 있도록 할 예정이다.</p>
<h3 id="wiki">Wiki</h3>
<p>문서를 공유하기 위해 github의 Wiki를 사용한다. 팀 소개와 프로젝트 내용, 개발 관련 문서 등 모두 Wiki에서 관리한다. 비슷한 유형의 문서끼리 분류하고 가독성을 높이기 위해 사이드바를 이용해 Wiki 문서를 표시할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/code_newb/post/3440c314-ac20-4fad-b048-f0726b55c432/image.png" alt=""></p>
<h3 id="브랜치-전략">브랜치 전략</h3>
<p>브랜치 전략이란 여러 개발자가 협업하는 환경에서 git 저장소를 효과적으로 활용하기 위한 workflow이다. git-flow라는 브랜치 전략을 사용한다. </p>
<p>git-flow: 5가지의 브랜치를 이용해 운영하는 브랜치 전략</p>
<blockquote>
<p> <a href="https://techblog.woowahan.com/2553/">우린 Git-flow를 사용하고 있어요 | 우아한형제들 기술블로그</a> </p>
</blockquote>
<ul>
<li><strong>main</strong>: 배포 가능한 브랜치</li>
<li><strong>develop</strong>: 개발한 기능이 모여있는 브랜치</li>
<li><strong>feature</strong>: 기능을 개발하는 브랜치 (develop 에서 분기)</li>
<li><strong>release</strong>: QA(품질검사)를 하기위한 브랜치 (출시 준비)</li>
<li><strong>hotfix</strong>: main 브랜치에 발생한 버그를 긴급수정하는 브랜치</li>
</ul>
<p><img src="https://camo.githubusercontent.com/6d61043b3dc77c8ce360595fdcb12a164494358a6826cf46053d952f1f3d3b72/68747470733a2f2f74656368626c6f672e776f6f776168616e2e636f6d2f77702d636f6e74656e742f75706c6f6164732f696d672f323031372d31302d33302f6769742d666c6f775f6f766572616c6c5f67726170682e706e67" alt="git-flow_overall_graph"></p>
<p>실제 적용은 main, develop, feature, hotfix 네 개의 브랜치만 사용할 듯하다.</p>
<h4 id="브랜치-네이밍-컨벤션">브랜치 네이밍 컨벤션</h4>
<ul>
<li>main</li>
<li>develop</li>
<li>feature/{feature_name}</li>
<li>hotfix/{issue_number}</li>
</ul>
<h4 id="git-flow-개발-프로세스">git-flow 개발 프로세스</h4>
<ol>
<li><p>develop 브랜치에서 새로운 기능 개발 브랜치 생성 feature/{feature_name}</p>
</li>
<li><p>개발 후 feature/{feature_name} 브랜치에 push</p>
</li>
<li><p>develop 브랜치에 pull requests</p>
</li>
<li><p>reviewer들의 리뷰가 승인되면 본인이 merge (merge한 브랜치는 삭제)</p>
</li>
<li><p>최종 테스트 후 main 브랜치에 merge</p>
<p>5.1. main 브랜치에서 버그가 발생한다면 hotfix 브랜치 생성</p>
<p>5.2. 버그 수정이 끝나면 develop과 main 브랜치에 각각 merge</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[타입스크립트 이해하기]]></title>
            <link>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 12 Sep 2023 04:57:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>&quot;한 입 크기로 잘라먹는 타입스크립트 - 인프런&quot; 강의를 요약하고 덧붙인 글입니다.</p>
</blockquote>
<h2 id="타입스크립트를-이해하기-위해">타입스크립트를 이해하기 위해</h2>
<ul>
<li>어떤 기준으로 타입을 정의하는지</li>
<li>어떤 기준으로 타입간의 관계를 정의하는지</li>
<li>어떤 기준으로 타입의 오류를 검사하는지
타입스크립트의 구체적인 원리와 동작 방식에 대해 살펴보겠습니다. </li>
</ul>
<h2 id="타입은-집합이다">타입은 집합이다</h2>
<p>타입스크립트의 타입은 &#39;집합&#39;입니다. 집합은 동일한 속성을 갖는 여러개의 요소들을 하나의 그룹으로 묶은 단위를 말합니다. 예를 들어, number 타입은 정수, 실수, 양수, 음수, 지수 등 모든 숫자 값들을 묶어 놓은 집합입니다. 
<img src="https://velog.velcdn.com/images/code_newb/post/92081619-d144-43e7-abb6-70c9f380719b/image.png" alt="">Number Literal 타입은 하나의 값만 포함하는 아주 작은 집합이라고 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/code_newb/post/e2a0de24-578a-434a-8943-a883f989fd1a/image.png" alt="">모든 Number Literal 타입은 Number 타입이라는 집합에 포함되는 부분 집합으로 볼 수 있습니다. 타입스크립트의 모든 타입들은 집합으로써 서로 포함하고 또 포함되는 관계를 갖습니다. </p>
<p>다른 타입을 포함하는 타입을 슈퍼 타입(부모 타입), 반대는 서브 타입(자식 타입)이라고 합니다.
<img src="https://velog.velcdn.com/images/code_newb/post/9dca76ea-e8e8-4677-b0b5-47e8f12bbfe6/image.png" alt=""></p>
<h3 id="타입-호환성">타입 호환성</h3>
<p>타입 호환성은 어떤 타입을 다른 타입으로 취급해도 괜찮은지 판단하는 것을 말합니다. </p>
<p>예를 들어 Number 타입과 Number Literal 타입이 있을 때 서브 타입인 Number Literal 타입의 값을 슈퍼 타입인 Number 타입의 값으로 취급하는 것은 가능합니다. 그러나 반대로는 불가능합니다.</p>
<p>Number 타입이 Number Literal 타입보다 더 큰 타입이기 때문입니다.</p>
<pre><code class="language-ts">let num1: number = 10;
let num2: 10 = 10;

num1 = num2; // ⭕
num2 = num1; // ❌</code></pre>
<p>집합의 관점에서 본다면 Number Literal 타입의 값 10은 모든 숫자를 포함하는 Number 타입에 포함되지만 그 역은 성립하지 않습니다.</p>
<p>서브 타입의 값을 슈퍼 타입의 값으로 취급하는 것을 업 캐스팅, 반대는 다운 캐스팅이라고 부릅니다. 업 캐스팅은 모든 상황에 가능하지만 다운 캐스팅은 대부분 불가능합니다.
<img src="https://velog.velcdn.com/images/code_newb/post/143bda32-2c6f-4ab8-a21a-4280b3d22523/image.png" alt=""></p>
<h2 id="타입-계층도와-함께-기본타입-살펴보기">타입 계층도와 함께 기본타입 살펴보기</h2>
<p>타입스크립트 타입 계층도는 기본 타입들간의 집합으로써 부모-자식 관계를 설명합니다.
<img src="https://velog.velcdn.com/images/code_newb/post/33320e59-f001-49bf-a76a-31265e11cab5/image.png" alt=""></p>
<h3 id="unknown-타입-전체-집합">unknown 타입 (전체 집합)</h3>
<p>unknown 타입은 타입 계층도의 최상단에 위치합니다. unknown 타입은 모든 타입의 슈퍼타입, 모든 타입은 unknown 타입의 부분집합입니다.</p>
<p>따라서 unknown 타입 변수에는 모든 타입의 값을 할당할 수 있습니다(업 캐스팅). </p>
<pre><code class="language-ts">let a: unknown = 1;
let b: unknown = &#39;a&#39;;
let c: unknown = true;
let d: unknown = null;
let e: unknown = undefined;
let f: unknown = [];
let g: unknown = {};
let h: unknown = () =&gt; {};</code></pre>
<p>반대로는 불가능합니다. unknown 타입의 값은 any를 제외한 어떤 타입의 변수에도 할당할 수 없습니다(다운 캐스팅).</p>
<pre><code class="language-ts">let unknownValue: unknown;

let a: number = unknownValue; // ❌</code></pre>
<h3 id="never-타입-공집합-타입">never 타입 (공집합 타입)</h3>
<p><img src="https://velog.velcdn.com/images/code_newb/post/1296a5c3-c4d6-4859-9ad8-0c1a4dd13bf4/image.png" alt="">
never 타입은 타입 계층도에서 가장 아래에 위치합니다. never 타입은 모든 집합의 부분집합 즉, 공집합입니다. 공집합은 원소의 개수가 0인 집합을 말합니다.</p>
<p>따라서 never 타입에 해당하는 값은 아무것도 없습니다. 어떤 값도 반환할 수 없는 무한루프나 비정상적 종료 등의 상황에 주로 사용됩니다. </p>
<p>공집합은 모든 집합의 부분집합. 그러므로 never 타입은 모든 타입의 서브 타입으로 모든 타입으로 업캐스팅 할 수 있습니다. </p>
<p>반대는 불가능합니다. 그래서 어떤 값도 저장되어서는 안 되는 변수의 타입으로 활용하기에 좋습니다.</p>
<pre><code class="language-ts">let neverVar: never;

let a: number = neverVar; 
let b: string = neverVar; 
let c: boolean = neverVar;    
let d: null = neverVar;  
let e: undefined = neverVar;  
let f: [] = neverVar;     
let g: {} = neverVar;

let never1: never = 10; // ❌</code></pre>
<h3 id="void-타입">void 타입</h3>
<p><img src="https://velog.velcdn.com/images/code_newb/post/76cfa34f-6940-41fe-a201-d7cd78162cca/image.png" alt="">
void 타입은 undefined 타입의 슈퍼타입입니다. 따라서 반환값을 void로 선언한 함수에서 undefined을 반환 해도 오류가 발생하지 않습니다. undefined 타입은 void 타입의 서브 타입이므로 업캐스팅이 가능하기 때문입니다.</p>
<pre><code class="language-ts">function noReturnFuncA(): void {
  return undefined;
}

function noReturnFuncB(): void {
  return;
}

function noReturnFuncC(): void {}</code></pre>
<p>void 타입의 서브타입은 undefined 타입과 never 타입 밖에 없습니다. 따라서 void 타입에는 undefined, never 이외에 다른 타입의 값을 할당할 수 없습니다.</p>
<h3 id="any-타입-치트키">any 타입 (치트키)</h3>
<p>any 타입은 사실상 타입 계층도를 완전히 무시합니다. 모든 타입의 슈퍼타입이 될 수도 있고 모든 타입의 서브 타입이 될 수도 있습니다.
<img src="https://velog.velcdn.com/images/code_newb/post/d70b2004-cd2f-4c76-8145-1a6b8f3f299e/image.png" alt="">
any 타입은 모든 타입으로 다운캐스트 할 수 있으며 또 모든 타입은 any 타입으로 업 캐스트 할 수 있습니다.</p>
<pre><code class="language-ts">let anyVar: any;
let unknownVar: unknown;
let undefinedVar: undefined;

anyVar = unknownVar; // 다운 캐스트
undefinedVar = anyVar; // 업 캐스트</code></pre>
<p>단, never 타입의 변수에 any 타입의 값을 할당할 수는 없습니다.</p>
<pre><code class="language-ts">let neverVar = anyVar; // ❌</code></pre>
<h2 id="객체-타입의-호환성">객체 타입의 호환성</h2>
<p>객체 타입은 프로퍼티를 기준으로 다른 객체 타입들과 슈퍼-서브 타입 관계를 갖습니다.</p>
<pre><code class="language-ts">type Animal = {
  name: string;
  color: string;
};

type Dog = {
  name: string;
  color: string;
  breed: string;
};

let animal: Animal = {
  name: &#39;기린&#39;,
  color: &#39;yellow&#39;,
};

let dog: Dog = {
  name: &#39;돌돌이&#39;,
  color: &#39;brown&#39;,
  breed: &#39;진도&#39;,
};

animal = dog; // ✅ OK
dog = animal; // ❌ </code></pre>
<p>Dog 타입이 더 많은 프로퍼티를 정의하고 있어 슈퍼타입처럼 보일 수 있지만 Animal 타입이 Dog 타입의 슈퍼타입입니다. </p>
<blockquote>
<p>TypeScript의 타입 호환성은 구조적 서브 타이핑(subtyping)을 기반으로 합니다. 구조적 타이핑이란 오직 멤버만으로 타입을 관계시키는 방식입니다. 명목적 타이핑(nominal typing) 과는 대조적입니다. TypeScript의 구조적 타입 시스템의 기본 규칙은 y가 최소한 x와 동일한 멤버를 가지고 있다면 x와 y는 호환된다는 것입니다. - <a href="https://www.typescriptlang.org/ko/docs/handbook/type-compatibility.html">TypeScript 공식 문서 - 타입 호환성</a></p>
</blockquote>
<p>타입스크립트는 프로퍼티를 기준으로 타입을 정의하는 구조적 타입 시스템을 따릅니다. Animal 타입은 name과 color 프로퍼티를 가지는 타입입니다. Dog 타입은 name과 color 프로퍼티, 추가로 breed 프로퍼티를 가집니다.</p>
<p>Dog 타입의 객체는 Animal 타입의 name과 color 프로퍼티를 반드시 가집니다. 따라서 Animal 타입에도 해당하는 객체입니다. 반대로 Animal 타입은 Dog 타입의 breed 프로퍼티를 가지고 있지 않으므로 Dog 타입에는 해당하지 않습니다.</p>
<blockquote>
<p><a href="https://blog.hwahae.co.kr/all/tech/9954">집합의 관점에서 타입스크립트 바라보기</a></p>
</blockquote>
<h3 id="초과-프로퍼티-검사">초과 프로퍼티 검사</h3>
<p>Book 타입으로 정의된 변수에 ProgrammingBook 타입으로 보이는 초기값을 설정하면 오류가 발생합니다.</p>
<pre><code class="language-ts">type Book = {
  name: string;
  price: number;
};

type ProgrammingBook = {
  name: string;
  price: number;
  skill: string;
};

let book: Book = { // ❌
  name: &quot;한 입 크기로 잘라먹는 리액트&quot;,
  price: 33000,
  skill: &quot;reactjs&quot;,
};</code></pre>
<p>Book 타입은 ProgrammingBook 타입의 슈퍼타입입니다. 이것은 업캐스팅에 해당되는데 오류가 발생합니다.</p>
<p>그 이유는 ‘초과 프로퍼티 검사’가 발동했기 때문입니다. 초과 프로퍼티 검사란 변수를 객체 리터럴로 초기화 할 때 발동하는 타입스크립트의 특수한 기능입니다. 이 기능은 타입에 정의된 프로퍼티 외의 다른 초과된 프로퍼티를 갖는 객체를 변수에 할당할 수 없도록 막습니다.</p>
<p>초과 프로퍼티 검사는 단순히 변수를 &#39;초기화&#39;할 때 &#39;객체 리터럴을 사용하지만 않으면&#39; 발생하지 않습니다.</p>
<pre><code class="language-ts">let programmingBook: ProgrammingBook = {
  name: &quot;한 입 크기로 잘라먹는 리액트&quot;,
  price: 33000,
  skill: &quot;reactjs&quot;,
};

let book3: Book = programmingBook;</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.typescriptlang.org/ko/docs/handbook/type-compatibility.html">TypeScript: Handbook - Type Compatibility</a></li>
<li><a href="https://ts.winterlood.com/">소개 - 한 입 크기로 잘라먹는 타입스크립트</a></li>
<li><a href="https://toss.tech/article/typescript-type-compatibility">TypeScript 타입 시스템 뜯어보기: 타입 호환성</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[타입스크립트 기본 - (2)]]></title>
            <link>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B3%B8-2</link>
            <guid>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B3%B8-2</guid>
            <pubDate>Fri, 08 Sep 2023 04:46:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>&quot;한 입 크기로 잘라먹는 타입스크립트 - 인프런&quot; 강의를 요약하고 덧붙인 글입니다.</p>
</blockquote>
<h2 id="타입-별칭type-alias">타입 별칭(Type Alias)</h2>
<p>객체 타입을 사용할 때 직접 해당 타입을 명시하였습니다. </p>
<pre><code class="language-ts">let user: {
  id: number;
  name: string;
} = {
  id: 1,
  name: &quot;cs&quot;,
}</code></pre>
<p>그런데 같은 타입의 변수를 여러개 사용해야 한다면 아래와 같이 타입을 중복해서 정의해서 사용하게 됩니다.</p>
<pre><code class="language-ts">let user1: {
  id: number;
  name: string;
} = {
  id: 1,
  name: &quot;cs&quot;,
}

let user2: {
  id: number;
  name: string;
} = {
  id: 2,
  name: &quot;jh&quot;,
}</code></pre>
<p>타입 정의는 중복되는 코드입니다. 이는 유지보수를 어렵게 하고 가독성을 떨어트립니다. 그리고 때로는 같은 타입을 재사용하거나 또 다른 이름으로 부르고 싶은 경우도 존재합니다. 타입 별칭을 사용하면 변수를 선언하듯 타입을 별도로 정의할 수 있습니다. 
<code>type 타입_이름 = 타입</code> 형태로 타입을 정의합니다.</p>
<pre><code class="language-ts">type User = {
  id: number;
  name: string;
}

let user: User = {
  id: 1,
  name: &quot;cs&quot;,
}</code></pre>
<p>단, 동일한 스코프에 동일한 이름의 타입 별칭을 선언하는 것은 불가능합니다. 
<em>타입 별칭은 타입 관련 문법이기 때문에 컴파일 결과 사라집니다.</em></p>
<h2 id="인덱스-시그니처index-signature">인덱스 시그니처(Index Signature)</h2>
<p>인덱스 시그니쳐는 객체 타입을 유연하게 정의할 수 있도록 돕는 특수한 문법입니다. 예를 들어 다양한 국가들의 영어 코드를 저장하는 객체가 있다고 가정하겠습니다.</p>
<pre><code class="language-ts">type CountryCodes = {
  Korea: string;
  UnitedState: string;
  UnitedKingdom: string;
};

let countryCodes: CountryCodes = {
  Korea: &quot;ko&quot;,
  UnitedState: &quot;us&quot;,
  UnitedKingdom: &quot;uk&quot;,
};</code></pre>
<p>countryCodes에 100개의 프로퍼티가 추가되어야 한다면 타입 정의에도 각 프로퍼티를 모두 정의해주어야 합니다. 아직 추가되어야 할 프로퍼티 이름과 값을 알지 못한다면 타입을 정의하지 못할 것입니다. 
하지만 객체의 키와 값의 타입 규칙을 알고 있다면 인덱스 시그니쳐를 이용하여 간단하게 타입을 정의할 수 있습니다.</p>
<pre><code class="language-ts">type CountryCodes = {
  [key: string]: string;
};

let countryCodes: CountryCodes = {
  Korea: &quot;ko&quot;,
  UnitedState: &quot;us&quot;,
  UnitedKingdom: &quot;uk&quot;,
  // (... 약 100개의 국가)
  Brazil : &#39;bz&#39;
};</code></pre>
<p><code>[key : string] : string</code>, 키가 string 타입이고 값이 string 타입인 모든 프로퍼티를 포함한다는 의미입니다.</p>
<p>주의할 점은 인덱스 시그니쳐는 정의된 규칙을 위반하지만 않으면 모든 객체를 허용합니다. 빈 객체는 이를 위반하지는 않으므로 오류가 발생하지 않습니다.</p>
<pre><code class="language-ts">type CountryNumberCodes = {
  [key: string]: number; 
}

let countryNumberCodes: CountryNumberCodes = {}; // ⭕</code></pre>
<p>반드시 포함해야 하는 프로퍼티가 있다면 직접 명시할 수 있습니다. 단, 인덱스 시그니쳐의 value 타입과 직접 추가한 프로퍼티의 value 타입이 호환되거나 일치해야 합니다.</p>
<pre><code class="language-ts">type CountryNumberCodes = {
  [key: string]: number;
  Korea: number; // Korea: string; ❌ Error
}</code></pre>
<h2 id="열거형enum-타입">열거형(Enum) 타입</h2>
<p>여러가지 값들에 각각 이름을 부여해 열거해두고 사용하는 타입입니다. 열거형 타입은 자바스크립트에는 존재하지 않고 오직 타입스크립트에서만 사용할 수 있는 특별한 타입입니다.</p>
<pre><code class="language-ts">enum Role {
  ADMIN = 0,
  USER = 1,
  GUEST = 2,
}

const user1 = {
  name: &quot;admin&quot;,
  role: Role.ADMIN,
}</code></pre>
<p>enum 멤버에 숫자 값을 직접 할당하지 않아도 0부터 1씩 늘어나는 값으로 자동 할당됩니다.</p>
<pre><code class="language-ts">enum Role {
  ADMIN, // 0 
  USER,  // 1 
  GUEST, // 2 
}</code></pre>
<p>자동 할당되는 값은 기본적으로 0부터 시작합니다. 만약 이 값을 변경하고 싶다면 다음과 같이 시작하는 위치에 값을 직접 할당해주면 됩니다. 그럼 자동으로 그 아래의 멤버들은 1씩 증가된 값으로 할당됩니다.</p>
<pre><code class="language-ts">enum Role {
  ADMIN = 10, // 10 
  USER,  // 11 
  GUEST, // 12
}</code></pre>
<p>enum의 멤버에는 숫자 말고도 문자열 값도 할당할 수 있습니다. 숫자형 열거형에서 숫자만으로는 그 값이 어떤 의미인지 추측하기 힘들 때 프로퍼티의 값으로 사용할 수 있습니다.</p>
<pre><code class="language-ts">enum Role {
  ADMIN,
  USER,
  GUEST,
}

enum Language {
  korean = &quot;ko&quot;,
  english = &quot;en&quot;,
}

const user1 = {
  name: &quot;admin&quot;,
  role: Role.ADMIN, // 0
  language: Language.korean,// &quot;ko&quot;
};</code></pre>
<h3 id="enum의-컴파일-결과">enum의 컴파일 결과</h3>
<p>타입스크립트 타입 관련 코드는 컴파일할 때 사라집니다. 그런데 enum은 컴파일될 때 다른 타입들처럼 사라지지 않고 자바스크립트 객체로 변환됩니다.</p>
<pre><code class="language-js">var Role;
(function (Role) {
    Role[Role[&quot;ADMIN&quot;] = 0] = &quot;ADMIN&quot;;
    Role[Role[&quot;USER&quot;] = 1] = &quot;USER&quot;;
    Role[Role[&quot;GUEST&quot;] = 2] = &quot;GUEST&quot;;
})(Role || (Role = {}));
var Language;
(function (Language) {
    Language[&quot;korean&quot;] = &quot;ko&quot;;
    Language[&quot;english&quot;] = &quot;en&quot;;
})(Language || (Language = {}));
var user1 = {
    name: &#39;admin&#39;,
    role: Role.ADMIN,
    language: Language.korean,
};</code></pre>
<h3 id="-enum을-사용하지-말아야-하는-이유">(+) enum을 사용하지 말아야 하는 이유</h3>
<ul>
<li><p>enum은 Tree-shaking 되지 않아 번들 파일의 크기를 증가시킬 수 있습니다</p>
<blockquote>
<p><a href="https://engineering.linecorp.com/ko/blog/typescript-enum-tree-shaking">TypeScript enum을 사용하지 않는 게 좋은 이유를 Tree-shaking 관점에서 소개합니다.</a></p>
</blockquote>
</li>
<li><p>enum은 선언되지 않은 key로 접근이 가능합니다.</p>
<pre><code class="language-ts">enum Role {
  ADMIN,
  USER,
  GUEST,
}

console.log(Role[3]) // undefined</code></pre>
<h2 id="any-타입">Any 타입</h2>
<p>any 타입은 특정 변수의 타입을 모를 때, 특정 값으로 인하여 타입 검사 오류가 발생하는 것을 원하지 않을 때 사용할 수 있습니다.</p>
<pre><code class="language-ts">let anyVar: any = 10;
anyVar = &quot;hello&quot;;
</code></pre>
</li>
</ul>
<p>anyVar = true;
anyVar = {};</p>
<p>anyVar.toUpperCase();
anyVar.toFixed();
anyVar.a;</p>
<pre><code>any 타입은 어떠한 타입 검사도 받지 않기 때문에 아무 타입의 값이나 담아 사용할 수 있고 또 다양한 타입의 메서드도 마음대로 호출해서 사용해도 문제가 되지 않습니다.

그러나, 위의 코드를 실행해보면 런타임에 오류가 발생합니다. 타입스크립트를 쓰는 이유는 실행 전에 타입 오류를 검사해서 안정성이 높이는 것인데 any 타입은 타입 검사를 받지 않으므로 타입스크립트를 쓰는 의미가 없습니다.

그렇다면 값의 타입을 모르는 경우는 어떻게 해야할까요? `unknown` 타입을 사용합니다.


## Unknown 타입
unknown 타입은 어떤 타입의 값이든 다 저장할 수 있습니다. any 타입과 비슷하지만 unknown 타입은 어떤 타입의 변수에도 저장할 수 없습니다.
```ts
let num: number = 10;

let unknownVar: unknown;
unknownVar = &quot;&quot;;
unknownVar = 1;
unknownVar = () =&gt; {};

num = unknownVar; // ❌ Error</code></pre><p>또 unknown 타입의 값은 어떤 연산에도 참여할 수 없으며, 어떤 메서드도 사용할 수 없습니다. 어떤 변수가 어떤 값을 받게 될 지 모른다면 any 타입보다 unknown 타입을 사용하는게 더 안전합니다.</p>
<pre><code class="language-ts">let unknownVar: unknown;
unknownVar * 2 // ❌ Error</code></pre>
<p>연산을 수행하고 싶다면 조건문을 이용해 이 값이 특정 타입임을 보장해주면 됩니다.</p>
<pre><code class="language-ts">if (typeof unknownVar === &quot;number&quot;) {
  unknownVar * 2;
}</code></pre>
<h2 id="void-타입">Void 타입</h2>
<p>void 타입은 아무런 값도 없음을 의미하는 타입입니다. 함수에 return문이 없거나 명시적으로 값을 반환하지 않을 때 추론되는 타입입니다.</p>
<pre><code class="language-ts">function func1(): void {
  console.log(&quot;hello&quot;);
}

function func2() {
  return;
}</code></pre>
<h3 id="함수의-void-반환-타입">함수의 void 반환 타입</h3>
<p>타입스크립트에서 void 타입을 사용하더라도 값을 반환할 수 있습니다. void를 반환 타입으로 사용했을 때입니다.</p>
<blockquote>
<p>void 반환 타입으로의 문맥적 타이핑은 함수를 아무것도 반환하지 않도록 강제하지 않습니다.이를 설명하는 또 다른 방법은, void 반환 타입을 가지는 문맥적 함수 타입(type vf = () =&gt; void)가 구현되었을 때, 아무값이나 반환될 수 있지만, 무시됩니다. - <a href="https://www.typescriptlang.org/ko/docs/handbook/2/functions.html#void-%EB%B0%98%ED%99%98-%ED%83%80%EC%9E%85">TypeScript: Documentation</a></p>
</blockquote>
<p>void 반환 타입은 함수가 다른 값을 반환할 수도 있다는 것입니다. 아래의 코드들은 모두 유효한 코드입니다.</p>
<pre><code class="language-ts">type voidFunc = () =&gt; void;

const f1: voidFunc = () =&gt; {
  return true;
};

const f2: voidFunc = () =&gt; true;

const f3: voidFunc = function () {
  return true;
};</code></pre>
<blockquote>
<p>자세한 내용은 ➡ <a href="https://pozafly.github.io/typescript/why-can-typescript-return-any-value-using-void/">왜 TypeScript는 void 타입을 사용해도 값을 return 할 수 있을까?</a></p>
</blockquote>
<h2 id="never-타입">Never 타입</h2>
<p>never 타입은 결코 관측될 수 없는 값을 의미합니다. 보통 다음과 같이 함수가 어떠한 값도 반환할 수 없는 상황(무한 루프, 프로그램 실행 종료, 오류 발생 등)에 해당 함수의 반환값 타입을 정의할 때 사용됩니다.</p>
<pre><code class="language-ts">function func3(): never {
  while (true) {}
}

function func4(): never {
  throw new Error();
}</code></pre>
<p>void와 혼동하기 쉬우나 분명한 차이가 있습니다. void 타입은 아무것도 반환하지 않습니다. never 타입은 결코 반환값이 있을 수 없는, 반환이 &#39;불가능&#39;함을 나타내는 타입입니다. </p>
<p>변수의 타입을 never로 정의하면 어떠한 타입의 값도 변수에 담을 수 없습니다.</p>
<pre><code class="language-ts">let anyVar: any;

let a: never;
a = 1; // ❌
a = null; // ❌
a = undefined; // ❌
a = anyVar; // ❌</code></pre>
<blockquote>
<p>추가로 읽을거리 <a href="https://ui.toast.com/posts/ko_20220323">타입스크립트의 Never 타입 완벽 가이드</a></p>
</blockquote>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.typescriptlang.org/ko/docs/handbook/intro.html">TypeScript: Handbook - The TypeScript Handbook</a></li>
<li><a href="https://ts.winterlood.com/">소개 - 한 입 크기로 잘라먹는 타입스크립트</a></li>
<li><a href="https://www.typescriptlang.org/ko/docs/handbook/2/functions.html">TypeScript: Documentation - More on Functions</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[타입스크립트 기본 - (1)]]></title>
            <link>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B3%B8</link>
            <guid>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B8%B0%EB%B3%B8</guid>
            <pubDate>Tue, 05 Sep 2023 11:38:14 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>&quot;한 입 크기로 잘라먹는 타입스크립트 - 인프런&quot; 강의를 요약하고 덧붙인 글입니다.</p>
</blockquote>
<h2 id="기본-타입basic-types">기본 타입(Basic Types)</h2>
<p>타입스크립트가 자체적으로 제공하는 타입을 뜻합니다. 자바스크립트에서 이미 사용하고 있는 타입들과 타입스크립트에서만 제공하는 독특한 타입들도 있습니다.<img src="https://velog.velcdn.com/images/code_newb/post/8868469b-957a-40bb-8eed-b21a789e794b/image.png" alt=""></p>
<h3 id="원시-타입">원시 타입</h3>
<p>원시 타입은 하나의 값만 저장하는 타입으로 불변 값(변경할 수 없는 값)을 정의합니다. 값을 교체할 수는 있지만, 직접 변형할 수는 없습니다. </p>
<pre><code class="language-js">var bar = &quot;baz&quot;;
console.log(bar); // baz
bar.toUpperCase();
console.log(bar); // baz</code></pre>
<h4 id="number">number</h4>
<p>숫자를 의미하는 모든 값을 포함하는 타입입니다. 정수 뿐만 아니라 소수, 음수 그리고 세 가지 특별한 값도 표현할 수 있습니다.</p>
<ul>
<li>Infinity: 양의 무한대</li>
<li>-Infinity: 음의 무한대</li>
<li>NaN: 산술 연산 불가 (not-a-number)</li>
</ul>
<pre><code class="language-ts">let num1: number = 123;
let num2: number = -123;
let num3: number = 0.123;
let num4: number = -0.123;
let num5: number = Infinity;
let num6: number = -Infinity;
let num7: number = NaN;</code></pre>
<h4 id="string">string</h4>
<p>텍스트 데이터를 나타낼 때 사용합니다. 문자열은 작은따옴표(&#39;&#39;), 큰따옴표(&quot;&quot;) 또는 백틱(``)으로 텍스트를 감싸서 표기합니다. 템플릿 리터럴로 만든 문자열도 포함합니다. </p>
<pre><code class="language-ts">let str1: string = &quot;hello&quot;;
let str2: string = &#39;hello&#39;;
let str3: string = `hello`;
let str4: string = `hello ${str1}`; // 템플릿 리터럴</code></pre>
<blockquote>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals">템플릿 리터럴이란?</a></p>
</blockquote>
<h4 id="boolean">boolean</h4>
<p>논리 요소를 나타내며 참과 거짓만을 저장하는 타입입니다. <code>true</code>와 <code>false</code> 두 가지 값만 가질 수 있습니다.  </p>
<pre><code class="language-ts">let bool1 : boolean = true;
let bool2 : boolean = false;</code></pre>
<h4 id="null">null</h4>
<p>오직 null 값만 포함하는 타입입니다. <code>null</code>은 어떤 값이 의도적으로 비어있음을 표현하며 불리언 연산에서는 거짓으로 취급합니다.</p>
<pre><code class="language-ts">let null1: null = null;</code></pre>
<h5 id="-엄격한-null-검사-옵션---strictnullchecks">(+) 엄격한 Null 검사 옵션 - strictNullChecks</h5>
<p>아직 값이 정해지지 않은 상태에서는 변수에 null을 할당하고 싶은 경우가 있습니다. 그러나 다른 타입의 변수에 null을 할당하면 오류가 발생합니다. </p>
<pre><code class="language-ts">let numA: number = null;  // ❌</code></pre>
<p>null 값을 변수의 임시값으로 활용하고 싶을 때 tsconfig.json의 strcitNullChecks 옵션을 false로 설정하면 됩니다. strictNullChecks 옵션은 타입스크립트에서 null 값을 null 타입 이외의 타입의 변수에 할당하는 것을 금지할지 허락할지 여부를 결정하는 옵션입니다.</p>
<pre><code class="language-ts">{
  &quot;compilerOptions&quot;: {
    ...
    &quot;strictNullChecks&quot;: false,
        ...
  },
  &quot;include&quot;: [&quot;src&quot;]
}</code></pre>
<h4 id="undefined">undefined</h4>
<p>null 타입과 마찬가지로 undefined만 포함하는 타입입니다. 값을 할당하지 않은 변수는 undefined 값을 가집니다.</p>
<pre><code class="language-ts">let unde1: undefined = undefined;</code></pre>
<h4 id="symbol">symbol</h4>
<p>고유한 참조값을 생성하는데 사용할 수 있는 타입입니다. symbol은 외부에 노출되지 않고 다른 값과 중복되지 않는 유일한 값입니다. 다른 원시 값은 리터럴을 통해 생성하지만 symbol은 Symbol 함수를 호출해 생성합니다.</p>
<pre><code class="language-ts">let sym1: symbol = Symbol();</code></pre>
<h4 id="리터럴">리터럴</h4>
<p>하나의 값만 포함하도록 값 자체로 만들어진 타입입니다. 리터럴을 사용하면 다양한 종류의 값을 생성할 수 있습니다. 변수의 타입을 값 자체로 정의하면 정의한 값 외에는 다른 값을 사용할 수 없습니다.</p>
<pre><code class="language-ts">let numA: 10 = 10;
let strA: &quot;hello&quot; = &quot;hello&quot;;
let boolA: true = true;
let boolB: false = false;</code></pre>
<h2 id="배열과-튜플">배열과 튜플</h2>
<h3 id="배열">배열</h3>
<p>배열을 저장하는 변수의 이름 뒤에 타입 주석의 시작을 의미하는 콜론(:)을 작성한 다음 <code>배열요소타입[]</code> 형식으로 배열 타입을 정의합니다.</p>
<pre><code class="language-ts">let numArr: number[] = [1, 2, 3]
let strArr: string[] = [&quot;hello&quot;, &quot;world&quot;];</code></pre>
<p><code>Array&lt;배열요소타입&gt;</code> 형태로도 배열의 타입을 정의할 수 있습니다. 꺽쇠와 함께 타입을 작성하는 문법을 타입스크립트에서는 ‘제네릭’ 이라고 부릅니다.</p>
<pre><code class="language-ts">let boolArr: Array&lt;boolean&gt; = [true, false, true];</code></pre>
<p>배열의 타입을 정의하는 두 형식 모두 모양만 다를뿐 기능은 동일하기에 타이핑하기 쉬운 첫 번째 방식을 주로 사용합니다.</p>
<p>배열에 들어가는 요소들의 타입이 다양할 경우에는 소괄호와 바(|) 를 이용해 배열 요소가 둘 중 하나의 타입에 해당하도록 타입을 정의합니다.</p>
<pre><code class="language-ts">// 배열 요소의 타입이 string이거나 number
let multiArr: (number | string)[] = [1, &quot;hello&quot;]; </code></pre>
<p>바(|)를 이용해 여러 타입중 하나를 만족하는 타입을 정의하는 문법을 유니온(Union) 타입 이라고 부릅니다.</p>
<h3 id="튜플">튜플</h3>
<p>튜플은 자바스크립트에는 없는 타입스크립트의 특수한 타입으로 길이와 타입이 고정된 배열을 의미합니다. 타입스크립트의 배열은 배열에 들어가는 타입은 고정시킬 수 있지만 길이까지 고정할 수는 없습니다.</p>
<pre><code class="language-ts">let tup1: [number, number] = [1, 2];
let tup2: [number, string, boolean] = [1, &quot;hello&quot;, true];</code></pre>
<p>튜플은 별도로 존재하는 자료형이 아닌 자바스크립트 배열입니다. 타입스크립트 코드를 컴파일 해 보면 자바스크립트 배열로 변환됩니다. 그러므로 배열 메서드를 이용해 튜플을 다룰 수 있습니다.
그러므로 튜플을 배열 메서드를 이용해 요소를 추가하거나 삭제 등의 연산을 할 때에는 주의해야 합니다.</p>
<pre><code class="language-ts">let tup1: [number, number] = [1, 2];
tup1.push(1);
tup1.pop();</code></pre>
<h4 id="튜플의-사용-예">튜플의 사용 예</h4>
<p>회원 정보를 2차원 배열로 저장하는 상황을 가정해 보겠습니다. 회원의 이름과 아이디를 저장해두는 배열을 만들어 두었습니다.</p>
<pre><code class="language-ts">const users = [
  [&quot;Lee&quot;, 1],
  [&quot;Park&quot;, 2],
  [&quot;Kim&quot;, 3],
];</code></pre>
<p>그런데 동료가 요소의 순서가 헷갈려 반대로 저장하였습니다. 이로 인해 오류가 발생합니다.</p>
<pre><code class="language-ts">const users = [
  [&quot;Lee&quot;, 1],
  [&quot;Park&quot;, 2],
  [&quot;Kim&quot;, 3],
  [4, &quot;Choi&quot;] // 추가
];

function makeUpperCase(inputString) { return inputString.toUpperCase(); }
makeUpperCase(users[3][0]) // ❌ Error
]</code></pre>
<p>튜플을 사용하면 이러한 문제를 쉽게 해결할 수 있습니다. 배열을 사용할 때 인덱스에 따라 넣어야 할 값이 정해져 있고 순서가 중요할 때 튜플을 사용하여 실수를 방지할 수 있습니다.</p>
<pre><code class="language-ts">const users: [string, number] = [
  [&quot;Lee&quot;, 1],
  [&quot;Park&quot;, 2],
  [&quot;Kim&quot;, 3],
  [4, &quot;Choi&quot;] // ❌ Error
];</code></pre>
<h2 id="객체">객체</h2>
<p>원시 타입을 제외하고 가장 많이 마주치는 타입입니다. </p>
<blockquote>
<p>자바스크립트의 객체는 키(key)과 값(value)으로 구성된 프로퍼티(Property)들의 집합이다. </p>
</blockquote>
<p>타입스크립트에서는 2가지 방식으로 객체의 타입을 정의합니다.</p>
<h3 id="object로-정의">object로 정의</h3>
<pre><code class="language-ts">let user: object = {
  id: 1,
  name: &#39;cs&#39;,
};</code></pre>
<p>그러나 타입스크립트에서 객체의 특정 프로퍼티에 접근하려고 하면 오류가 발생합니다.</p>
<pre><code class="language-ts">let user: object = {
  id: 1,
  name: &#39;cs&#39;,
};

user.id; // ❌ Error</code></pre>
<p>그 이유는 타입스크립트의 object 타입은 값이 객체임을 표현하는 것 외에는 아무 정보도 제공하지 않는 타입이기 때문입니다. 객체의 프로퍼티에 대한 정보가 없기 때문에 프로퍼티에 접근하려 하면 오류가 발생합니다. 객체의 모양을 정확히 타입으로 만드려면 다른 방법을 사용해야 합니다.</p>
<h3 id="객체-리터럴-타입">객체 리터럴 타입</h3>
<p>객체 리터럴 타입은 다음과 같이 중괄호를 열고 객체가 갖는 프로퍼티를 직접 나열합니다. 객체 리터럴과 비슷한 문법으로 객체 타입을 정의한 타입을 객체 리터럴 타입이라고 부릅니다. </p>
<pre><code class="language-ts">let user: {
  id: number;
  name: string;
} = {
  id: 1,
  name: &quot;cs&quot;,
};

user.id;</code></pre>
<p>객체의 타입을 정의할 때에는 object 보다는 객체 리터럴 타입을 사용하는 것이 좋습니다. 타입스크립트에서는 객체의 타입을 정의할 때 프로퍼티를 기준으로 객체의 구조를 정의하듯 타입을 정의합니다. 이런 특징을 <strong>구조적 타입 시스템</strong>이라고 부릅니다.  </p>
<h4 id="-명목적-타입-시스템">(+) 명목적 타입 시스템</h4>
<p>명목적 타입 시스템은 구조적 타입 시스템과는 대조적으로 변수나 객체의 타입을 해당 타입의 이름 또는 명칭으로 식별합니다. 객체의 타입이 명시적으로 선언되어야 한다는 의미입니다. 클래스의 이름이 타입을 나타냅니다.</p>
<pre><code class="language-py">class Animal:
    def make_sound(self):
        pass

class Dog(Animal):
    def make_sound(self):
        print(&quot;멍멍&quot;)

def sound_maker(animal: Animal):
    animal.make_sound()

my_dog = Dog()
sound_maker(my_dog)  # &quot;멍멍&quot; 출력</code></pre>
<p><strong>구조적 타입 시스템의 예)</strong></p>
<pre><code class="language-ts">interface Animal {
    makeSound: () =&gt; void;
}

interface Dog extends Animal {
    bark: () =&gt; void;
}

function soundMaker(animal: Animal) {
    animal.makeSound();
}

const myDog: Dog = {
    makeSound: () =&gt; console.log(&quot;멍멍&quot;),
    bark: () =&gt; console.log(&quot;왈왈&quot;)
};

soundMaker(myDog); // &quot;멍멍&quot; 출력</code></pre>
<p>객체의 구조가 중요하며 객체가 특정 인터페이스 또는 구조를 따르면 해당 타입으로 간주됩니다. 타입의 이름이나 클래스의 이름은 중요하지 않습니다.</p>
<h3 id="선택적-프로퍼티optional-property">선택적 프로퍼티(Optional Property)</h3>
<p>객체를 다루다보면 특정 프로퍼티를 사용하지 않는 경우도 있습니다. 특정 프로퍼티를 상황에 따라 생략하도록 만들고 싶다면 프로퍼티의 이름 뒤에 <code>?</code> 붙여 선택적 프로퍼티로 만들어줍니다. </p>
<pre><code class="language-ts">let user: {
  id?: number;
  name: string;
} = {
  id: 1,
  name: &quot;cs&quot;,
};

user = {
  name: &quot;jh&quot;,
};</code></pre>
<h3 id="읽기전용-프로퍼티readonly-property">읽기전용 프로퍼티(Readonly Property)</h3>
<p>특정 프로퍼티를 읽기 전용으로 만들고 싶다면 다음과 같이 프로퍼티의 이름 앞에 <code>readonly</code> 키워드를 붙입니다. 읽기전용 프로퍼티를 사용하면 의도치 않은 프로퍼티의 수정을 방지할 수 있습니다.</p>
<pre><code class="language-ts">let user: {
  id?: number;
  readonly name: string;
} = {
  id: 1,
  name: &quot;cs&quot;,
};

user.name = &quot;dskfd&quot;; // Error</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.typescriptlang.org/ko/docs/handbook/intro.html">TypeScript: Handbook - The TypeScript Handbook</a></li>
<li><a href="https://ts.winterlood.com/">소개 - 한 입 크기로 잘라먹는 타입스크립트</a></li>
<li><a href="https://www.typescriptlang.org/ko/docs/handbook/2/everyday-types.html#%EA%B0%9D%EC%B2%B4-%ED%83%80%EC%9E%85">TypeScript: Documentation - Everyday Types</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[타입스크립트 개론]]></title>
            <link>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%A1%A0-hq175xyi</link>
            <guid>https://velog.io/@code_newb/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%A1%A0-hq175xyi</guid>
            <pubDate>Fri, 04 Aug 2023 05:50:19 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8/">&quot;한 입 크기로 잘라먹는 타입스크립트 - 인프런&quot;</a> 강의를 요약하고 덧붙인 글입니다.</p>
</blockquote>
<h1 id="타입스크립트-등장-배경">타입스크립트 등장 배경</h1>
<p>타입스크립트는 자바스크립트의 상위 집합으로서, 기본적으로 자바스크립트의 모든 기능을 포함하고 있습니다. 이 말은 곧 자바스크립트를 배우지 않고서는 타입스크립트를 배울 수 없음을 뜻합니다. 타입스크립트의 기반이 되는 자바스크립트를 먼저 알아보며 타입스크립트가 등장한 이유를 살펴보겠습니다.</p>
<h2 id="자바스크립트의-탄생">자바스크립트의 탄생</h2>
<p>초기 웹 페이지는 정적인 HTML로만 구성되었고, 사용자와의 상호작용이 제한적이었습니다. 기존의 정적인 웹 페이지를 &quot;어떻게 동적인 웹 페이지를 만들 수 있을까?&quot;를 고민하였고 &#39;자바스크립트&#39;가 탄생합니다. </p>
<p>자바스크립트는 웹 브라우저에서 동작하는 간단한 사용자 상호작용을 위한 언어로 개발되었습니다. 웹 페이지에 삽입되는 스크립트 언어로 브라우저에서 바로 실행되었고 자바스크립트를 통해 웹 페이지에 동적인 기능과 상호작용을 추가할 수 있었습니다.</p>
<blockquote>
<p>스크립트 언어(scripting language)란 응용 소프트웨어를 제어하는 컴퓨터 프로그래밍 언어를 가리킨다. 스크립트 프로그래밍 언어라고도 한다. <a href="https://ko.wikipedia.org/wiki/%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8_%EC%96%B8%EC%96%B4">스크립트 언어 - 위키백과</a></p>
</blockquote>
<h2 id="스크립트-언어-자바스크립트">스크립트 언어, 자바스크립트</h2>
<p>자바스크립트는 1995년에 불과 10일 만에 만들어진 언어입니다. 웹 브라우저에서만 동작하고 경고창 띄우기와 같은 아주 간단한 사용자 상호작용을 처리하였기에 엄격한 문법을 갖출 필요가 없었습니다. 대신 아주 유연하게 설계되었습니다. 버그로부터의 안정성이나 견고함은 일부 포기하는 대신 프로그래머가 쉽고 빠르고 간결하게 코드를 작성하는데에 중점을 두고 만들어졌습니다. 또한 초기 웹 브라우저들은 인터넷 속도가 느리고, 컴퓨터의 성능이 현재와 비교해 상당히 낮았으므로 가벼운 스크립트 언어를 사용한 것이죠. </p>
<blockquote>
<p>더 깊은 이해를 위해서는 - <a href="https://velog.io/@teo/typescript">Typescript는 어떻게 공부해야 하나요?</a></p>
</blockquote>
<p>그러나 웹이 발전하고 자바스크립트 실행 환경 &#39;Node.js&#39;가 등장하면서 웹 브라우저뿐만 아니라 어디서든 자바스크립트를 실행할 수 있게 되었습니다. 오늘날에는 웹 개발부터 모바일 애플리케이션을 만들거나 데스크탑 애플리케이션을 만드는 등 무엇이든 자바스크립트로 다양한 프로그램을 만들 수 있습니다. </p>
<h2 id="자바스크립트-이상하다">자바스크립트 이상하다</h2>
<p>여기서 문제가 발생합니다. 프로그램의 규모가 커지자 자바스크립트의 유연함이 버그 발생 가능성을 높이고 프로그램의 안정성을 떨어뜨리게 된 것이죠. 예를 들어, </p>
<ul>
<li>자바스크립트의 동일 비교 연산자는(==) 인수를 강제로 변환하여, 예기치 않은 동작을 유발합니다.<pre><code class="language-js">if (&quot;&quot; == 0) {
// true, Number(&quot;&quot;) == 0 =&gt; 0 == 0 =&gt; true
}
if (1 &lt; x &lt; 3) {
// true, 어떤 x 값이던 참!
}
true == &quot;true&quot; // false, Number(true) == Number(&quot;true&quot;) =&gt; 1 == NaN =&gt; false
(번외) &quot;b&quot; + &quot;a&quot; + +&quot;a&quot; + &quot;a&quot; // &quot;baNaNa&quot;, &quot;b&quot; + &quot;a&quot; + Number(&quot;a&quot;) + &quot;b&quot; =&gt; &quot;b&quot; + &quot;a&quot; + NaN + &quot;a&quot; </code></pre>
연산 과정에서 강제 형변환으로 결과를 예측하기 어렵습니다. 
<a href="https://jsisweird.com/">(+) JS Is Weird</a>: 자바스크립트의 이상한 문법 퀴즈 풀어보기</li>
<li>자바스크립트는 존재하지 않는 프로퍼티의 접근을 허용합니다.<pre><code class="language-js">const obj = { width: 10, height: 15 };
const area = obj.width * obj.heigth; // NaN, 10 * undefined</code></pre>
문법 오류가 있더라도 자바스크립트는 오류를 출력하지 않고 실행됩니다. 즉, 프로그램을 실행해보지 않는 이상 어떤 문법 에러를 잡아낼 수 없습니다.</li>
</ul>
<p>이렇게 예측하기 힘든 자바스크립트의 문제는 규모가 큰 프로그램에서 더욱 부각됩니다. 디버깅이 어렵고, 예기치 않은 동작이 여기저기서 발생할 수 있습니다. </p>
<p>이를 극복하기 위해 자바스크립트의 기존 문법은 유지하되 안정성을 확보한 언어가 필요해졌습니다. 이렇게 등장한 언어가 &#39;타입스크립트&#39;입니다.</p>
<h2 id="자바스크립트의-한계점">자바스크립트의 한계점</h2>
<p>위의 문제와 함께 자바스크립트가 어떤 한계가 왜 있었는지 더 구체적으로 들여다보겠습니다. 자바스크립트를 포함해서 모든 프로그래밍 언어에는 타입 시스템이라는게 존재합니다.</p>
<blockquote>
<p><strong>타입 시스템이란?</strong> 
언어에서 사용할 수 있는 아주 <u>여러가지 값들을 어떤 기준으로 묶어서 타입으로 정할지</u> 결정하고 또 <u>코드의 타입을 언제 검사할지</u> 그리고 <u>어떻게 검사할지</u> 등의 우리가 프로그래밍 언어를 사용할때 타입과 관련해서 지켜야 하는 규칙들을 모아둔 체계.</p>
</blockquote>
<p>타입 시스템은 크게 두가지로 나눌 수 있습니다.</p>
<ul>
<li>코드를 실행하기 전에는 타입을 결정하지 않고 코드를 실행하고 나서 유동적으로 변수의 타입을 결정하는 &#39;동적 타입 시스템&#39;</li>
<li>코드 실행전에 모든 변수의 타입을 고정적으로 결정하는 &#39;정적 타입 시스템&#39;</li>
</ul>
<p><img src="https://velog.velcdn.com/images/code_newb/post/a60948de-c0ab-4da1-8980-8ea59ec58836/image.png" alt=""></p>
<h3 id="동적-타입-시스템dynamic-type-system">동적 타입 시스템(Dynamic Type System)</h3>
<p>변수의 타입을 코드가 실행되는 도중에(런타임에) 결정하기 때문에 개발자가 변수의 타입을 명시적으로 정의하지 않아도 됩니다. </p>
<pre><code class="language-js">let a = &#39;hello&#39;;</code></pre>
<p>그리고 변수의 타입이 어떤 하나의 타입으로 딱 고정되지 않고 현재 변수에 담긴 값에 따라서 변수의 타입이 동적으로 계속해서 달라집니다.</p>
<pre><code class="language-js">let a = &#39;hello&#39;;
a = 2147483647</code></pre>
<p>이처럼 유연하게 타입을 결정하고 간결한 코드 작성이 동적 타입 시스템의 장점입니다. 그러나, 큰 단점이 있습니다.</p>
<pre><code class="language-js">let a = &#39;hello&#39;;
a = 2147483647;
a.toUpperCase(); // ❌ Error 발생</code></pre>
<p>위의 코드를 실행하면 실행은 되지만 오류가 발생하며 비정상적으로 종료됩니다. toUpperCase은 문자열을 대문자로 변환해 반환하는 문자열에만 사용할 수 있는 메서드입니다. 변수 a 값의 타입은 숫자(number)이므로 숫자 타입인 변수에 문자열에만 사용하는 메서드를 사용하니 당연히 오류가 발생합니다. </p>
<p>문제는 이 코드가 실행이 되기는 된다는 것입니다. 오류가 발생할 코드라면 실행 이전에 검사하여 실행되지 않도록 막는 것이 좋습니다. 복잡한 프로그램에서는 언제 터질지 모르는 시한폭탄과 같은 코드이기 때문입니다.</p>
<p><em>동적 타입 시스템은 프로그램이 런타임에 오류가 발생한다는 것이 치명적인 문제.</em></p>
<h3 id="정적-타입-시스템static-type-system">정적 타입 시스템(Static Type System)</h3>
<p>반면에 정적 타입 시스템은 코드를 실행하기 전에 모든 변수의 타입을 결정합니다. 변수에 할당되는 값의 타입을 미리 명시하여 타입 오류를 사전에 방지할 수 있습니다.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;

int main() {
  int a = 123;
  char b[] = &quot;hello&quot;;

  int c = a * b; // ❌ Error 발생

  return 0;
}</code></pre>
<p>C 코드를 예로 들면 변수 a에는 정수 타입으로 값은 123을, 변수 b에는 문자열 배열로 값은 hello를 저장했습니다. <code>a * b</code> 연산은 정수 a와 문자열 b을 곱하는 불가능한 연산이므로 코드 실행 전에 타입 오류를 보여줍니다. 프로그래머가 실수를 하더라도 에디터 상에서 오류를 알려주기 때문에 바로잡을 기회가 주어집니다.</p>
<p>그러나, 정적 타입 시스템에도 단점은 있습니다. 모든 변수에 타입을 지정해주어야 하므로 개발 시간이 늘어날 수 있고 많은 타입 선언이 필요한 프로젝트의 경우 유지보수하는 것이 어려울 수 있습니다.</p>
<h3 id="정리-동적-타입-시스템과-정적-타입-시스템의-장단점">정리) 동적 타입 시스템과 정적 타입 시스템의 장단점</h3>
<table>
<thead>
<tr>
<th></th>
<th>동적 타입 시스템</th>
<th>정적 타입 시스템</th>
</tr>
</thead>
<tbody><tr>
<td>장점</td>
<td>개발 속도와 유연성</td>
<td>타입 안정성</td>
</tr>
<tr>
<td></td>
<td>짧은 코드 길이</td>
<td>코드 가독성</td>
</tr>
<tr>
<td></td>
<td>자유로운 타입 변환이 가능</td>
<td>자동 완성과 코드 어시스트</td>
</tr>
<tr>
<td>단점</td>
<td>런타임 타입 오류</td>
<td>타입 선언의 부담</td>
</tr>
<tr>
<td></td>
<td>타입 오류 발견의 어려움</td>
<td>개발 시간 증가</td>
</tr>
<tr>
<td></td>
<td>디버깅 &amp; 유지보수의 어려움</td>
<td>유연성 감소</td>
</tr>
</tbody></table>
<h2 id="타입스크립트의-독특한-타입-시스템">타입스크립트의 독특한 타입 시스템</h2>
<p>그래서 타입스크립트는 동적 타입 시스템과 정적 타입 시스템을 혼합한 것 같은 독특한 타입시스템을 사용합니다. </p>
<pre><code class="language-ts">let a: number = 2147483647;</code></pre>
<p>정적 타입 시스템과 같이 변수의 타입을 실행 전에 결정하고 타입 오류를 실행 전에 검사하여 알려줍니다. 타입스크립트는 정적 타입 시스템의 타입 안정성을 확보하면서도 동적 타입 시스템처럼 모든 변수의 타입을 직접 명시하지 않아도 됩니다. </p>
<p>그 이유는 타입스크립트에서는 변수의 타입을 직접 정의하지 않아도 변수에 담기는 초기값을 기준으로 자동으로 타입을 알아서 추론합니다. </p>
<pre><code class="language-ts">let a = 2147483647;
a.toUpperCase(); // ❌ Property &#39;toUpperCase&#39; does not exist on type &#39;number&#39;</code></pre>
<p>타입스크립트의 이런 독특한 타입 시스템은 동적 타입 시스템의 타입 안전하지 않은 문제를 해결하면서도 정적 타입 시스템의 귀찮음도 동시에 해결하는 멋진 타입 시스템입니다.</p>
<p>이런 타입시스템을 &quot;점진적으로 타입을 결정한다&quot;라고 해서 <strong>점진적 타입 시스템(Gradual Type System)</strong>이라고 부릅니다. 타입이 정의된 변수들에 대해서는 타입을 미리 결정하고 타입이 정의되지 않은 변수들은 타입을 자동으로 추론하는 타입 시스템.</p>
<h1 id="정리하자면-타입스크립트는">정리하자면 타입스크립트는</h1>
<p>자바스크립트를 더 안전하게 사용할 수 있도록 &quot;타입 관련 기능들을 추가한 언어&quot;로 자바스크립트의 확장판이라고 볼 수 있습니다.</p>
<p>타입스크립트는 점진적 타입 시스템을 채택해서 정적 타입 시스템처럼 프로그램 실행 전에 타입을 올바르게 썼는지 타입 검사를 해 타입 안정성을 확보하면서도 동적 타입 시스템처럼 모든 변수에 일일히 타입을 지정해주지 않아도 되는 유연함까지 확보한 독특한 타입 시스템을 갖추고 있는 언어!</p>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://www.typescriptlang.org/ko/docs/handbook/intro.html">TypeScript: Handbook - The TypeScript Handbook</a></li>
<li><a href="https://ts.winterlood.com/">소개 - 한 입 크기로 잘라먹는 타입스크립트</a></li>
<li><a href="https://kim1124.tistory.com/93">1. 타입 스크립트에 대해 알아보자.</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 다크모드 구현하기]]></title>
            <link>https://velog.io/@code_newb/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%8B%A4%ED%81%AC%EB%AA%A8%EB%93%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@code_newb/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EB%8B%A4%ED%81%AC%EB%AA%A8%EB%93%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 04 May 2023 09:19:31 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>지난 <a href="https://velog.io/@code_newb/darkmodelearning">다크모드에 대해 알아보자</a> 글 작성 이후 다크모드 구현한 내용을 정리해보았습니다.</p>
</blockquote>
<h2 id="다크모드-구현하기">다크모드 구현하기</h2>
<h3 id="익숙한-방법이었던-styled-components">익숙한 방법이었던 styled-components</h3>
<p>이전 프로젝트에는 <code>styled-components</code>를 사용해 제공되는 ThemeProvider와 theme을 정의해서 구현했었다. (feat. recoil)</p>
<pre><code class="language-tsx">// Root.tsx
const Root = () =&gt; {
  const isDark = useRecoilValue(isDarkAtom);
  return (
    &lt;&gt;
      &lt;ThemeProvider theme={isDark ? darkTheme : lightTheme}&gt;
        &lt;GlobalStyles /&gt;
        &lt;Header /&gt;
        &lt;Outlet /&gt;
      &lt;/ThemeProvider&gt;
    &lt;/&gt;
  );
};</code></pre>
<pre><code class="language-ts">// theme.ts
import { DefaultTheme } from &#39;styled-components&#39;;

export const lightTheme: DefaultTheme = {
  bgColor: &#39;white&#39;,
  textColor: &#39;#000&#39;,
  itemColor: &#39;#E3CAA5&#39;,
  accentColor: &#39;#AD8B73&#39;,
};

export const darkTheme: DefaultTheme = {
  bgColor: &#39;#0A2647&#39;,
  textColor: &#39;#fff&#39;,
  itemColor: &#39;#205295&#39;,
  accentColor: &#39;#2C74B3&#39;, // 379634
};</code></pre>
<pre><code class="language-tsx">// styles.ts
export const Title = styled.h1`
  font-size: 48px;
  color: ${(props) =&gt; props.theme.accentColor};
`;</code></pre>
<p>ThemeProvider의 props로 전달한 theme이 변경되면 정의한 theme에 따라 바뀌는 쉽고 유지보수가 편한 방법이었다. 모든 컴포넌트는 styled를 사용해 스타일을 정의할 때 이 theme 값을 사용하여 동적으로 스타일링 할 수 있었다.</p>
<p>하지만 이번에는 순수 CSS만으로만 구현하고자 하였고, styled-components를 사용했을 때보다 성능상의 이점을 얻고자 하였다.</p>
<blockquote>
<p>CSS-in-JS 라이브러리는 브라우저에서 페이지가 로드될 때 스타일을 구문 분석해 적용한다.(런타임)</p>
</blockquote>
<h3 id="그래서-postcss">그래서 PostCSS</h3>
<p>다크모드가 설정이 되면 html 태그에 다크모드 class 지정하는 방식으로 다크모드를 구현한다. css selector를 이용해 다크모드이면 다른 색상을 사용하는 방식. JS를 사용해 html 요소에 &#39;dark&#39; 클래스를 추가/제거하여 다크모드와 라이트모드를 설정한다.</p>
<h4 id="스타일은-어떻게-적용">스타일은 어떻게 적용?</h4>
<p><a href="https://developer.mozilla.org/ko/docs/Web/CSS/Using_CSS_custom_properties">사용자 지정 CSS 속성</a>을 사용한다.  <code>:root</code> 의사 클래스는 문서 트리의 루트 요소를 선택한다. 이를 전역 CSS 변수를 선언하는데 활용한다.</p>
<blockquote>
<p>사용자 지정 속성은 두 개의 붙임표로 시작하는 속성의 이름과 함께, 유효한 CSS 값이라면 아무거나 그 값으로 지정해 선언합니다. 다른 일반적인 속성과 마찬가지로 사용자 지정 속성도 아래와 같이 규칙 집합 내에 작성합니다.</p>
</blockquote>
<pre><code class="language-css">:root {
  --main-bg-color: brown;
}</code></pre>
<p>위에서 언급했듯, 사용자 지정 속성의 값을 사용할 때에는 일반적인 값의 자리에 var() 함수를 지정하고, 그 매개변수로는 사용자 지정 속성의 이름을 제공합니다.</p>
<pre><code class="language-css">element {
  background-color: var(--main-bg-color);
}</code></pre>
<p><a href="https://developer.mozilla.org/ko/docs/Web/CSS/Using_CSS_custom_properties">사용자 지정 CSS 속성 사용하기 (변수) - CSS: Cascading Style Sheets | MDN</a></p>
<p>(+) html에서 root는 항상 html을 가리키는데 html보다 :root 의사 클래스의 우선순위가 더 높다. </p>
<p>공통으로 사용할 속성을 미리 변수로 선언하고 다크모드가 적용되었을 때 속성을 기존의 변수에 덮어쓴다. </p>
<pre><code class="language-css">:root {
  --color-black: #000;
  --color-white: #fff;
  --color-accent: #03045e;
  --color-bg: #caf0f8;
  --color-bg-darker: #ade8f4;
  --color-bg-sidebar: #fff;
  --color-bg-nav-hover: #e8f8fb;
  --color-bg-actived: #023e8a;
  --color-border: #03045e;
  --color-text: #03045e;
  --color-text-actived: #fff;
  --color-text-hover: #0096c7;
  --color-badge: #fff;
}

html.dark {
  --color-accent: #495057;
  --color-bg: #212529;
  --color-bg-darker: #495057;
  --color-bg-sidebar: #343a40;
  --color-bg-nav-hover: #222;
  --color-bg-actived: #495057;
  --color-border: #f8f9fa;
  --color-text: #dee2e6;
  --color-text-actived: #fff;
  --color-text-hover: #adb5bd;
  --color-badge: #495057;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/code_newb/post/685d7d34-8ea8-443b-9b53-6adf03ddae8c/image.png" alt="">➡ 다크모드가 적용되었을 때 우선순위가 높은 html.dark 변수가 적용된 모습.</p>
<h3 id="다크모드-context">다크모드 Context</h3>
<p>다크모드는 어플리케이션 전역에서 공통으로 사용되는 값이므로 Context API를 사용한다. </p>
<pre><code class="language-tsx">import React, { createContext, useContext, useEffect, useState } from &#39;react&#39;;
import { IChildren } from &#39;../typing/db&#39;;

interface ContextProps {
  darkMode: boolean;
  toggleDarkMode: () =&gt; void;
}

// 다크모드 Context 생성
export const DarkModeContext = createContext&lt;ContextProps&gt;({
  darkMode: false,
  toggleDarkMode: () =&gt; {},
});

// Context 내부 요소들에 value 전달할 Provider 생성
export const DarkModeProvider = ({ children }: IChildren) =&gt; {
  const [darkMode, setDarkMode] = useState(false);
  const toggleDarkMode = () =&gt; {
    setDarkMode(!darkMode);
    updateDarkMode(!darkMode);
  };

  // 어플리케이션이 실행될 때 localStorage에 다크모드인지 아닌지 
  // 혹은 브라우저가 다크모드인지 아닌지 확인한 다음 다크모드 초기값을 세팅
  useEffect(() =&gt; {
    const isDark =
      localStorage.theme === &#39;dark&#39; ||
      (!(&#39;theme&#39; in localStorage) &amp;&amp;
        window.matchMedia(&#39;(prefers-color-scheme: dark)&#39;).matches);
    setDarkMode(isDark);
    updateDarkMode(isDark);
  }, []);

  return (
    // 자식 컴포넌트에서 다크모드 설정값에 접근하고 값을 변경할 수 있도록
    // darkMode 변수와 toggle 함수를 전달
    &lt;DarkModeContext.Provider value={{ darkMode, toggleDarkMode }}&gt;
      {children}
    &lt;/DarkModeContext.Provider&gt;
  );
};

// 다크모드 값에 따라 document.documentElement 즉, 루트 요소(html)에 &#39;dark&#39; class 값을 추가, 제거
function updateDarkMode(darkMode: boolean) {
  if (darkMode) {
    document.documentElement.classList.add(&#39;dark&#39;);
    localStorage.theme = &#39;dark&#39;;
  } else {
    document.documentElement.classList.remove(&#39;dark&#39;);
    localStorage.theme = &#39;light&#39;;
  }
}

// 외부에서 다크모드 컨텍스트를 사용하기 쉽도록 custom hook을 만들어 사용
export const useDarkMode = () =&gt; useContext(DarkModeContext);</code></pre>
<h3 id="다크모드-세팅-기억">다크모드 세팅 기억</h3>
<blockquote>
<p><code>prefers-color-scheme</code> CSS 미디어 특성은 사용자의 시스템이 라이트 테마나 다크 테마를 사용하는지 탐지하는 데에 사용됩니다.
<a href="https://developer.mozilla.org/ko/docs/Web/CSS/@media/prefers-color-scheme">prefers-color-scheme - CSS: Cascading Style Sheets | MDN</a></p>
</blockquote>
<p><code>prefers-color-scheme</code> 미디어 쿼리를 사용하면 사용자 운영체제의 다크모드 설정 여부를 알 수 있다. <code>matchMedia()</code> 메서드에 분석할 미디어 쿼리 문자열을 전달하면 반환되는 <code>MediaQueryList</code> 객체의 <code>matches</code> 속성은 반환값으로 참/거짓을 반환하는데 이를 활용. <a href="https://developer.mozilla.org/ko/docs/Web/API/Window/matchMedia">Window.matchMedia() - Web API | MDN</a>
<code>window.matchMedia(&#39;(prefers-color-scheme: dark)&#39;).matches);</code>
이를 활용해 최초 웹페이지에 접근하면 운영체제의 다크모드 설정 여부를 따르고 이후 localStorage의 theme 값에 따라 다크모드/라이트모드를 적용한다.</p>
<h3 id="실제-적용">실제 적용</h3>
<p>커스텀 hooks를 만들어두었기에 쉽게 사용 가능.</p>
<pre><code class="language-tsx">import React from &#39;react&#39;;
import { useDarkMode } from &#39;../reducer/DarkModeContext&#39;;
import styles from &#39;./ToggleTheme.module.css&#39;;

export default function ToggleTheme() {
  const { darkMode, toggleDarkMode } = useDarkMode();

  return (
    &lt;div className={styles.theme}&gt;
      &lt;input
        type=&quot;checkbox&quot;
        id=&quot;toggle&quot;
        hidden
        checked={darkMode}
        onChange={toggleDarkMode}
      /&gt;
      &lt;label htmlFor=&quot;toggle&quot;&gt;
        &lt;span /&gt;
      &lt;/label&gt;
    &lt;/div&gt;
  );
}</code></pre>
<h3 id="결과">결과</h3>
<p><img src="https://velog.velcdn.com/images/code_newb/post/ed98773f-e4ec-4339-9453-97d42e684d9b/image.gif" alt=""></p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://bepyan.github.io/blog/2022/css-in-js">CSS-in-JS 라이브러리들에 대한 고찰</a></li>
<li><a href="https://react.dev/learn/passing-data-deeply-with-context">Passing Data Deeply with Context - React</a></li>
<li><a href="https://fe-developers.kakaoent.com/2021/211118-dark-mode/">웹에서 다크모드 지원하기 | 카카오엔터테인먼트 FE 기술블로그</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[다크모드에 대해 알아보자]]></title>
            <link>https://velog.io/@code_newb/darkmodelearning</link>
            <guid>https://velog.io/@code_newb/darkmodelearning</guid>
            <pubDate>Wed, 12 Apr 2023 06:42:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>투두리스트 프로젝트 중 기능으로 다크모드를 추가하였으나 가독성과 컬러 선택이 아쉬워 다크모드에 대해 알아보았습니다.</p>
</blockquote>
<h1 id="다크모드">다크모드</h1>
<blockquote>
<p><strong>다크 모드</strong>(<a href="https://ko.wikipedia.org/wiki/%EC%98%81%EC%96%B4" title="영어">영어</a>: Dark Mode), <strong>다크 테마</strong>(dark theme), <strong>블랙 모드</strong>(black mode), <strong>나이트 모드</strong>(night mode)는 밝은 색의 텍스트, 아이콘, <a href="https://ko.wikipedia.org/w/index.php?title=%EA%B7%B8%EB%9E%98%ED%94%BD_%EC%82%AC%EC%9A%A9%EC%9E%90_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4_%EC%9A%94%EC%86%8C&amp;action=edit&amp;redlink=1" title="그래픽 사용자 인터페이스 요소 (없는 문서)">그래픽 사용자 인터페이스 요소</a>들을 어두운 배경 위에 사용하는 <a href="https://ko.wikipedia.org/wiki/%EC%BB%AC%EB%9F%AC_%EC%8A%A4%ED%82%B4" title="컬러 스킴">컬러 스킴</a>으로, 컴퓨터 <a href="https://ko.wikipedia.org/wiki/%EC%82%AC%EC%9A%A9%EC%9E%90_%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4" title="사용자 인터페이스">사용자 인터페이스</a> 디자인과 <a href="https://ko.wikipedia.org/wiki/%EC%9B%B9_%EB%94%94%EC%9E%90%EC%9D%B8" title="웹 디자인">웹 디자인</a> 면에서 자주 논의되는 모드이다.
<a href="https://ko.wikipedia.org/wiki/%EB%8B%A4%ED%81%AC_%EB%AA%A8%EB%93%9C">다크 모드 - 위키백과, 우리 모두의 백과사전</a></p>
</blockquote>
<h2 id="다크모드를-지원해야-하는-이유">&quot;다크모드를 지원해야 하는 이유&quot;</h2>
<p><strong>사용자에게 좋은 경험을 제공하기 위해</strong></p>
<p>사용자의 눈의 피로를 덜어주고 집중도를 높여줄 수 있는 방법으로 다크모드를 사용한다. 모니터 화면을 장시간 봐야 하는 경우 라이트 모드는 눈이 쉽게 피로해지는 반면 다크 모드는 상대적으로 피로감이 덜하다</p>
<p>또한, 다크모드 OS UI 사용자가 라이트 모드의 화면을 마주해 느낄 수 있는 이질감을 없애기 위함</p>
<h2 id="다크모드-ui-디자인">다크모드 UI 디자인</h2>
<p>다크 테마는 테마가 검은색이라는 말이 아닌 <strong>저조도</strong>의 테마라고 보는 것이 정확</p>
<h3 id="주의할-점-색상">주의할 점: 색상</h3>
<p><strong>채도가 높은 색상은 어두운 바탕에서는 떨리는 것처럼 보일 수 있기 때문에, 다크모드 UI에서는 채도가 높은 색상을 피하는 것이 좋다</strong></p>
<blockquote>
<p>색이 보다 선명할수록 채도가 높다고 말하며 회색이나 흰색 또는 검정과 같은 무채색에 가까울수록 채도가 낮다고 말한다.</p>
</blockquote>
<p>텍스트와 함께 색상을 사용할 때는 콘트라스트 비율이 WCAG의 AA 표준인 최소 4.5대 1을 넘어야만 한다
(참고: <a href="https://snook.ca/technical/colour_contrast/colour.html#fg=33FF33,bg=333333">명도 대비 평가 도구</a>)</p>
<p>배경이나 화면의 색으로는 순수한 검은색(#000000)을 사용하지 않는 것이 좋다</p>
<h3 id="원칙">원칙</h3>
<ul>
<li><p>다크모드는 색상으로 높이차를 나타낸다. 위로 갈수록 밝은 색상 사용</p>
<ul>
<li>이유: 라이트모드에서는 높이차를 그림자로 표현할 수 있으나 다크모드에서는 그림자 표현이 두드러지지 않기 때문</li>
</ul>
</li>
<li><p>악센트 색상 사용</p>
<ul>
<li>어두운 테마 UI에 제한된 색상 액센트를 텍스트나 버튼과 같은 핵심 요소를 강조하기 위해 드물게 사용해야 한다</li>
</ul>
</li>
<li><p>Opacity 활용</p>
<ul>
<li>텍스트의 강조를 위해. 가장 강조되어야 하는 텍스트는 87%, 그 다음 60%, 비활성화 상태의 텍스트는 38%가 적당하다</li>
</ul>
</li>
</ul>
<h3 id="다크모드-설계-고려사항">다크모드 설계 고려사항</h3>
<ul>
<li><p>컬러 시스템의 1대 1 매칭</p>
<ul>
<li><p>Hex 컬러 값으로 매칭하는 것이 아니라 해당 컬러가 사용된 UI와 목적에 따라 네이밍을 정해 시스템화하는 것이 필요하다</p>
</li>
<li><p>e.g. #fff - white 대신 #fff - background로 네이밍. 다크 모드에서는 #121212 컬러로 지정하여 매칭</p>
</li>
</ul>
</li>
<li><p>Elevated UI의 고려</p>
<ul>
<li>2개 이상의 레이어가 겹치는 상황을 대비해 최소 3가지 이상의 Elevated UI 컬러를 지정</li>
</ul>
</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><p><a href="https://m2.material.io/design/color/dark-theme.html">Dark theme - Material Design</a></p>
</li>
<li><p><a href="https://brunch.co.kr/@slowmslife/32">다크모드의 UI 컬러</a></p>
</li>
<li><p><a href="http://icunow.co.kr/guide-darkmode/">다크모드 구성, 어떻게 하면 좋을까? | 지금 써보러 갑니다</a></p>
</li>
<li><p><a href="https://velog.io/@yijaee/%EB%8B%A4%ED%81%AC%EB%AA%A8%EB%93%9C-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0">다크모드 구현하기</a></p>
</li>
<li><p><a href="https://yozm.wishket.com/magazine/detail/619/">다크모드 UI 디자인의 원칙 | 요즘IT</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래밍이란?]]></title>
            <link>https://velog.io/@code_newb/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-%EC%8A%A4%ED%84%B0%EB%94%94-1</link>
            <guid>https://velog.io/@code_newb/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-%EC%8A%A4%ED%84%B0%EB%94%94-1</guid>
            <pubDate>Thu, 26 Jan 2023 02:57:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>《모던 자바스크립트 Deep Dive》 1장을 학습하며 정리한 포스트입니다.</p>
</blockquote>
<h2 id="프로그래밍이란">프로그래밍이란?</h2>
<blockquote>
<p>프로그래밍이란 컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션이다</p>
</blockquote>
<p>커뮤니케이션의 목적 중의 하나는 소통이나 관계를 통해 이루고자 하는 특정 요구를 실현하는 것이다. 컴퓨터에게 실행을 요구하는 이유, 프로그램이 필요한 이유는 주어진 문제를 더욱 간편하게 빠르게 쉽게 해결하기 위해서이다.</p>
<p>하지만, 컴퓨터는 0과 1밖에 알지 못하는 기계이다. 프로그래밍이란 멍청하지만 똑똑한 컴퓨터가 실행할 수 있도록 정확하고 상세하게 요구사항을 설명하는 작업이다. <strong>문제(요구사항)를 명확히 이해하는 것을 우선</strong>으로 복잡함을 단순하게 분해하고 정리하여 구분해야 하며 순서에 맞게 행위를 배열해야 한다. 모호하고 대략적인 요구사항을 전달하면 기대하는 결과는 얻을 수 없다.</p>
<p>컴퓨터와 사람은 사고, 인지의 방식이 다르다. 따라서 컴퓨터의 관점에서 해결하려는 문제를 절차적으로 사고하고 효과적으로 해결할 수 있는 절차적 사고 능력이 필요하다.</p>
<h2 id="프로그래밍-언어">프로그래밍 언어</h2>
<p>이렇게 정의된 문제 해결 방안이 컴퓨터에게 전달된다. 그러나, 컴퓨터는 0과 1만을 이해한다고 했다. 명령을 수행하는 주체는 컴퓨터이므로 사람의 표현법이 아니라 컴퓨터의 표현법으로 명령을 전달해야 한다. 컴퓨터가 이해할 수 있는 언어는 0과 1로만 구성된 기계어이다.</p>
<p>하지만 사람이 기계어를 이해해서 직접 명령을 전달하는 것은 매우 어려운 일이다. 그렇기에 사람이 이해할 수 있는 약속된 구문(문법)으로 구성된 &quot;프로그래밍 언어&quot;를 사용해 프로그램을 작성한 후, 그것을 컴퓨터가 이해할 수 있는 기계어로 변환하는 일종의 번역기를 이용한다. 이 일종의 번역기를 컴파일러 혹은 인터프리터라고 한다. </p>
<h2 id="구문과-의미">구문과 의미</h2>
<p>언어의 구성 요소에는 형태, 내용, 사용이 있다고 한다. 언어의 형태는 언어가 어떤 모양을 가지고 있는지, 내용은 언어가 가지고 있는 의미를, 사용은 실제로 언어가 어떻게 사용되는지를 말한다. 프로그래밍 &#39;언어&#39;는 구문과 의미의 조합으로 표현된다.</p>
<p>&quot;외국어를 잘하려면 외국어 화자의 말이나 문장을 정확히 이해한 후, 문맥에 따른 적절한 어휘 선택, 그리고 순차적으로 결론을 향해 나아가는 문장 구성이 필요하다. 즉, 문법에 맞는 문장을 구성하는 것은 물론 의미(sementics)를 가지고 있어야 언어의 역할을 충실히 수행할 수 있다.&quot;</p>
<p>정의된 문제의 해결 방안은 프로그래밍 언어의 문법을 사용해 표현한다. 작성된 코드는 해결 방안의 구체적 구현물이다. 이것은 요구사항이 실현(문제가 해결)되어야 의미가 있다. 커뮤니케이션의 목적을 달성하는 것이다.</p>
<blockquote>
<p>결국 프로그래밍은 요구사항의 집합을 분석해서 적절한 자료구조와 함수의 집합으로 변환한 후, 그 흐름을 제어하는 것이다.</p>
</blockquote>
<h2 id="review">Review</h2>
<p>컴퓨터는 정확하다. 요구한 대로 동작한다. 문제가 있는 것은 나의 코드이다.
코드를 먼저 작성하기보다 문제를 이해하고 작은 단위로 분해하고, 적절한 자료구조와 알고리즘을 사용하여 원활한 커뮤니케이션을 추구해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ReactJS] 2. styled-components 동작 원리]]></title>
            <link>https://velog.io/@code_newb/ReactJS-2.-styled-components-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@code_newb/ReactJS-2.-styled-components-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Wed, 18 Jan 2023 08:25:02 GMT</pubDate>
            <description><![CDATA[<h2 id="styled-components">styled-components</h2>
<p>styled-components는 CSS-in-JS 라이브러리로 Tagged Template Literals이라는 ES6 문법을 사용하여 스타일을 지정합니다. HTML 엘리먼트나 React 컴포넌트를 전달하고 백틱(`) 기호 내에 CSS 코드를 작성하면 스타일이 적용된 HTML 엘리먼트나 React 컴포넌트를 반환합니다.</p>
<h2 id="동작-원리">동작 원리</h2>
<h3 id="tagged-template-literals"><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals#tagged_templates">Tagged template literals?</a></h3>
<blockquote>
<p>template literals 의 더욱 발전된 한 형태는 tagged templates 입니다. 태그를 사용하면 템플릿 리터럴을 함수로 파싱 할 수 있습니다. 태그 함수의 첫 번째 인수는 문자열 값의 배열을 포함합니다. 나머지 인수는 표현식과 관련됩니다.</p>
</blockquote>
<p>** styled.h1`` ** 문법은 h1 이라는 함수를 호출하는 것(styled.h1())과 같습니다. 하지만 차이점은 tagged templates literals를 사용하면 템플릿 리터럴이 모두 분할되어 문자열 배열을 첫 번째 인자로 가지고 다음 인자는 스트링 템플릿(<code>${}</code>)으로 전달된 값들을 갖습니다.</p>
<pre><code class="language-js">const logArgs = (...args) =&gt; console.log(...args)
const favoriteFood = &#39;pizza&#39;

logArgs(`I like ${favoriteFood}`)
// I like pizza

logArgs`I like ${favoriteFood}`
// [&#39;I like &#39;, &#39;&#39;] &#39;pizza&#39;</code></pre>
<p><strong>이를 사용한 styled-components에서의 예제로 살펴보겠습니다.</strong></p>
<pre><code class="language-jsx">const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
`;

const App = () =&gt; {
  console.log(Title);
  return &lt;Title&gt;ToDoList&lt;/Title&gt;
};
</code></pre>
<p><img src="https://velog.velcdn.com/images/code_newb/post/9f4ed25d-2189-43e1-9a74-22d161c88bc3/image.png" alt=""></p>
<p>전달한 HTML Element에 해시값으로 자동으로 클래스명이 생성되었고 스타일 태그로 적용된 것을 확인할 수 있습니다. 출력 결과의 <code>componentStyle &gt; rules</code>를 살펴보면 tagged templates literals 문법으로 표현되어 있습니다.</p>
<p>데이터를 가공하는 방법에 대해서는 <a href="https://www.youtube.com/watch?v=ZQcILg_OvY0">&quot;Styled Components의 작동 원리 (ES6 태그 템플릿)&quot;</a> 이 영상을 참고해보세요.</p>
<p>styled-components는 렌더링 될 때 DOM 요소에 고유한 클래스명이 주입되므로 다른 요소에 영향을 미치지 않으며 CSS 표준 문법을 사용해 쉽게 스타일을 적용할 수 있게 합니다. </p>
<p>tagged templates literals로 함수가 호출될 때 실제 함수가 전달됩니다. 아래 예제에서 괄호를 사용해 <code>execFunArgs</code> 함수를 호출했을 때 실제 함수가 전달되지 않았기 때문에 아무 일도 일어나지 않습니다. 그저 단순한 문자열이 전달된 것입니다.</p>
<pre><code class="language-js">const execFuncArgs = (...args) =&gt; args.forEach(arg =&gt; {
  if (typeof arg === &#39;function&#39;) {
    arg()
  }
})

execFuncArgs(`Hi, ${() =&gt; { console.log(&#39;Executed!&#39;) }}`)
// undefined

execFuncArgs`Hi, ${() =&gt; { console.log(&#39;Executed!&#39;) }}`
// &quot;Executed!&quot;</code></pre>
<p>template literal 문법으로 함수를 전달할 수 있기 때문에 props에 기반한 동적인 스타일링이 가능한 것!</p>
<pre><code class="language-jsx">const Button = styled.button`
  font-size: 1em;
  color: ${props =&gt; props.primary ? &quot;white&quot; : &quot;palevioletred&quot;};
`;

return (
  &lt;div&gt;
    &lt;Button&gt;Normal&lt;/Button&gt;
    &lt;Button primary&gt;Primary&lt;/Button&gt;
  &lt;/div&gt;
);</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://mxstbr.blog/2016/11/styled-components-magic-explained/">The magic behind 💅 styled-components - Max Stoibers Blog</a></li>
<li><a href="https://www.zigae.com/styled-components-abstract/">우리가 몰랐던 styled-components 동작원리</a></li>
<li><a href="https://www.joshwcomeau.com/react/demystifying-styled-components/">Demystifying styled-components</a></li>
<li><a href="https://medium.com/styled-components/how-styled-components-works-618a69970421">How styled-components works: A deep dive under the hood</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ReactJS] 1. styled-components 사용 이유]]></title>
            <link>https://velog.io/@code_newb/React-JS-1.-styled-components-%EC%82%AC%EC%9A%A9-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@code_newb/React-JS-1.-styled-components-%EC%82%AC%EC%9A%A9-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Tue, 17 Jan 2023 10:41:14 GMT</pubDate>
            <description><![CDATA[<h2 id="리액트-컴포넌트-스타일링-방법들">리액트 컴포넌트 스타일링 방법들</h2>
<h3 id="1-inline-style">1. Inline style</h3>
<p>가장 간단하고 쉬운 방법으로 리액트 컴포넌트에 직접 스타일을 적용
HTML 엘리먼트의 style 속성을 이용</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;

const Box = () =&gt; {
  return &lt;div style={{width: &#39;200px&#39;, height: &#39;200px&#39;, backgroundColor: &#39;teal&#39;}}&gt;...&lt;/div&gt;;
};

export default App;</code></pre>
<h3 id="2-cssscss">2. css/scss</h3>
<p>외부 스타일 시트 파일을 리액트 컴포넌트에서 불러와서 스타일을 적용</p>
<pre><code class="language-css">// styles.css

.box {
  width: &#39;200px&#39;;
  height: &#39;200px&#39;;
  backgroundColor: &#39;teal&#39;;
}</code></pre>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import &#39;./styles.css&#39;

const Box = () =&gt; {
  return &lt;div className=&quot;box&quot;&gt;...&lt;/div&gt;;
};

export default Box;</code></pre>
<h3 id="3-css-module">3. css Module</h3>
<p>css를 모듈화 하여 사용하는 방식. css 파일을 불러올 때 고유한 클래스명을 만들어서 클래스명이 중첩되는 현상을 방지</p>
<pre><code class="language-css">// box.module.css

.box {
  width: &#39;200px&#39;;
  height: &#39;200px&#39;;
  backgroundColor: &#39;teal&#39;;
}</code></pre>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import styles from &#39;./box.module.css&#39;

const Box = () =&gt; {
  return &lt;div className={styles.box}&gt;...&lt;/div&gt;;
};

export default Box;</code></pre>
<h2 id="문제점">문제점?</h2>
<ul>
<li><code>inline style</code> =&gt; <code>:hover</code>과 같은 의사 클래스를 사용하지 못하고 지속/확장 가능하지 않기 때문에 권장X</li>
<li><code>css/scss</code> =&gt; css파일의 코드들이 애플리케이션 전체에 적용 ➡ 전역적으로 css를 적용하게 되면 유지 관리와 사용하기가 어려움(전역 네임스페이스)</li>
<li><code>css Module</code> =&gt; className만으로는 동적인 스타일링을 구현하기 어려움</li>
</ul>
<h2 id="css-in-js">CSS-in-JS</h2>
<p>JavaScript를 사용하여 스타일을 지정하는 방법으로 스타일을 구성 요소 수준으로 추상화합니다(+ CSS는 스타일을 문서 수준으로 적용).
<br/>ReactJS를 사용해 웹을 개발하면 Component 단위로 만들어 조합하여 웹 페이지를 구성합니다. JavaScript 환경을 최대한 활용하며 컴포넌트 레벨로 추상화하기에 <a href="https://styled-components.com/docs/basics#motivation">여러 장점</a>이 있습니다.</p>
<h2 id="styled-components">styled-components</h2>
<p>styled-components는 리액트 컴포넌트에 스타일을 효율적으로 작성하기 위한 대표적인 CSS-in-JS 라이브러리 중 하나입니다. 애니메이션, 테마, 전역 스타일링, props 기반의 동적 스타일링 등 여러 강력한 기능들을 제공합니다. 
다크모드와 상태변화에 따른 동적 스타일링을 효율적으로 작성하기 위해 styled-components 라이브러리를 사용하여 앞으로의 프로젝트를 진행합니다.</p>
<p><a href="https://analogcoding.tistory.com/181">styled-components 를 사용하는 8가지 이유 -번역</a></p>
<p><img src="https://velog.velcdn.com/images/code_newb/post/3eaf1a31-cdb0-41f0-b58b-f6cead4897ca/image.png" alt="npm trends: css-in-js library">▶ 가장 인기 있는 CSS-in-JS 라이브러리 (23. 1. 17 기준) <a href="https://npmtrends.com/emotion-vs-jss-vs-styled-components">Link</a></p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.daleseo.com/react-styling/">React 컴포넌트 CSS 스타일링 기본</a></li>
<li><a href="https://styled-components.com/docs">styled-components: Documentation</a></li>
<li><a href="https://yamoo9.github.io/react-master/lecture/sc-gettring-started.html#%E1%84%86%E1%85%A9%E1%84%90%E1%85%B5%E1%84%87%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%89%E1%85%A7%E1%86%AB">스타일 라이브러리 | 야무의 React 러닝 가이드</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML 문서 구조]]></title>
            <link>https://velog.io/@code_newb/HTML-%EB%AC%B8%EC%84%9C-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@code_newb/HTML-%EB%AC%B8%EC%84%9C-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Thu, 19 May 2022 12:56:31 GMT</pubDate>
            <description><![CDATA[<h1 id="html-문서-구조">HTML 문서 구조</h1>
<h2 id="시맨틱-태그">시맨틱 태그</h2>
<p><strong>시멘틱(semantic)</strong> 이란 &#39;의미론적인&#39;, &#39;의미가 통하는&#39;이라는 뜻이 있습니다. 의미에 맞는 태그, 요소를 사용하고 구조화를 잘 해주어야 기계뿐 아니라 사람에게도 명확한 의미를 전달할 수 있습니다.</p>
<h3 id="시맨틱-태그를-사용하여-얻는-이점">시맨틱 태그를 사용하여 얻는 이점</h3>
<ul>
<li><p>검색 엔진에 의해 검색 결과가 상위에 노출될 수 있게 합니다.</p>
<ul>
<li><blockquote>
<p><strong>검색 엔진의 동작 원리</strong></p>
<p>검색 엔진은 크게 정보 수집, 색인 그리고 검색의 순서로 동작합니다.</p>
<p>검색 엔진은 사용자가 검색 엔진을 사용하기 전에 미리 웹 상에서 정보를 수집하여 색인을 만들어 놓습니다.</p>
<p>그리고나서 사용자가 찾고자 하는 정보의 키워드를 입력하면, 미리 만들어 놓은 색인 중에서 입력된 키워드에 해당하는 정보들을 찾아서 보여주는 것입니다.
<a href="http://www.tcpschool.com/webbasic/searchengine">코딩의 시작, TCP School</a></p>
</blockquote>
</li>
</ul>
</li>
<li><p>시각 장애가 있는 사용자가 스크린 리더로 페이지를 탐색할 때 웹 사이트의 구조를 제대로 이해할 수 있습니다.</p>
</li>
<li><p>문서 구조가 정확히 나눠지므로 다양한 기기에서 웹 문서를 표현하기가 쉽습니다.</p>
</li>
</ul>
<h2 id="html-레이아웃">HTML 레이아웃</h2>
<p>레이아웃(layout)은 각 구성요소를 제한된 공간 안에 효과적으로 배열하는 일을 의미합니다. 웹 페이지는 디자인은 서로 달라 보여도 대부분 비슷한 구조로 짜여져 있습니다.</p>
<p>HTML5에서는 웹 페이지의 레이아웃만을 위한 시맨틱 요소들을 제공합니다. 이는 웹 브라우저가 문서 구조를 파악하는데 중요한 역할을 합니다.</p>
<h3 id="header"><code>&lt;header&gt;</code></h3>
<p>웹 페이지의 헤더 내용을 포함하는 데 사용됩니다. 헤더에는 소개 콘텐츠, 제목 요소, 검색 창, 웹페이지의 로고 또는 아이콘, 저작권 정보 등이 포함됩니다. 한 문서 내에 여러 개의 header 요소가 존재할 수 있습니다.</p>
<pre><code class="language-html">&lt;header&gt;
    &lt;h1&gt;HTML&lt;/h1&gt;
&lt;/header&gt;
...
&lt;section&gt;
    &lt;header&gt;
        &lt;h2&gt;HTML Tags&lt;/h2&gt;
        &lt;p&gt;HTML tags are ...&lt;/p&gt;
    &lt;/header&gt;
&lt;/section&gt;</code></pre>
<h3 id="nav"><code>&lt;nav&gt;</code></h3>
<p>같은 웹 문서 안에서 다른 위치로 연결하거나 다른 웹 문서로 연결하는 링크를 만듭니다. <code>&lt;nav&gt;</code> 요소는 주요 탐색 링크에만 쓰입니다. 문서의 모든 링크가 <code>&lt;nav&gt;</code> 요소 안에 있을 필요가 없으며 사이트 전체 탐색이나 현재 페이지 내 탐색으로 사용하는 등 하나의 문서에서 여러 개의 <code>&lt;nav&gt;</code> 태그를 가질 수 있습니다. 주로 메뉴, 목차, 색인에 쓰입니다.</p>
<pre><code class="language-html">&lt;nav&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Home&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;About&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;#&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/nav&gt;</code></pre>
<h3 id="main"><code>&lt;main&gt;</code></h3>
<p>해당 문서의 주요 콘텐츠를 나타냅니다. 사이드바, 탐색 링크, 저작권 정보, 사이트 로고 및 검색 양식과 같은 문서에서 반복되는 콘텐츠를 포함해서는 안 됩니다. 하나의 문서에는 단 하나의 <code>&lt;main&gt;</code>만 사용해야 합니다.</p>
<pre><code class="language-html">&lt;main&gt;
  &lt;h1&gt;Front-end web develop&lt;/h1&gt;
  &lt;p&gt;Front-end web development is the development of the graphical user interface of a website.&lt;/p&gt;
  &lt;section&gt;
    &lt;h2&gt;HTML&lt;/h2&gt;
    &lt;p&gt;HyperText Markup Language (HTML) is the backbone of any website development process, without which a web page does not exist&lt;/p&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h2&gt;CSS&lt;/h2&gt;
    &lt;p&gt;Cascading Style Sheets (CSS) controls the presentation aspect of the site and allows your site to have its own unique look.&lt;/p&gt;
  &lt;/section&gt;
  &lt;section&gt;
    &lt;h2&gt;JavaScript&lt;/h2&gt;
    &lt;p&gt;JavaScript is an event-based imperative programming language (as opposed to HTML&#39;s declarative language model) that is used to transform a static HTML page into a dynamic interface.&lt;/p&gt;
  &lt;/section&gt;
&lt;/main&gt;</code></pre>
<h3 id="section"><code>&lt;section&gt;</code></h3>
<p>웹 페이지의 구역을 나타내는 데 사용됩니다. 섹션의 예로는 장(chapter), 탭 대화 상자 내의 다양한 탭 페이지, 논문의 장/절 등이 있습니다. 각각의 구역을 구별하기 위해 제목 요소(h1~h6)를 자식 요소로 포함하고 있는 경우가 많습니다. 단순한 스타일링이 목적이라면 <code>&lt;div&gt;</code> 요소를 사용해야 합니다.</p>
<h3 id="article"><code>&lt;article&gt;</code></h3>
<p>문서, 페이지, 애플리케이션, 또는 사이트 안에서 독립적으로 구분해 배포하거나 재사용할 수 있는 구역을 나타냅니다. 게시판과 블로그 글, 매거진이나 뉴스 기사 등이 여기에 해당합니다.</p>
<pre><code class="language-html">&lt;h1&gt;Most Popular Browsers&lt;/h1&gt;
&lt;article&gt;
    &lt;h2&gt;Google Chrome&lt;/h2&gt;
    &lt;p&gt;Google Chrome is a web browser developed by Google, released in 2008. Chrome is the world&#39;s most popular web browser today!&lt;/p&gt;
&lt;/article&gt;
&lt;article&gt;
    &lt;h2&gt;Mozilla Firefox&lt;/h2&gt;
    &lt;p&gt;Mozilla Firefox is an open-source web browser developed by Mozilla. Firefox has been the second most popular web browser since January, 2018.&lt;/p&gt;
&lt;/article&gt;</code></pre>
<h4 id="article-vs-section">article vs section</h4>
<p>자체만으로 다른 페이지에 보여질 수 있을 때 article을 사용하며 section은 일반적으로 제목(h1-h6)으로 시작하여 관련된 정보를 포함하고 있는 구역입니다.</p>
<p><code>&lt;article&gt;</code> 내에 많은 내용이 포함될텐데 연관있는 내용들을 묶어줄 때 <code>&lt;section&gt;</code>을 사용할 수 있습니다. 여러 개의 <code>&lt;section&gt;</code>을 <code>&lt;article&gt;</code>로 묶을 수 있고 그 반대도 가능합니다.</p>
<h3 id="aside"><code>&lt;aside&gt;</code></h3>
<p>주요 콘텐츠에 대한 몇 가지 추가 정보를 포함하는 데 사용됩니다. 문서의 주요 내용과 간접적으로만 연관되어 해당 콘텐츠들로부터 분리시킬 수 있는 콘텐츠로 구성된 페이지 영역을 정의합니다.</p>
<pre><code class="language-html">&lt;p&gt;HTML(Hypertext Markup Language) is a markup language that tells web browsers how to structure the web pages you visit.&lt;/p&gt;
&lt;aside&gt;
    &lt;h4&gt;markup language&lt;/h4&gt;
    &lt;p&gt;A markup language is a set of rules governing what markup information may be included in a document and how it is combined with the content of the document in a way to facilitate use by humans and computer programs.&lt;/p&gt;
&lt;/aside&gt;</code></pre>
<h3 id="footer"><code>&lt;footer&gt;</code></h3>
<p>작성자, 저작권 정보, 관련 문서, 사이트맵 등 문서 또는 구역의 바닥글 콘텐츠를 포함하는 데 사용됩니다. 연락처 정보는 <code>&lt;address&gt;</code> 태그 내에 작성합니다. 하나의 HTML 문서에는 여러 개의 <code>&lt;footer&gt;</code> 요소가 포함될 수 있습니다.</p>
<pre><code class="language-html">&lt;footer&gt; 
    &lt;a href=&quot;#&quot;&gt;About Us&lt;/a&gt;|
    &lt;a href=&quot;#&quot;&gt;Privacy Policy&lt;/a&gt;
    &lt;p&gt;Copyright © 2022 .. All rights reserved&lt;/p&gt;
    &lt;address&gt;Contact 010-1234-5678&lt;/address&gt;
&lt;/footer&gt;</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><p><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element">HTML 요소 참고서 - HTML: Hypertext Markup Language | MDN</a></p>
</li>
<li><p><a href="https://www.w3schools.com/tags/default.asp">HTML Reference</a></p>
</li>
<li><p><a href="https://www.javatpoint.com/html-tags">HTML Tags - javatpoint</a></p>
</li>
<li><p><a href="http://www.tcpschool.com/html-tags/intro">코딩의 시작, TCP School</a></p>
</li>
<li><p><a href="https://www.geeksforgeeks.org/html-tags-complete-reference/">HTML Tags Complete Reference - GeeksforGeeks</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML 텍스트 관련 태그들]]></title>
            <link>https://velog.io/@code_newb/HTML-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EA%B4%80%EB%A0%A8-%ED%83%9C%EA%B7%B8%EB%93%A4</link>
            <guid>https://velog.io/@code_newb/HTML-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EA%B4%80%EB%A0%A8-%ED%83%9C%EA%B7%B8%EB%93%A4</guid>
            <pubDate>Mon, 02 May 2022 12:17:05 GMT</pubDate>
            <description><![CDATA[<h1 id="html-텍스트-관련-태그">HTML 텍스트 관련 태그</h1>
<p>HTML의 주요 작업 중 하나는 브라우저가 텍스트를 올바르게 표시 할 수 있도록 텍스트 구조와 의미를 제공하는 것입니다. 따라서 알맞는 태그를 사용하여 텍스트로 정보를 전달하는 것은 매우 중요합니다.</p>
<h2 id="제목과-단락">제목과 단락</h2>
<h3 id="제목-태그">제목 태그</h3>
<p>제목(heading) 태그는 문서 내에 제목을 표현할 때 사용합니다. 제목 태그는 <code>&lt;h1&gt;</code>부터 <code>&lt;h6&gt;</code>까지 중요도에 다르게 사용합니다. 각 태그들은 계층적으로 올바른 순서로 사용해야 합니다. 6개의 제목 태그를 사용할 수 있지만 가급적 많은 목차 레벨을 갖지 않도록 하는 것이 좋습니다.</p>
<ul>
<li><p><code>&lt;h1&gt;</code>: 콘텐츠의 메인 테마나 제목과 같이 가장 중요한 텍스트를 나타내는 데 사용. 페이지당 하나만 사용하는 것을 권장</p>
</li>
<li><p><code>&lt;h2&gt;</code>, <code>&lt;h3&gt;</code>: 일반적으로 부제목으로 사용</p>
</li>
<li><p><code>&lt;h4&gt;, &lt;h5&gt;, &lt;h6&gt;</code>: 하위 섹션 내에서 추가 구조를 제공</p>
</li>
</ul>
<p><strong>HTML의 제목은 검색 엔진이 웹 페이지의 구조를 이해하고 색인을 생성하는 데 도움이 됩니다.</strong> 제목 태그는 사용자에게는 콘텐츠를 미리 보여주며 검색 엔진에게는 문맥과 계층 구조를 제공합니다.</p>
<blockquote>
<p><strong><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#why_do_we_need_structure" title="Permalink to Why do we need structure?">Why do we need structure?</a></strong></p>
</blockquote>
<h3 id="단락-태그">단락 태그</h3>
<p>단락(paragraph) 태그는 본문에 해당하는 내용을 표현할 때 사용합니다. 여러 개의 <code>&lt;p&gt;</code> 태그를 사용하면 브라우저는 자동으로 두 단락 사이에 공백 한 줄을 추가합니다. 단락 태그 내에 많은 공백을 넣으면 브라우저는 불필요한 공백과 추가된 줄을 제거합니다. 아래 두 코드의 실행 결과는 동일합니다.<img src="https://velog.velcdn.com/images/code_newb/post/ee22e059-7609-43f9-b5cb-ec6c48177cbe/image.png" alt="">html은 한 칸 이상의 공백 및 개행을 무시하기 때문에 개행을 위해서는 <code>&lt;br&gt;</code> 태그를 사용합니다.</p>
<h3 id="span-태그">span 태그</h3>
<p><code>&lt;span&gt;</code> 태그는 컨텐츠에 추가적인 의미를 더하지 않고 스타일을 적용하거나 JavaScript로 조작하기 위해 사용합니다. 또한, 텍스트의 일부 언어를 변경하거나 특정 부분에 스크립트를 적용할 때 컨테이너로 사용됩니다.</p>
<h2 id="리스트">리스트</h2>
<p>리스트는 일련된 항목들이 나열된 것들을 의미합니다. 콘텐츠가 많은 포털이나 검색 엔진같은 사이트에는 분야나 항목으로 구분할 것이 많으므로 리스트가 자주 사용됩니다.</p>
<h3 id="순서-있는-목록">순서 있는 목록</h3>
<p>순서 있는 목록(ordered list)이란 각 항목을 순서대로 나열한 것입니다. 숫자 순서 형식이나 알파벳 순서 형식 또는 순서가 강조되는 모든 형식으로 항목을 나타낼 수 있습니다. <code>&lt;ol&gt;</code> 태그는 순서가 있는 리스트를 표현할 때 사용합니다. <strong>type</strong> 태그 속성을 부여하여 5가지 유형을 적용할 수 있습니다.</p>
<ul>
<li><code>1</code> (기본값) - 숫자(1, 2, 3)</li>
<li><code>I</code> - 대문자 로마 숫자(I II III)</li>
<li><code>i</code> - 소문자 로마 숫자(i ii iii)</li>
<li><code>A</code> - 대문자 알파벳(ABC)</li>
<li><code>a</code> - 소문자 알파벳(abc)</li>
</ul>
<pre><code class="language-html">&lt;ul type=&quot;I&quot;&gt;
  &lt;li&gt;Coffee&lt;/li&gt;
  &lt;li&gt;Tea&lt;/li&gt;
  &lt;li&gt;Milk&lt;/li&gt;
&lt;/ul&gt;</code></pre>
<p><code>&lt;li&gt;</code> 태그는 각 목록 항목을 정의하는 데 사용됩니다. 반드시<code>&lt;ol&gt;</code>, <code>&lt;ul&gt;</code> 혹은 <code>&lt;menu&gt;</code> 안에 위치해야 합니다.</p>
<h3 id="순서없는-목록">순서없는 목록</h3>
<p>순서 없는 목록(unordered list)은 항목의 순서가 중요하지 않은 항목 목록을 표시하는 데 사용합니다. 서로 다른 순서의 목록을 나타내기 위해 <code>&lt;ul&gt;</code> 태그에는 4가지 종류의 <strong>type 속성값이 있으나 HTML5에서는 지원되지 않습니다</strong>.</p>
<ul>
<li><p><code>disc</code>(기본값) - 원</p>
</li>
<li><p><code>circle</code> - 빈 원</p>
</li>
<li><p><code>square</code> - 정사각형</p>
</li>
<li><p><code>none</code> - 없음</p>
</li>
</ul>
<h3 id="설명-목록">설명 목록</h3>
<p>dl(definition/description list) 태그는 용어와 그에 대한 정의를 표현할 때 사용합니다. <code>&lt;dl&gt;</code>은 용어와 설명이 하나의 세트로 항목을 이루고 하나 이상의 항목으로 리스트가 이루어지는 구조입니다.</p>
<ul>
<li><p><code>&lt;dt&gt;</code>: 용어를 나타내는 태그</p>
</li>
<li><p><code>&lt;dd&gt;</code>: 용어에 대한 정의 또는 설명</p>
</li>
</ul>
<pre><code class="language-html">&lt;dl&gt;  
  &lt;dt&gt;HTML&lt;/dt&gt;  
  &lt;dd&gt;is a markup language&lt;/dd&gt;  

  &lt;dt&gt;JavaScript&lt;/dt&gt;  
  &lt;dd&gt;is a scripting language&lt;/dd&gt;    
&lt;/dl&gt;  </code></pre>
<h2 id="그-밖의-텍스트-관련-태그">그 밖의 텍스트 관련 태그</h2>
<p>모든 텍스트 요소를 다루지는 못하고 일반적으로 사용되는 태그를 살펴보겠습니다.</p>
<h3 id="인용구">인용구</h3>
<p>다른 출처에서 인용된 블록을 정의하는데 사용합니다.</p>
<p>블록 레벨 컨텐츠의 섹션(문단, 여러 단락, 리스트등)이 인용된 경우, 이를 나타내는 <code>&lt;blockquote&gt;</code> 태그를 사용합니다. <code>cite</code> 속성에 인용의 출처를 표기합니다.</p>
<pre><code class="language-html">&lt;blockquote cite=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote&quot;&gt;
  &lt;p&gt;The &lt;strong&gt;HTML &lt;code&gt;&lt;blockquote&gt;&lt;/code&gt; Element&lt;/strong&gt; (or &lt;em&gt;HTML Block
  Quotation Element&lt;/em&gt;) indicates that the enclosed text is an extended quotation.&lt;/p&gt;
&lt;/blockquote&gt;</code></pre>
<p>짧은 인용문에는 <code>&lt;q&gt;</code> 태그가 쓰입니다. 마찬가지로 <code>cite</code> 속성을 가지므로 출처를 표기할 수 있습니다.</p>
<pre><code class="language-html">&lt;p&gt;The quote element — &lt;code&gt;&lt;q&gt;&lt;/code&gt; — is &lt;q cite=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q&quot;&gt;intended
for short quotations that don&#39;t require paragraph breaks.&lt;/q&gt;&lt;/p&gt;</code></pre>
<p>인용구에 쓰이는 두 태그의 차이는  <code>&lt;blockquote&gt;</code> 태그는 블록 레벨 요소, <code>&lt;q&gt;</code> 태그는 인라인 레벨 요소입니다. <code>&lt;blockquote&gt;</code> 태그는 브라우저에 표시될 때 들여쓰기된 문단으로, <code>&lt;q&gt;</code> 태그는 인용구를 따옴표로 묶어 표현합니다.</p>
<h3 id="약어">약어</h3>
<p><code>&lt;abbr&gt;</code> 태그는 요소의 약어나 축약형을 정의하는 데 사용합니다. 약어는 브라우저나 번역 시스템, 검색 엔진에게 유용한 정보를 줄 수 있습니다. <strong>title</strong> 속성을 통해 원래의 용어를 나타낼 수 있습니다.</p>
<pre><code class="language-html">&lt;abbr title=&quot;Hypertext Markup Language&quot;&gt;HTML&lt;/abbr&gt;</code></pre>
<p><code>&lt;abbr&gt;</code> 태그 사이에 작성된 내용은 일부 브라우저에서 점선 밑줄로 표시됩니다. 용어의 전체 뜻은 요소 위에 마우스를 올려 놓으면 설명이 표시됩니다.</p>
<h3 id="연락처-표시">연락처 표시</h3>
<p><code>&lt;address&gt;</code> 태그를 이용해서 연락처 세부 정보를 표시할 수 있습니다. <code>&lt;address&gt;</code> 태그가 <code>&lt;body&gt;</code> 태그 내에서 사용되면 문서의 연락처 정보를 나타내고, <code>&lt;article&gt;</code> 태그 내에서 사용되면 해당 글에 대한 연락 정보를 나타냅니다.</p>
<pre><code class="language-html">&lt;address&gt;
  &lt;p&gt;Chris Mills, Manchester, The Grim North, UK&lt;/p&gt;
&lt;/address&gt;</code></pre>
<p><code>&lt;address&gt;</code> 요소의 텍스트는 주로 이탤릭체(italic)로 표현되며, 위쪽과 아래쪽에 약간의 공백을 자동으로 삽입하여 다른 텍스트와 구분합니다.</p>
<h3 id="위첨자와-아래-첨자">위첨자와 아래 첨자</h3>
<p>위첨자를 표현할 때는 <code>&lt;sup&gt;</code> 태그를, 아래첨자를 표현할 때는 <code>&lt;sub&gt;</code> 태그를 사용합니다.</p>
<p>사용 예시</p>
<ul>
<li><p>아랫첨자: 수학 공식, 분자식, 화학 반응식 등</p>
</li>
<li><p>윗첨자: 수학 공식, 각주 등</p>
</li>
</ul>
<pre><code class="language-html">&lt;p&gt;My birthday is on the 25&lt;sup&gt;th&lt;/sup&gt; of May 2001.&lt;/p&gt;
&lt;p&gt;2H&lt;sub&gt;2&lt;/sub&gt; + O&lt;sub&gt;2&lt;/sub&gt; → 2H&lt;sub&gt;2&lt;/sub&gt;O&lt;/p&gt;</code></pre>
<h3 id="컴퓨터-코드">컴퓨터 코드</h3>
<p>컴퓨터 코드를 나타낼 때 아래와 같은 많은 요소들을 사용할 수 있습니다.</p>
<ul>
<li><code>&lt;code&gt;</code>: 일반적인 컴퓨터 코드</li>
<li><code>&lt;pre&gt;</code>: 공백(일반적으로 코드 블록)을 유지하기 위해 사용. 독특한 서식의 텍스트나 컴퓨터 코드 등을 HTML 문서에 그대로 표현</li>
<li><code>&lt;var&gt;</code>: 변수이름을 특별하게 표시</li>
<li><code>&lt;kbd&gt;</code>: 컴퓨터에 입력 된 키보드 (및 기타 유형) 입력을 표시</li>
<li><code>&lt;samp&gt;</code>: 컴퓨터 프로그램의 출력을 표시</li>
</ul>
<pre><code class="language-html">&lt;pre&gt;&lt;code&gt;const btn = document.querySelector(&#39;button&#39;);

btn.onclick = function() {
  alert(&#39;Hello!&#39;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;var&gt;btn&lt;/var&gt; represents a paragraph element.&lt;/p&gt;
&lt;p&gt;Select all the text with &lt;kbd&gt;Ctrl&lt;/kbd&gt;/&lt;kbd&gt;Cmd&lt;/kbd&gt; + &lt;kbd&gt;A&lt;/kbd&gt;.&lt;/p&gt;
&lt;p&gt;&lt;samp&gt;Keyboard not found!&lt;br&gt;Press F1 to continue...&lt;/samp&gt;&lt;/p&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/code_newb/post/96ba11ec-c097-4c57-be98-8043c7bfd43e/image.png" alt=""></p>
<h3 id="시간과-날짜">시간과 날짜</h3>
<p><code>&lt;time&gt;</code> 태그는 사람이 읽을 수 있는 날짜/시간을 표시하는 데 사용됩니다. <code>datetime</code> 속성은 시간을 기계가 읽을 수 있는 형식으로 변환하여 캘린더에 알림이나 이벤트를 추가하고 검색 엔진의 검색 결과 향상에 도움을 줍니다</p>
<pre><code class="language-html">&lt;time datetime=&quot;2016-01-20&quot;&gt;20 January 2016&lt;/time&gt;</code></pre>
<h2 id="하이퍼링크">하이퍼링크</h2>
<p>하이퍼링크(hyperlink)는 문서들을 다른 문서들과 연결시켜줍니다. 또는 원하는 다른 리소스와 연결시켜주기도 합니다.</p>
<h3 id="a-태그"><code>&lt;a&gt;</code> 태그</h3>
<p><code>&lt;a&gt;</code> 태그(앵커 태그) 는 웹페이지에 하이퍼링크를 생성하는 데 사용됩니다. 이 하이퍼링크는 웹페이지를 다른 웹페이지로 연결하는 데 사용됩니다.</p>
<p><code>&lt;a&gt;</code> 태그에서 가장 중요한 속성은 바로 링크(link)의 목적지를 가리키는 href 속성입니다. 아래 링크에서 <code>&lt;a</code>&gt; 태그의 많은 속성을 확인할 수 있습니다.</p>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a"><a>: The Anchor element - HTML: HyperText Markup Language | MDN</a></p>
<p>기본 스타일</p>
<ul>
<li>아직 방문하지 않은 링크 : 밑줄, 파란색</li>
</ul>
<ul>
<li><p>방문했던 링크 : 밑줄, 보라색</p>
</li>
<li><p>현재 마우스가 클릭하고 있는 링크 : 밑줄, 빨간색</p>
</li>
</ul>
<pre><code class="language-html">&lt;a href=&quot;https://developer.mozilla.org/ko/&quot;&gt;MDN Web Docs&lt;/a&gt;.</code></pre>
<h2 id="reference">Reference</h2>
<ul>
<li><p><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element">HTML 요소 참고서 - HTML: Hypertext Markup Language | MDN</a></p>
</li>
<li><p><a href="https://www.w3schools.com/tags/default.asp">HTML Reference</a></p>
</li>
<li><p><a href="https://www.javatpoint.com/html-tags">HTML Tags - javatpoint</a></p>
</li>
<li><p><a href="http://www.tcpschool.com/html-tags/intro">코딩의 시작, TCP School</a></p>
</li>
<li><p><a href="https://www.geeksforgeeks.org/html-tags-complete-reference/">HTML Tags Complete Reference - GeeksforGeeks</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML 기초]]></title>
            <link>https://velog.io/@code_newb/HTML-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@code_newb/HTML-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Wed, 27 Apr 2022 08:47:26 GMT</pubDate>
            <description><![CDATA[<h1 id="html">HTML</h1>
<h2 id="html이란">HTML이란?</h2>
<p>HTML은 <strong>HyperText Markup Language</strong>의 약자로 웹 페이지를 만드는 데 사용되는 언어입니다.</p>
<ul>
<li><p>Hypertext(하이퍼텍스트): 웹 페이지를 다른 페이지로 연결하는 링크</p>
</li>
<li><p>Markup Language(마크업 언어): 문서나 데이터의 구조를 표현하는 언어</p>
</li>
</ul>
<p>그저 데이터를 나열해 놓은 것이 아니라 본문의 제목, 단락, 목록 등과 같이 의미를 포함하며 웹 페이지의 구조를 설명합니다. 구조를 표현하기 위한 방법으로 &#39;태그(Tag)&#39;를 활용합니다.</p>
<h2 id="태그tag">태그(Tag)</h2>
<p><strong>태그</strong>는 무언가를 표시하기 위한 꼬리표라는 의미가 있으며 웹 페이지의 구조에 대한 정보를 브라우저에 제공합니다. <a href="https://ko.wikipedia.org/wiki/%EC%9B%B9_%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80">웹 브라우저</a>는 웹 서버 또는 로컬 저장소에서 HTML 문서를 수신하고 태그를 분석해 사용자가 볼 수 있는 웹 페이지로 표시합니다.</p>
<p>HTML은 태그들의 집합이며 태그는 요소를 만들 때 사용합니다. 태그는 <code>&lt;</code>, <code>&gt;</code> 기호로 표현하며 <code>&lt;</code>, <code>&gt;</code> 기호 사이에 태그 이름이 들어갑니다. 태그 이름은 대소문자를 구분하지 않지만 가독성과 기타 이유로 소문자로 작성하는 것이 좋습니다. <a href="https://stackoverflow.com/questions/19808514/is-it-bad-to-use-uppercase-letters-for-html-tags">소문자 작성 이유</a></p>
<p>태그는 일반적으로 여는 태그(Opnening tag)와 닫는 태그(Closing tag)로 이루어지며 닫는 태그는 태그 이름 앞에 <code>/</code> 기호가 붙습니다. 여는 태그와 닫는 태그 사이에는 내용이 위치합니다. 짝을 이루지 않아 내용이 없는 태그도 있습니다. 이를 빈 태그(Empty Tag)라고 합니다.</p>
<p>내용을 포함한 태그 전체를 <strong>요소(Element)</strong> 라고 합니다.</p>
<pre><code class="language-html">&lt;p&gt;Text&lt;/p&gt;</code></pre>
<ul>
<li><p><code>&lt;p&gt;</code>: 여는 태그</p>
</li>
<li><p><code>&lt;/p&gt;</code>: 닫는 태그</p>
</li>
<li><p><code>Text</code>: 내용</p>
</li>
</ul>
<h3 id="태그-속성attributes">태그 속성(Attributes)</h3>
<p>개별 태그의 기능을 확장하고 더 쉽게 관리하기 위해 <strong>속성</strong>을 사용할 수 있습니다. 속성은 태그에 추가로 정보를 제공하거나 태그의 동작이나 표현을 제어할 수 있는 설정값을 의미합니다. 속성은 이름과 값으로 구성되며 시작 태그에서 태그 이름 뒤에 공백으로 구분 후 속성 이름=&quot;속성값&quot;으로 표현합니다.</p>
<pre><code class="language-html">&lt;a href=&quot;https://developer.mozilla.org/ko/&quot;&gt;MDN Web Docs&lt;/a&gt;</code></pre>
<h2 id="html-문서-구조">HTML 문서 구조</h2>
<p>웹 브라우저는 HTML 문서 구조를 통해 HTML 버전, 문서의 제목, 정보, 내용 등을 파악합니다. HTML 문서는 일반적으로 문서 형식 정의로 시작하여 <code>&lt;html&gt;, &lt;head&gt;, &lt;body&gt;</code> 3개의 영역으로 구성됩니다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;title&gt;title&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;heading&lt;/h1&gt;
    &lt;p&gt;paragraph&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="문서-형식-정의">문서 형식 정의</h3>
<p>문서 형식 정의(Document Type Declaration)는 문서가 어떤 유형으로 작성되었는지 브라우저에게 알려줍니다. 웹 브라우저는 문서 형식 선언이 없는 HTML 문서는 쿼크 모드로, 문서 형식 선언이 있는 HTML 문서는 표준 모드로 렌더링합니다.<code>&lt;!DOCTYPE html&gt;</code>은 현재 문서가 HTML5 언어로 작성한 웹 문서를 의미합니다.</p>
<blockquote>
<p><strong>쿼크 모드</strong>(Quirks mode, 쿽스 모드)는 오래된 <a href="https://ko.wikipedia.org/wiki/%EC%9B%B9_%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80" title="웹 브라우저">웹 브라우저</a>를 위하여 디자인된 <a href="https://ko.wikipedia.org/wiki/%EC%9B%B9_%ED%8E%98%EC%9D%B4%EC%A7%80" title="웹 페이지">웹 페이지</a>의 <a href="https://ko.wikipedia.org/wiki/%ED%95%98%EC%9C%84_%ED%98%B8%ED%99%98%EC%84%B1" title="하위 호환성">하위 호환성</a>을 유지하기 위해 <a href="https://ko.wikipedia.org/wiki/W3C" title="W3C">W3C</a>나 <a href="https://ko.wikipedia.org/wiki/IETF" title="IETF">IETF</a>의 표준을 엄격히 준수하는 <strong>표준 모드</strong>(Standards Mode)를 대신하여 쓰이는 <a href="https://ko.wikipedia.org/wiki/%EC%9B%B9_%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80" title="웹 브라우저">웹 브라우저</a> 기술을 가리킨다. 같은 코드라도 웹 브라우저마다 서로 다르게 해석하므로 전혀 다른 결과물을 보여주게 된다.
<a href="https://ko.wikipedia.org/wiki/%EC%BF%BC%ED%81%AC_%EB%AA%A8%EB%93%9C">쿼크 모드 - 위키백과, 우리 모두의 백과사전</a></p>
</blockquote>
<h3 id="html-태그"><code>&lt;html&gt;</code> 태그</h3>
<p><code>&lt;html&gt;</code> 태그는 HTML 파일의 시작과 끝을 표시하며 작성된 문서가 HTML을 사용한 문서임을 나타냅니다. HTML 페이지의 루트 요소로 <code>&lt;html&gt; ~ &lt;/html&gt;</code> 사이에 모든 콘텐츠가 작성됩니다. 
<code>lang</code> 속성은 페이지의 언어에 대한 정보를 제공합니다. 이는 웹 페이지의 텍스트 내용을 올바르게 표시하도록, 검색 엔진이 다른 국가의 사용자에게 올바른 검색 결과를 표시하는데 도움을 줍니다.
기본 언어 선언이 중요한 이유는 스크린리더가 선언된 언어에 해당하는 TTS로 자동으로 전환함으로 콘텐츠를 자연스럽게 출력하도록 하기 위함입니다.</p>
<blockquote>
<p><a href="https://www.seobility.net/en/wiki/Declaring_language_in_HTML">Declaring language in HTML</a></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/code_newb/post/08f6a1bd-261b-4372-abed-2e9771680cc8/image.png" alt=""></p>
<h3 id="head-태그"><code>&lt;head&gt;</code> 태그</h3>
<p>웹 브라우저 화면에 표시되지 않고 메타데이터(metadata) 집합을 정의합니다. 검색 결과에 나타날 키워드와 페이지 설명, 외부 스타일 시트 파일 연결, 문자 집합 선언 등이 포함됩니다.</p>
<blockquote>
<p><strong>메타데이터</strong>(metadata)는 <a href="https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0" title="데이터">데이터</a>(data)에 대한 데이터이다. 이렇게 흔히들 간단히 정의하지만 엄격하게는, 캐런 코일(Karen Coyle)에 의하면 &#39;어떤 목적을 가지고 만들어진 데이터(Constructed data with a purpose)&#39;라고도 정의한다.
<a href="https://ko.wikipedia.org/wiki/%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0">메타데이터 - 위키백과, 우리 모두의 백과사전</a></p>
</blockquote>
<p><code>&lt;meta&gt;</code> 태그는 메타데이터를 정의할 때 사용합니다. 다양한 종류의 메타데이터를 제공할 때 사용되며, 브라우저와 검색 엔진이 이를 활용합니다.</p>
<h3 id="body-태그"><code>&lt;body&gt;</code> 태그</h3>
<p>실제 웹 브라우저에 표시되는 모든 콘텐츠가 <code>&lt;body&gt;</code> 내에 작성됩니다.</p>
<h2 id="reference">Reference</h2>
<ul>
<li><p><a href="https://developer.mozilla.org/ko/docs/Web/HTML">HTML: Hypertext Markup Language | MDN</a></p>
</li>
<li><p><a href="https://brunch.co.kr/@coveryou/14#comment">html 이란? 속 시원한 HTML 뜻 풀이</a></p>
</li>
<li><p><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Quirks_Mode_and_Standards_Mode">호환 모드와 표준 모드 - HTML: Hypertext Markup Language | MDN</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[인터넷의 역사]]></title>
            <link>https://velog.io/@code_newb/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%98-%EC%97%AD%EC%82%AC</link>
            <guid>https://velog.io/@code_newb/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%98-%EC%97%AD%EC%82%AC</guid>
            <pubDate>Tue, 29 Mar 2022 13:16:43 GMT</pubDate>
            <description><![CDATA[<h1 id="인터넷의-역사">인터넷의 역사</h1>
<p>1957년 이전에는 컴퓨터가 한 번에 하나의 작업만 처리(일괄 처리)할 수 있었습니다. 컴퓨터가 커지면서 열을 식히기 위해 냉각 기능이 있는 방에 배치되어야 했고 이는 더 이상 직접 컴퓨터로 작업할 수 없음을 의미했습니다. 왜냐하면 개발자는 전문가를 통해서만 컴퓨터를 사용할 수 있게 되었기 떄문입니다. 이는 많은 오류를 발생시키고 시간을 낭비하는 매우 비효율적인 방식이였습니다.</p>
<p>1957년에는 원격 연결로 컴퓨터를 직접 작업할 수 있게 되며 이와 동시에 time-sharing이라는 아이디어가 등장합니다. 컴퓨팅 파워를 분할하여 여러 사용자와 공유하고자 한 것입니다. 그리고 이 컴퓨터들을 연결시켜 서로 통신을 쉽게 하려 노력했습니다.</p>
<p>냉전시대인 1957년 10월 4일 소련은 최초의 무인 위성인 스푸트니크를 발사합니다. 스푸트니크는 모두 R-7 로켓에 의해 발사되었는데 이것은 원래 탄도 미사일 발사용으로 개발된 것입니다. 이로 인해 미국에 미사일 갭(소련과 미사일 전력의 격차)에 대한 공포가 확대되자 기술 주도권을 확보하기 위해 1958년 2월 국방고등연구계획국(ARPA, 오늘날의 DARPA)를 설립합니다.</p>
<p>DARPA는 핵공격에도 안정적인 정보 교환이 가능한 통신 시스템 연구하였습니다. 정보 전송 속도를 높이고 기존 연구를 또 연구하는 불필요한 일을 막기 위해 대규모 컴퓨터 네트워크를 만드는 것에도 계속 관심을 기울였습니다.</p>
<p><img src="https://t1.daumcdn.net/cfile/tistory/9981F93A5BECBF3B35" alt=""></p>
<p>▶ 최초의 ARPANET</p>
<p>1968년 DARPA는 ULCA-스탠퍼드-유타-UC 산타바바라 등 4개 대학을 잇는 프로젝트를 추진했으며 컴퓨터 네트워크 구축하기 위해 입찰을 공고합니다. 그 중 BBN이 자금을 제공하기로 하고 DARPA 팀과 함께 IMP와 네트워크를 구축했습니다. 이 네트워크가 바로 현재의 인터넷망의 시초인 <strong>ARPANET</strong>입니다. ARPANET은 패킷 교환을 사용했으며 전화선을 통해 패킷을 이동했습니다.</p>
<p>ARPANET에 영향을 준 다른 곳에서 연구된 중요한 개념들을 먼저 살펴보겠습니다.</p>
<ul>
<li><p>RAND Corporation</p>
<ul>
<li><p>1960년대 초반 RAND Corporation의 Paul Baran은 핵전쟁 중에도 작동할 수 있는 시스템을 연구해 왔습니다. 1964년에 그는 <strong>분산 적응형 메시지 블록 교환</strong>을 설명하는 논문을 냈습니다. 탈중앙집중적 명령 및 통제 시스템을 구축함으로써 시스템의 일부분이 파괴되더라도 전체 시스템의 손실을 최소화하고자 했습니다.</p>
</li>
<li><p>통신은 전파를 통해 이루어졌는데 이는 핵공격에 매우 취약합니다. 핵 공격이 전리층에 영향을 미쳐 장파 전파는 사용할 수 없게 됩니다.</p>
</li>
</ul>
</li>
<li><p>NPL(National Physical Laboratory)</p>
<ul>
<li><p>영국 국립물리연구소(NPL)에 의해 개발된 네트워크가 있었습니다. 이는 상업용으로 설계되었기 때문에 많은 사용자와 메시지를 주고받는 네트워크로 통선망의 혼잡이 예상되었습니다.</p>
</li>
<li><p>여기서 컴퓨터 메시지를 네트워크를 통해 독립적으로 라우팅되고 다른 경로를 통해 목적지에서 재조립되는 패킷으로 나누는 <strong>패킷 교환(packet switching)</strong> 이라는 아이디어가 등장합니다.</p>
</li>
<li><p>패킷 교환에 대한 그의 연구는 1967년 10월 운영 체제 원칙에 관한 심포지엄에서 ARPANET 개발자의 관심을 끌었고 패킷 교환 개념은 ARPANET 적용으로 이어집니다.</p>
</li>
</ul>
</li>
<li><p>Cyclades</p>
<ul>
<li><p>Cyclades 네트워크는 1970년대 초에 만들어진 프랑스 연구 네트워크입니다. 예산이 적었기 때문에 게이트웨이를 사용하지 않고 컴퓨터 간 직접적으로 연결하기로 결정하였습니다. 즉, Cyclades 프로토콜은 직접 연결을 제공하는 물리 계층을 사용하여 모든 장치들을 통과합니다.</p>
</li>
<li><p>Cyclades는 데이터그램을 사용하고 네트워크 자체가 아니라 데이터 전달을 담당하는 네트워크 호스트를 만든 최초의 네트워크였습니다. 지형이나 간섭에 의해 데이터가 중간에 유실되더라도 호스트가 메시지 전송 기록을 보관했다가 네트워크가 다시 연결되면 자동으로 재전송할 수 있게 설계되었습니다. 이것은 TCP/IP의 개발에 큰 영향을 줍니다.</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://jartigag.xyz/assets/images/posts/inter-nets.png" alt=""></p>
<blockquote>
<p>먼저 1969년 9월 클라인록이 있는 UCLA의 &#39;네트워크측정센터(Network Measurement Center)&#39;가 최초의 아르파넷 노드로 선정되었다. 한 달 후 &#39;스탠퍼드연구소(Stanford Research Institute, SRI)&#39;가 두 번째 노드로 연결되었다. SRI는 더글러스 엥겔바트(Douglas Engelbart)가 인간 지능 확장 프로젝트를 수행한 연구소로, 다르파의 &#39;네트워크정보센터(Network Information Center)&#39;를 지원, 일종의 도메인 네임 시스템인 호스트 네임 테이블을 유지, 관리하는 기능을 수행하였다.
<a href="https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;blogId=byspoets&amp;logNo=220984534946">인터넷의 역사와 ARPANET: 네이버 블로그</a></p>
</blockquote>
<p>최초의 패킷 교환은 두 번째 노드가 연결되고 1969년 10월 29일 UCLA와 스탠포드 연구소 간에 최초로 통신이 이루어집니다. 이 후 ARPANET에 연결되는 컴퓨터는 점차 증가했고 1973년에는 최초로 다른 종류의 네트워크인 캘리포니아의 알로하넷(ALOHANET)과의 연결에 성공합니다.</p>
<p>1970년대 초 당시에는 많은 컴퓨터들이 사용되고 있었지만 이는 각각의 네트워크들이 서로 달라서 통신이 원활하지 않았습니다. 1974년 TCP/IP가 이러한 문제를 해결하게 됩니다. TCP/IP는 패킷에 이름을 붙여 작은 패킷으로 쪼개진 하나의 데이터가 네트워크의 다른 경로로 가더라도 모두 목적지에 도착하여 다시 재조합될 수 있도록 합니다.</p>
<blockquote>
<p>1981년 미국 국립과학재단(NSF)이 CSNET(컴퓨터 과학망)을 개발하면서 아파넷으로의 접속이 확장되었으며 1982년 인터넷 프로토콜 스위트 (TCP/IP)가 표준화되었고 인터넷이라 불리는, 완전히 상호 연결되는 TCP/IP 네트워크의 월드 와이드 네트워크의 개념이 등장하였다.
<a href="https://ko.wikipedia.org/wiki/%EC%9D%B8%ED%84%B0%EB%84%B7%EC%9D%98_%EC%97%AD%EC%82%AC">인터넷의 역사 - 위키백과, 우리 모두의 백과사전</a></p>
</blockquote>
<p>1969년 구축되어 인터넷의 기간망 기능을 수행한 ARPANET은 1983년 연구용인 ARPANET과 군사용인 밀넷(MILNET)으로 분리됩니다. 1973년 이후 발전한 인터넷의 기본적인 통신 프로토콜 TCP/IP가 1983년에 이르러 인터넷 사용자들의 합의에 의해서 ARPANET의 유일한 통신 프로토콜이 되었고 민간용 ARPANET이 인터넷으로 바뀐후 세계적인 통신망으로 발전합니다.</p>
<br/>

<h2 id="참고자료">참고자료</h2>
<ul>
<li><p><a href="https://www.youtube.com/watch?v=9hIQjrMHTv4">History of the Internet - YouTube</a></p>
</li>
<li><p><a href="https://www.youtube.com/watch?v=21eFwbb48sE&amp;t=287s">Who Invented the Internet? And Why? - YouTube</a></p>
</li>
<li><p><a href="https://polarizedlentium.tistory.com/217">인터넷의 역사 (1) - 인터넷의 기원에 대한 논란 :: Polarized Lentium</a></p>
</li>
<li><p><a href="https://www.venturesquare.net/514020">거의 모든 인터넷의 역사 (14) - TCP/IP와 이더넷의 탄생</a></p>
</li>
<li><p><a href="https://blog.daum.net/gmania65/137">최초의 패킷교환방식 ‘아르파넷(ARPANET)’ 등장, 인터넷의 효시</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 개발 환경 구축 (TS, ESLint, Prettier)]]></title>
            <link>https://velog.io/@code_newb/React-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95</link>
            <guid>https://velog.io/@code_newb/React-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95</guid>
            <pubDate>Mon, 14 Mar 2022 05:53:19 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>VSCode 에디터를 사용하며 CRA를 이용해 TypeScript 프로젝트를 생성하고 문법 검사(ESLint)와 코드 정렬(Prettier) 환경을 구축합니다.</p>
</blockquote>
<h2 id="1-프로젝트-생성">1. 프로젝트 생성</h2>
<p><code>npx create-react-app 프로젝트명 --template typescript</code><img src="https://images.velog.io/images/code_newb/post/90244b94-9764-40cf-a85e-3177acd826a4/image.png" alt="">▶ 생성된 프로젝트</p>
<h2 id="2-vscode-확장-프로그램-설치">2. VSCode 확장 프로그램 설치</h2>
<h3 id="eslint-자바스크립트-문법-유효성-검사-도구">ESLint: 자바스크립트 문법 유효성 검사 도구</h3>
<p>VSCode ESLint 설치
<img src="https://images.velog.io/images/code_newb/post/b40e1bc9-3380-474d-ad39-3d5502cb29c4/image.png" alt=""></p>
<h3 id="prettier-코드-자동-정렬-도구">Prettier: 코드 자동 정렬 도구</h3>
<p>VSCode Prettier 설치
<img src="https://images.velog.io/images/code_newb/post/be327645-b15f-4f41-86d5-dae4a61573ee/image.png" alt=""></p>
<h2 id="3-setup">3. Setup</h2>
<p><strong>패키지 설치</strong></p>
<pre><code>$ npm i -D eslint prettier typescript
$ npm i -D @typescript-eslint/parser @typescript-eslint/eslint-plugin 
$ npm i -D eslint-plugin-prettier eslint-config-prettier
$ npm i -D eslint-plugin-react eslint-plugin-react-hooks</code></pre><h3 id="eslint">ESLint</h3>
<pre><code>📄 .eslintrc 파일 생성(최상위 폴더에)

{
  &quot;parser&quot;: &quot;@typescript-eslint/parser&quot;,
  &quot;env&quot;: {
    &quot;browser&quot;: true,
    &quot;node&quot;: true
  },
  &quot;extends&quot;: [
    &quot;plugin:@typescript-eslint/eslint-recommended&quot;,
    &quot;plugin:@typescript-eslint/recommended&quot;,
    &quot;plugin:@typescript-eslint/recommended-requiring-type-checking&quot;,
    &quot;plugin:prettier/recommended&quot;,
    &quot;prettier&quot;
  ],
  &quot;plugins&quot;: [&quot;@typescript-eslint&quot;, &quot;react-hooks&quot;],
  &quot;rules&quot;: {
    &quot;prettier/prettier&quot;: 0
  },
  &quot;settings&quot;: {
    &quot;react&quot;: {
      &quot;version&quot;: &quot;detect&quot;
    }
  },
  &quot;overrides&quot;: [
    {
      &quot;files&quot;: [&quot;*.js&quot;, &quot;*.ts&quot;, &quot;*.tsx&quot;],
      &quot;parserOptions&quot;: {
        &quot;project&quot; : [&quot;./tsconfig.json&quot;]
      }
    }
  ]
}</code></pre><h3 id="prettier">Prettier</h3>
<pre><code>📄 .prettierrc 파일 생성(최상위 폴더에)

{
  &quot;trailingComma&quot;: &quot;all&quot;,
  &quot;tabWidth&quot;: 2,
  &quot;semi&quot;: true,
  &quot;singleQuote&quot;: true,
  &quot;printWidth&quot;: 120,
  &quot;parser&quot;: &quot;typescript&quot;
}</code></pre><p><strong>저장한 후 자동으로 정렬이 되지 않는다면?</strong></p>
<p><code>설정(Settings) - 텍스트 편집기(Text Editor) - 서식(Formatting) 혹은 format on save 검색</code></p>
<p><strong>format on save 체크</strong>
<img src="https://images.velog.io/images/code_newb/post/188f8ee2-5405-4dac-97ce-4ab58787b418/image.png" alt=""></p>
<p><code>설정(Settings) - 텍스트 편집기(Text Editor) 혹은 formatter 검색</code></p>
<p><strong>Default Formatter: Prettier로 변경</strong>
<img src="https://images.velog.io/images/code_newb/post/4ae7f3ef-844d-4244-a4b9-ddbae469d1b5/image.png" alt=""></p>
<h2 id="reference">Reference</h2>
<p><a href="https://create-react-app.dev/docs/adding-typescript/">Adding TypeScript | Create React App</a>
<a href="https://prettier.io/docs/en/install.html#set-up-your-editor">Install - Prettier</a>
<a href="https://eslint.org/blog/2019/01/future-typescript-eslint">The future of TypeScript on ESLint</a>
<a href="https://seonghui.github.io/blog/2020/12/27/typescript-eslint-prettier/">Typescript 프로젝트에 ESLint, Prettier 적용하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] ES6+ 기본 문법]]></title>
            <link>https://velog.io/@code_newb/JavaScript-ES6-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@code_newb/JavaScript-ES6-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Sat, 30 Oct 2021 13:22:32 GMT</pubDate>
            <description><![CDATA[<h2 id="꼭-알아야-할-es6-문법">꼭 알아야 할 ES6+ 문법</h2>
<h3 id="상수변수-선언">상수/변수 선언</h3>
<p>var 대신에 const 혹은 let을 사용 -&gt;  block scope</p>
<ul>
<li>const: 재할당 불가. 내부 속성값은 수정가능 (상수)<ul>
<li>변수가 object일 때 내부 속성을 바꾸는 것은 가능</li>
</ul>
</li>
<li>let: Lexical Variable Scoping을 지원하는 변수 선언 문법</li>
</ul>
<p><strong>호이스팅</strong> </p>
<blockquote>
<p>JavaScript에서 <strong>호이스팅</strong>(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다. <code>var</code>로 선언한 변수의 경우 호이스팅 시 <code>undefined</code>로 변수를 초기화합니다. 반면 <code>let</code>과 <code>const</code>로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다.
<a href="https://developer.mozilla.org/ko/docs/Glossary/Hoisting">https://developer.mozilla.org/ko/docs/Glossary/Hoisting</a></p>
</blockquote>
<pre><code>console.log(name)

var name = &#39;test&#39;;

console.log(name);

// 결과
&gt; undefined
&gt; test</code></pre><p>const, let을 사용하면 호이스팅 X</p>
<h3 id="object-선언">Object 선언</h3>
<p>tom1 === tom2</p>
<pre><code class="language-js">let tom1 = {
    name: &quot;Tom&quot;,
    age: 10,
    region: &quot;Seoul&quot;,
}

let tom2 = {
    &quot;name&quot;: &quot;Tom&quot;,
    &quot;age&quot;: 10,
    &quot;region&quot;: &quot;Seoul&quot;,
}</code></pre>
<p><strong>Key 게산이 필요한 경우</strong></p>
<pre><code class="language-js">const tom2 = {
     &quot;name&quot;: &quot;Tom&quot;,
    &quot;age&quot;: 10,
    &quot;region&quot;: &quot;Seoul&quot;
    [&quot;score&quot; + &quot;1&quot;]: 100,
}</code></pre>
<p><strong>단축 속성명</strong></p>
<p>tom1 === tom2</p>
<pre><code class="language-js">let name = &quot;Tom&quot;;
let age = 10;

let tom1 = {
    name: name,
    age: age,
    print: function() {
        console.log(`name: ${this.name}, age: ${this.age}`);
    }
};

let tom2 = {
    name,
    age,
    print() {
        console.log(`name: ${this.name}, age: ${this.age}`);
    }
};</code></pre>
<h3 id="객체-복사">객체 복사</h3>
<p>JS는 Object/Array에 대해서는 대입 시에 얕은 복사 (Shallow Copy)</p>
<pre><code class="language-js">const obj1 = { value1: 10 };
const obj2 = obj1;
const obj3 = JSON.parse(JSON.stringify(obj1)) // 깊은 복사

obj1.value1 += 1;

console.log(`obj1:`, obj1);
console.log(`obj2:`, obj2);
console.log(`obj3:`, obj3);</code></pre>
<p><strong><code>JSON.parse()</code></strong> 메서드는 JSON 문자열의 구문을 분석하고, 그 결과에서 JavaScript 값이나 객체를 생성합니다.</p>
<p><strong><code>JSON.stringify()</code></strong> 메서드는 JavaScript 값이나 객체를 JSON 문자열로 변환</p>
<h3 id="template-literals">Template Literals</h3>
<blockquote>
<p>템플릿 리터럴은 내장된 표현식을 허용하는 문자열 리터럴입니다. 여러 줄로 이뤄진 문자열과 문자 보간기능을 사용할 수 있습니다.
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals</a></p>
</blockquote>
<p>Multi-line string</p>
<p>String Interpolation</p>
<p>`string text ${expression} string text`</p>
<p>백틱(`) 사용</p>
<h3 id="배열-비구조화-array-destructuring">배열 비구조화 (Array Destructuring)</h3>
<pre><code class="language-js">let [name] = [&quot;Tom&quot;, 10,&quot;Seoul&quot;] // &quot;Tom&quot; 대입

let [, age,] = [&quot;Tom&quot;, 10, &quot;Seoul&quot;] // 10만 대입

let [name, age, region, height] = [&quot;Tom&quot;, 10, &quot;Seoul&quot;] // height 값은 undefined

let [name, age, region, height=150] = [&quot;Tom&quot;, 10, &quot;Seoul&quot;] // height 디폴트값 할당</code></pre>
<h2 id="객체-비구조화-object-destructuring">객체 비구조화 (Object Destructuring)</h2>
<pre><code class="language-js">const tom = {
    name: &quot;Tom&quot;,
    age: 10,
    region: &quot;Seoul&quot;
}

const { age, name, height } = tom;
// 객체에서 필요한 값들만 추출, height는 undefined

const print_person = ({ name }) =&gt; {
    console.log(name)
}</code></pre>
<pre><code class="language-js">const person = {
    name: &quot;Tom&quot;,
    age: 10,
    region: {
        country: &#39;서울&#39;,
        postcode:&#39;06222&#39;
    }
}

// region은 할당되지 않고 경로로만 사용된 것
const { name, region: { postcode }} = person</code></pre>
<h3 id="전개-연산자-spread-operator">전개 연산자 (Spread Operator)</h3>
<pre><code class="language-js">const tom = {
    name: &quot;Tom&quot;,
    age: 10,
    region: &quot;Seoul&quot;
}let [name, ...rest] = [&quot;Tom&quot;, 10, &quot;Seoul&quot;] // name에는 &quot;Tom&quot;, rest에는 나머지 인자가 대입(Array)

// 여러 개의 인자를 전달받을 때 
let printArgs = (...args) =&gt; {
    console.log(args)
}

// 
const tom = {
    name: &quot;Tom&quot;,
    age: 10,
    region: &quot;Seoul&quot;
}

// 속성명이 중복될 경우, 마지막 값이 대입
const steve = {
    ...tom,
    name: &quot;Steve&quot;
}</code></pre>
<p><strong>리액트에서는 수많은 값들을 <a href="https://ko.wikipedia.org/wiki/%EB%B6%88%EB%B3%80%EA%B0%9D%EC%B2%B4">불변객체</a>로서 처리</strong></p>
<p>👉 <strong>Spread Operator</strong> </p>
<h3 id="함수--default-parameters">함수 / Default Parameters</h3>
<p>모든 타입의 값들을 디폴트 파라미터로 지정할 수 있다</p>
<pre><code class="language-js">function hello(name=&quot;Tom&quot;, age=10) {
    console.log(`나느 ${name}. ${age} 살`)
}

const get_default_age = () =&gt; 10

function hello(name=&quot;Tom&quot;, age=get_default_age()) {
    console.log(`나느 ${name}. ${age} 살`)
}</code></pre>
<p>디폴트 값에 함수를 적용할 경우</p>
<p>👉 자바스크립트에서는 값이 필요할 때 호출</p>
<h3 id="함수--named-parameters">함수 / Named Parameters</h3>
<p>객체 비구조화를 활용</p>
<pre><code class="language-js">function print_person1(name, age, region) {
    console.log(&#39;1&gt;&#39;, name, age, region)
}
print_person1(&#39;Tom&#39;, 10, &#39;Seoul&#39;) // Index에 맞게 대입

function print_person2({ name, age, region }) {
    console.log(&#39;2&gt;&#39;, name, age, region)
}
print_person2({ name: &#39;Tom&#39;, age: 10, region: &#39;Seoul&#39; })</code></pre>
<h3 id="함수--arrow-function">함수 / Arrow Function</h3>
<p>return을 사용하지 않아도, 계산된 값을 반환</p>
<p>인자가 1개일 경우, 소괄호 생략 가능</p>
<pre><code class="language-js">let hello1 = (name, age) =&gt; {
    return `안녕. 나는 ${name}. ${age}이야.`;
}

// 함수를 중괄호로 감싸지 않으면, return 문을 쓰지 않아도 반환값으로 사용
let hello2 = (name, age) =&gt; `안녕. 나는 ${name}. ${age}이야.`;</code></pre>
<p><strong>this와 arguments를 바인딩하지 않음</strong></p>
<p>모든 객체에는 this가 존재</p>
<pre><code class="language-js">var tom = {
    name: &quot;Tom&quot;,
    print1: function() {
        console.log(`[print1-1] name: ${this.name}`)
        (function() {
            // 내부 function의 this로 변경
            console.log(`[print1-2] name: ${this.name}`)
        })
    }
}

&gt; [print1-1] name: Tom
&gt; [print1-2] name: undefined</code></pre>
<h3 id="함수--다양한-형태">함수 / 다양한 형태</h3>
<pre><code class="language-js">const mysum1 = (x, y) =&gt; x + y;
const mysum1 = (x, y) =&gt; x + y;
const mysum1 = (x, y) =&gt; ({x: x,  y: y}); // 콜론으로 인해, 소괄호 필요 (함수로 인지하기 때문)
const mysum1 = (x, y) =&gt; {
    return {x: x, y: y}
}</code></pre>
<h3 id="콜백지옥"><a href="callbackhell.com">콜백지옥</a></h3>
<p>비동기 개발을 할 때 많이 사용하는 기법 </p>
<h3 id="u콜백u---promise---asyncawait"><u>콜백</u> -&gt; Promise -&gt; async/await</h3>
<pre><code class="language-js">const fs = require(&#39;fs&#39;)

fs.readdir(&#39;.&#39;, function (err, files) {
    if (err) {
        cosole.log(&#39;Error finding files: &#39; + err)
    } else {
        console.log(files);
    }
})

// 위 fs.readdir이 끝나기 전에 수행
console.log(&quot;ENDED&quot;)</code></pre>
<h3 id="콜백---upromiseu---asyncawait">콜백 -&gt; <u>Promise</u> -&gt; async/await</h3>
<pre><code>const fs = require(&#39;fs&#39;)
const fsPromises = fs.promises

fsPromises.readdir(&#39;.&#39;)
    .then(files =&gt; {
        cosole.log(&#39;Error finding files: &#39; + err)
    })
    .catch(err =&gt; console.error(err))
})

// 위 fsPromises.readdir이 끝나기 전에 수행
console.log(&quot;ENDED&quot;)</code></pre><h3 id="콜백---promise---uasyncawaitu">콜백 -&gt; Promise -&gt; <u>async/await</u></h3>
<p>ES8 (ECAM 2017) 부터 지원
await : promise의 then을 기다림 (await를 사용하면 함수는 항상 async)
비동기이지만 동기적인 방식으로 이해할 수 있는 로직</p>
<pre><code class="language-js">const fs = require(&#39;fs&#39;)
const fsPromises = fs.promises

async function fn() {
    try {
        let files = await fsPromises.readdir(&#39;.&#39;);
        console.log(files);
    }
    catch(err) {
        console.error(err)
    }
}

fn() // async 함수이기에,완료 전에 다음 로직이 동작

console.log(&quot;ENDED&quot;)</code></pre>
<h3 id="모듈-시스템">모듈 시스템</h3>
<p>예전 웹 상의 자바스크립트에서는 script 태그를 통해서만 로딩</p>
<p>2가지 모듈 시스템</p>
<ul>
<li>CommonJS Module: nodejs에서 주로 활용</li>
<li>ES6 Module: 리액트에서 주로 활용</li>
</ul>
<h3 id="모듈--es6-module">모듈 / ES6 module</h3>
<p>IE를 포함한 구형 브라우저에서는 미지원</p>
<p>node 이후에 ES6 Module이 나왔기에, node에서는 왠만한 ES6 문법은 지원하지만, 모듈은 ES6 module 지원하지 않고, CommonJS만을 지원</p>
<p>문법: export, import </p>
<h3 id="모듈--commonjs">모듈 / CommonJS</h3>
<p>node에서 지원하는 일반적인 모듈 패턴
문법: module.export, require</p>
<h3 id="고차-함수-high-order-function">고차 함수 (High Order Function)</h3>
<p>함수를 인자로 받거나 반환이 가능하고, 다른 함수를 조작하는 함수
함수/클래스 역시 모두 객체</p>
<h2 id="reference">Reference</h2>
<p>📗 <a href="https://www.zerocho.com/category/JavaScript/post/5740531574288ebc5f2ba97e">(JavaScript) 함수의 범위(scope) - Lexical Scoping</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] CSS 적용하기 ]]></title>
            <link>https://velog.io/@code_newb/React-styled-components-CSS-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@code_newb/React-styled-components-CSS-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 20 Oct 2021 15:43:30 GMT</pubDate>
            <description><![CDATA[<h1 id="css-적용하기">CSS 적용하기</h1>
<h2 id="styled-components">styled-components</h2>
<p><code>npm i styled-components</code></p>
<p>styled-components는 style이 적용된 Component를 생성</p>
<h3 id="component-스타일링">component 스타일링</h3>
<p><strong>Component의 props를 전달받아 조건부로 사용 가능</strong></p>
<pre><code class="language-jsx">📄 App.jsx

import React from &#39;react&#39;;
import styled from &#39;styled-components&#39;;

const Button = styled.button`
  width: 50px;
  padding: 1rem;
  background-color: ${props =&gt; props.delete ? &quot;red&quot; : &quot;blue&quot;}
  &amp;:active {    // 의사 클래스(가상 클래스) css 적용
    box-shadow: 1px 1px 1px;
  }
`

const App = () =&gt; {
  return (
    &lt;Button&gt;Create&lt;/Button&gt;
    &lt;Button delete&gt;Delete&lt;/Button&gt;
  );
}

export default App;</code></pre>
<h3 id="확장-스타일링-feat-antd">확장 스타일링 (feat. antd)</h3>
<p><strong>기존 Component에 스타일을 추가</strong></p>
<pre><code class="language-jsx">📄 App.jsx

import React from &#39;react&#39;;
import { Input } from &#39;antd&#39;;
import &#39;antd/dist/antd.css&#39;;

const MyInput = styled(Input)`
  margin: 16px;
  &amp;:disabled {
    ${(props) =&gt; (props.valid === &#39;invalid&#39; ? &#39;background: #ccc&#39; : null)}
`;

const App = () =&gt; {
  return (
    &lt;MyInput 
      type=&quot;email&quot;
      id=&quot;email&quot;
      name=&quot;email&quot;
      value={email}
      onChange={onChangeEmail}
      placeholder=&quot;이메일 입력&quot;
      required
      valid=&quot;invalid&quot; 
    /&gt;
  )
}</code></pre>
<h3 id="-부분적으로-component에-스타일-적용">(+) 부분적으로 Component에 스타일 적용</h3>
<p><strong>css 파일을 생성하여 선언한 뒤 className으로 적용</strong></p>
<pre><code class="language-jsx">📄 App.css
.mb-4 {
  margin-bottom: 4px;
}


📄 App.jsx
import React from &#39;react&#39;;
import styled from &#39;styled-components&#39;;

const Button = styled.button`
  width: 50px;
  padding: 1rem;
  background-color: ${props =&gt; props.delete ? &quot;red&quot; : &quot;blue&quot;}
`

const App = () =&gt; {
  return (
    &lt;Button className=&quot;mb-4&quot;&gt;Create&lt;/Button&gt;
    &lt;Button delete=&quot;delete&quot;&gt;Delete&lt;/Button&gt;
  );
}

export default App;</code></pre>
<h2 id="📗-reference">📗 Reference</h2>
<p><strong><a href="https://react.vlpt.us/styling/03-styled-components.html">03. styled-components</a></strong>
<strong><a href="https://dkje.github.io/2020/10/13/StyledComponents/">[React] Styled Components 사용기</a></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 프론트엔드 세팅하기]]></title>
            <link>https://velog.io/@code_newb/React-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@code_newb/React-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 14 Sep 2021 09:45:47 GMT</pubDate>
            <description><![CDATA[<h1 id="react-개발환경-세팅">React 개발환경 세팅</h1>
<p>VSCode + CRA + JavaScript 를 기반으로 한 세팅입니다.</p>
<h2 id="1-프로젝트-생성">1. 프로젝트 생성</h2>
<p><a href="https://velog.io/@code_newb/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%B9%98-vscode">CRA를 이용한 프로젝트 생성(권장)</a></p>
<h2 id="2-확장-프로그램-설치--설정">2. 확장 프로그램 설치 &amp; 설정</h2>
<p>VSCode 편집기에서 제공하는 플러그인을 설치하여 사용합니다.</p>
<h3 id="prettier-코드-자동-정렬-도구">Prettier: 코드 자동 정렬 도구</h3>
<p><strong>VSCode Prettier 설치</strong>
<code>npm i -D prettier eslint-plugin-prettier eslint-config-prettier</code>
<img src="https://images.velog.io/images/code_newb/post/4071cb38-0c53-49e6-b349-1468c15b0268/image.png" alt=""></p>
<pre><code>📄 .prettierrc    // 프로젝트 루트 폴더에 생성

{
  &quot;printWidth&quot;: 120,        // 줄 바꿈할 줄 길이
  &quot;tabWidth&quot;: 2,        // 탭 너비
  &quot;singleQuote&quot;: true,        // 작은 따옴표 사용
  &quot;trailingComma&quot;: &quot;all&quot;,    // 후행 콤마 사용 (https://heygyun.tistory.com/49)
  &quot;semi&quot;: true            // 세미콜론 사용 여부
}
</code></pre><h3 id="eslint-자바스크립트-문법-유효성-검사-도구">ESLint: 자바스크립트 문법 유효성 검사 도구</h3>
<p><strong>VSCode ESLint 설치</strong>
<code>npm i -D eslint</code><img src="https://images.velog.io/images/code_newb/post/156ea30d-a81a-4f21-bbf2-fb5c0bc53881/image.png" alt=""></p>
<blockquote>
<p>🚨 <strong>Error: Parsing error: Unexpected token &lt; eslint</strong>
원인: ESLint가 ES6 이상을 파싱할 때 생기는 문제 
ESLint는 구문 분석을 위해 기본적으로 Espree 파서를 사용 
해결: babel-eslint 패키지를 설치 <code>npm install babel-eslint</code>
.eslintrc 파일에 <code>&quot;parser&quot;: &quot;babel-eslint&quot;</code> 추가
<br>🚨 <strong>Error: Delete <code>␍</code>eslint prettier/prettier</strong>
원인 &amp; 해결: <a href="https://codingcoding.tistory.com/175">https://codingcoding.tistory.com/175</a>
<br>🚨 <strong>The react-scripts package provided by Create React App requires a dependency:
  &quot;eslint&quot;: &quot;^7.32.0&quot;</strong>
  원인: React 프로젝트에서 요구하는 버전과 맞지 않아서 발생한 에러 (설치된 eslint 버전은 8.3.0 - 21.11.25 기준) 
  해결: eslint 버전을 낮추어 설치 <code>npm i -D eslint@7.32.0</code></p>
</blockquote>
<pre><code>📄 .eslintrc    // 프로젝트 루트 폴더에 생성

{
  &quot;extends&quot;: [&quot;plugin:prettier/recommended&quot;, &quot;react-app&quot;],
  &quot;parserOptions&quot;: {
    &quot;sourceType&quot;: &quot;module&quot;,
    &quot;ecmaVersion&quot;: 2021
  },
  &quot;rules&quot;: {
    &quot;prettier/prettier&quot;: [&quot;error&quot;, {
      &quot;endOfLine&quot;:&quot;auto&quot;
     }]
  }
}
</code></pre><h3 id="reactjs-code-snippets-react-관련-템플릿을-단축키로-작성">Reactjs code snippets: React 관련 템플릿을 단축키로 작성</h3>
<p><img src="https://images.velog.io/images/code_newb/post/4014da03-8ccf-4616-8f94-c822c6d6d0e5/image.png" alt=""> <a href="https://marketplace.visualstudio.com/items?itemName=xabikos.ReactSnippets">참고: Reactjs code snippets - Visual Studio Marketplace</a></p>
<p>파일 생성 후 <code>rsc + Tap</code> 하면 함수형 컴포넌트 기본형을 자동으로 생성해줍니다.</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;

const App = () =&gt; {
  return (
    &lt;div&gt;

    &lt;/div&gt;
  );
};

export default App;</code></pre>
<h2 id="3-폴더-구조와-라우터-설정">3. 폴더 구조와 라우터 설정</h2>
<h3 id="리액트-폴더-구조">리액트 폴더 구조</h3>
<p><strong>함수형 컴포넌트 기반 (+hooks)</strong></p>
<pre><code>📁 Project
ㄴ 📁 components    // 리액트 컴포넌트
ㄴ 📁 hooks        // 리액트 hook
ㄴ 📁 layouts        // 공통 레이아웃
   ㄴ App.jsx
ㄴ 📁 pages        // 서비스 페이지(페이지 진입점)
ㄴ 📁 utils        // 자주 쓰이는 함수</code></pre><p>위의 폴더 구조는 고정적인 것이지 않고 자유롭게 설정하셔도 됩니다.
<a href="https://ko.reactjs.org/docs/faq-structure.html">(+) React 프로젝트 구조를 설계하기 위해 추천할 만한 방법이 있을까요?</a></p>
<h3 id="라우터-설정">라우터 설정</h3>
<p><code>npm i react-router react-router-dom</code></p>
<pre><code class="language-jsx">📄 App.jsx

import React from &#39;react&#39;;
import LogIn from &#39;../pages/LogIn&#39;;
import SignUp from &#39;../pages/SignUp&#39;;
import { BrowserRouter, Switch, Route } from &#39;react-router-dom&#39;;

const App = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;Switch&gt;
        &lt;Route exact path=&quot;/&quot; component={LogIn} /&gt;
        &lt;Route path=&quot;/signUp&quot; component={SignUp} /&gt;
      &lt;/Switch&gt;
    &lt;/BrowserRouter&gt;
  );
};

export default App;</code></pre>
<h3 id="절대경로-설정">절대경로 설정</h3>
<p><code>npm i @craco/craco craco-alias</code></p>
<pre><code class="language-json">📄 package.json 수정

&quot;scripts&quot;: {
  &quot;start&quot;: &quot;craco start&quot;,
  &quot;build&quot;: &quot;craco build&quot;,
  &quot;test&quot;: &quot;craco test&quot;,
  &quot;eject&quot;: &quot;react-scripts eject&quot;
},</code></pre>
<hr>
<pre><code class="language-json">📄 jsconfig.json 생성    // 프로젝트 루트 폴더에 생성

{
  &quot;compilerOptions&quot;: {
      &quot;baseUrl&quot;: &quot;src&quot;,
      &quot;paths&quot;: {
        &quot;@components/*&quot;: [&quot;src/components/*&quot;],
        &quot;@layouts/*&quot;: [&quot;src/layouts/*&quot;],
        &quot;@pages/*&quot;: [&quot;src/pages/*&quot;],
        &quot;@utils/*&quot;: [&quot;src/utils/*&quot;],
        &quot;@hooks/*&quot;: [&quot;src/hooks/*&quot;]
      }
  },
  &quot;include&quot;: [
      &quot;src&quot;
  ]
}</code></pre>
<hr>
<pre><code class="language-js">📄 craco.config.js 생성    // 프로젝트 루트 폴더에 생성

const CracoAlias = require(&#39;craco-alias&#39;);
module.exports = {
  plugins: [
    {
      plugin: &#39;CracoAlias&#39;,
      options: {
        source: &#39;jsconfig&#39;,
        jsConfigPath: &#39;jsconfig.paths.json&#39;,
      },
    },
  ],
};</code></pre>
<h2 id="4-코드-스플리팅-절대경로-적용">4. 코드 스플리팅 (절대경로 적용)</h2>
<p><code>npm i @loadable/component</code></p>
<pre><code class="language-jsx">📄 App.jsx

import React from &#39;react&#39;;
import loadable from &#39;@loadable/component&#39;;
import { BrowserRouter, Switch, Route } from &#39;react-router-dom&#39;;

const LogIn = loadable(() =&gt; import(&#39;@pages/LogIn&#39;));
const SignUp = loadable(() =&gt; import(&#39;@pages/SignUp&#39;));

const App = () =&gt; {
  return (
    &lt;BrowserRouter&gt;
      &lt;Switch&gt;
        &lt;Route exact path=&quot;/&quot; component={LogIn} /&gt;
        &lt;Route path=&quot;/signUp&quot; component={SignUp} /&gt;
      &lt;/Switch&gt;
    &lt;/BrowserRouter&gt;
  );
};

export default App;</code></pre>
<h1 id="reference">Reference</h1>
<p>📗 <a href="https://prettier.io/docs/en/options.html">Options - Prettier</a>
📗 <a href="https://tech.kakao.com/2019/12/05/make-better-use-of-eslint/">ESLint 조금 더 잘 활용하기</a>
📗 <a href="https://velog.io/@kyusung/eslint-config-2">ESLint 설정 살펴보기</a>
📗 <a href="https://velopert.com/3417">react-router :: 1장. 리액트 라우터 사용해보기</a>
📗 <a href="https://velog.io/@velopert/react-code-splitting">리액트 프로젝트 코드 스플리팅 정복하기</a>
📗 <a href="https://grahams.tistory.com/314">[react.js]CRA v4에서 절대경로 설정하기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 개발 환경 구축 (Webpack, Babel)]]></title>
            <link>https://velog.io/@code_newb/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95-Webpack-Babel</link>
            <guid>https://velog.io/@code_newb/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95-Webpack-Babel</guid>
            <pubDate>Thu, 12 Aug 2021 13:44:02 GMT</pubDate>
            <description><![CDATA[<h2 id="vscode--webpackbabel을-이용한-리액트-개발-환경-구축">vscode &amp; Webpack/Babel을 이용한 리액트 개발 환경 구축</h2>
<h3 id="1-nodejs-vscode-설치">1. Node.js, VSCode 설치</h3>
<ul>
<li><p>Node.js 최신 버전으로 설치</p>
<blockquote>
<p><strong>Node.js 왜 설치하나요?</strong> 
Node.js는 Chrome의 V8 JavaScript 엔진을 기반으로 하는 JavaScript 런타임 입니다. - <a href="https://nodejs.org/en/">Node.js 공식 사이트</a>
쉽게 말해, Node.js는 브라우저 밖에서도 자바스크립트를 실행할 수 있게 해주는 런타임 환경입니다. 앞으로 사용할 <a href="https://ko.wikipedia.org/wiki/Npm_(%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4)">npm</a>은 Node.js의 패키지 관리 도구.</p>
</blockquote>
</li>
<li><p><a href="https://code.visualstudio.com/download">Visual Studio Code (VSCode)</a></p>
<h3 id="2-프로젝트-생성-및-초기화">2. 프로젝트 생성 및 초기화</h3>
<p>컴퓨터에 원하는 위치에 폴더 하나를 생성하고 vscode를 실행하여 파일 ➡ 폴더 열기 ➡ 생성한 폴더 선택</p>
</li>
</ul>
<p>터미널에서 <code>npm init</code> 명령을 실행 (Node.js 프로젝트 폴더로 선언한다는 의미) 👉 package.json 파일이 생성됩니다.
(package name, author, license만 작성하고 나머지는 enter 했습니다)</p>
<blockquote>
<p>🧾 <strong>package.json</strong>
프로젝트 정보와 패키지 버전 정보를 담고 있는 파일
참고: (<a href="https://heropy.blog/2018/02/18/node-js-npm/">https://heropy.blog/2018/02/18/node-js-npm/</a>)
<br><strong>📁 node_modules</strong>
패키지를 설치했을 때 실제 소스코드가 들어있는 폴더</p>
</blockquote>
<pre><code>📃 package.json

{
  &quot;name&quot;: &quot;test&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
  },
  &quot;author&quot;: &quot;cs&quot;,
  &quot;license&quot;: &quot;MIT&quot;
}
</code></pre><h3 id="3-웹팩--리액트-패키지-설치하기">3. 웹팩 &amp; 리액트 패키지 설치하기</h3>
<blockquote>
<p>*<em>웹팩이란? *</em>
최신 프런트엔드 프레임워크에서 가장 많이 사용되는 모듈 번들러(Module Bundler)입니다. 모듈 번들러란 웹 애플리케이션을 구성하는 자원(HTML, CSS, Javscript, Images 등)을 모두 각각의 모듈로 보고 이를 조합해서 병합된 하나의 결과물을 만드는 도구를 의미합니다. - <a href="https://joshua1988.github.io/webpack-guide/webpack/what-is-webpack.html">https://joshua1988.github.io/webpack-guide/webpack/what-is-webpack.html</a></p>
</blockquote>
<p><code>npm i -D webpack webpack-cli</code> 👉 웹팩 설치 </p>
<ul>
<li><code>webpack</code> : 웹팩 </li>
<li><code>webpacK-cli</code> : CLI에서 웹팩 사용가능</li>
</ul>
<p><code>npm i react react-dom</code> 👉 리액트 패키지 설치</p>
<ul>
<li><code>react</code> : 리액트 기본 요소</li>
<li><code>react-dom</code> : react와 DOM 연결</li>
</ul>
<p>npm을 사용해 리액트 패키지를 설치하지 않으면 CDN을 사용해 html 파일에 스크립트를 추가해야 합니다.</p>
<pre><code class="language-html"> &lt;script src=&quot;https://unpkg.com/react@17/umd/react.development.js&quot; crossorigin&gt;&lt;/script&gt;
 &lt;script src=&quot;https://unpkg.com/react-dom@17/umd/react-dom.development.js&quot; crossorigin&gt;&lt;/script&gt;</code></pre>
<h3 id="4-바벨-설치">4. 바벨 설치</h3>
<blockquote>
<p><strong>Babel이란?</strong>
현재 및 이전 브라우저 또는 환경에서 ECMAScript 2015+ 코드를 이전 버전의 JavaScript로 변환하는 데 주로 사용되는 도구 체인입니다. - <a href="https://babeljs.io/docs/en/">https://babeljs.io/docs/en/</a></p>
</blockquote>
<p><code>const element = &lt;h1&gt;Hello, world!&lt;/h1&gt;;</code>
자바스크립트에서 html 태그를 쓰는 것은 문법적으로 가능하지 않습니다. Babel은 이와 같은 <a href="https://ko.reactjs.org/docs/introducing-jsx.html">JSX</a> 구문을 자바스크립트 문법으로 변환할 수 있습니다.</p>
<p><code>npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader</code></p>
<ul>
<li><code>babel/core</code> : 바벨의 기본 요소</li>
<li><code>babel/preset-env</code> : 브라우저에 맞게 최신 문법을 예전 문법으로 변환(지원)</li>
<li><code>babel/preset-react</code> :  JSX 지원</li>
<li><code>babel-loader</code> : 바벨과 웹팩을 연결<h3 id="5-웹팩-설정">5. 웹팩 설정</h3>
루트 경로에 <code>webpack.config.js</code> 웹팩 설정 파일 생성<h4 id="mode">mode</h4>
<code>mode</code> 속성을 정의하면 웹팩의 실행 모드가 설정됩니다. 각 실행 모드에 따라 웹팩의 결과물 모습이 달라집니다.</li>
<li><code>none</code> : 모드 설정 X</li>
<li><code>development</code> : 개발용</li>
<li><code>production</code> : 배포용 (default)</li>
</ul>
<h4 id="devtool">devtool</h4>
<p>이 옵션은 소스 맵이 생성되는지 여부와 생성 방법을 제어합니다. 소스 맵(Source Map)이란 배포용으로 빌드한 파일과 원본 파일을 서로 연결시켜주는 기능입니다. <code>devtool</code> 속성을 추가하고 <a href="(https://webpack.js.org/configuration/devtool/#devtool)">소스 맵 설정 옵션</a> 중 하나를 선택해 지정할 수 있습니다.</p>
<h4 id="entry">entry</h4>
<p>웹팩이 파일을 읽어들이기 시작하는 부분(진입점)입니다. 웹팩은 entry에 명시된 파일을 통해 의존하는 다른 모듈과 라이브러리를 알아내 하나의 번들 파일을 만들어냅니다.</p>
<h4 id="loader">loader</h4>
<p>로더(Loader)는 웹팩이 웹 애플리케이션을 해석할 때 자바스크립트 파일이 아닌 웹 자원(HTML, CSS, Images, 폰트 등)들을 변환할 수 있도록 도와주는 속성입니다.</p>
<ul>
<li><code>test</code> : 로더를 적용할 파일 유형 (일반적으로 정규 표현식 사용)</li>
<li><code>use</code> : 해당 파일에 적용할 로더의 이름</li>
</ul>
<h4 id="plugins">plugins</h4>
<p>웹팩에 적용할 플러그인들을 설정합니다. 플러그인(plugin)은 웹팩의 기본적인 동작에 추가적인 기능을 제공하는 속성입니다. </p>
<h4 id="output">output</h4>
<p>결과물의 파일 경로를 의미합니다. <code>filename</code> 속성은 웹팩으로 빌드한 파일의 이름을 의미하고, <code>path</code> 속성은 해당 파일의 경로를 의미합니다.</p>
<pre><code class="language-js">📃 webpack.config.js

const path = require(&#39;path&#39;) // Node.js 에서 파일을 쉽게 다룰 수 있도록 도와주는 모듈

module.exports = {
  name: &#39;test&#39;,
  mode: &#39;development&#39;,
  devtool: &#39;eval&#39;,

  entry: {
    app: [&#39;./index.jsx&#39;]
  },

  module: {
    rules: [{
      test: /\.jsx?$/,
      loader: &#39;babel-loader&#39;,
      options: {
        presets: [&#39;@babel/preset-env&#39;, &#39;@babel/preset-react&#39;],
      }
    }],
  },

  plugins: [],

  output: {
    path: path.join(__dirname, &#39;dist&#39;),    // __dirname: webpack.config.js 파일이 위치한 경로
    filename: &#39;app.js&#39;,
    publicPath: &#39;/dist/&#39;
  },
}</code></pre>
<hr>
<pre><code class="language-html">📃 index.html

&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot; /&gt;
  &lt;title&gt;Test&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div id=&quot;root&quot;&gt;&lt;/div&gt;
  &lt;script src=&quot;./dist/app.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<hr>
<pre><code class="language-jsx">📃 index.jsx

const React = require(&#39;react&#39;)
const ReactDom = require(&#39;react-dom&#39;)

const Test = require(&#39;./Test&#39;)

ReactDom.render(&lt;Test /&gt;, document.querySelector(&#39;#root&#39;))</code></pre>
<hr>
<pre><code class="language-jsx">📃 Test.jsx
const React = require(&#39;react&#39;)

const Test = () =&gt; {
  return (
    &lt;div&gt;
      Hello, React!
    &lt;/div&gt;
  )
}

module.exports = Test</code></pre>
<hr>
<pre><code>📃 package.json

{
  &quot;name&quot;: &quot;test&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;webpack&quot;
  },
  &quot;author&quot;: &quot;cs&quot;,
  &quot;license&quot;: &quot;MIT&quot;,
  &quot;dependencies&quot;: {
    &quot;react&quot;: &quot;^17.0.2&quot;,
    &quot;react-dom&quot;: &quot;^17.0.2&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@babel/core&quot;: &quot;^7.15.0&quot;,
    &quot;@babel/preset-env&quot;: &quot;^7.15.0&quot;,
    &quot;@babel/preset-react&quot;: &quot;^7.14.5&quot;,
    &quot;babel-loader&quot;: &quot;^8.2.2&quot;,
    &quot;webpack&quot;: &quot;^5.50.0&quot;,
    &quot;webpack-cli&quot;: &quot;^4.7.2&quot;
  }
}</code></pre><hr>
<h3 id="6-웹팩-빌드">6. 웹팩 빌드</h3>
<p><code>npm run dev</code> 👉 package.json 파일의 scripts 명령어 실행
<img src="https://images.velog.io/images/code_newb/post/e82ec803-993a-4d7f-b2ce-33777d9d3c88/image.png" alt=""><strong>Hello React😉</strong></p>
<h2 id="reference">Reference</h2>
<p>📗 <a href="https://www.zerocho.com/category/NodeJS/post/57387cb8715202c8679b3af1">Node.js와 npm</a>
📗 <a href="https://reactjs-kr.firebaseapp.com/docs/installation.html">리액트 공식 사이트 - 설치</a>
📗 <a href="https://babeljs.io/docs/en/">What is Babel?</a>
📗 <a href="https://webpack.js.org/guides/">Guides | Webpack</a>
📗 <a href="https://d2.naver.com/helloworld/0239818">JavaScript 모듈화 도구, webpack</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[캐시]]></title>
            <link>https://velog.io/@code_newb/%EC%BA%90%EC%8B%9C</link>
            <guid>https://velog.io/@code_newb/%EC%BA%90%EC%8B%9C</guid>
            <pubDate>Tue, 10 Aug 2021 09:14:40 GMT</pubDate>
            <description><![CDATA[<h5 id="『http-완벽-가이드』-교재와-다른-레퍼런스를-참고하여-작성하였습니다">『HTTP 완벽 가이드』 교재와 다른 레퍼런스를 참고하여 작성하였습니다.</h5>
<h1 id="캐시">캐시</h1>
<p><strong>웹 캐시</strong>는 자주 쓰이는 문서의 사본을 자동으로 보관하는 HTTP 장치입니다. 복수의 클라이언트가 자주 쓰이는 원 서버 페이지에 접근할 때, 서버는 같은 문서를 클라이언트에게 각각 한 번씩 전송하게 됩니다. 똑같은 바이트들이 네트워크를 통해 계속 반복해서 이동합니다. 이 불필요한 데이터 전송은 값비싼 <strong>네트워크 대역폭을 잡아먹고, 전송을 느리게 만들며, 웹 서버에 부하</strong>를 줍니다. 캐시를 이용하면, 첫 번째 서버 응답은 캐시에 보관됩니다. 캐시된 사본이 뒤이은 요청들에 대한 응답으로 사용될 수 있기 때문에, 원 서버가 중복해서 트래픽을 주고받는 낭비가 줄어들게 됩니다.</p>
<h2 id="대역폭-병목">대역폭 병목</h2>
<p>많은네트워크가 원격 서버보다 로컬 네트워크 클라이언트에 더 넓은 대역폭을 제공합니다. 클라이언트들이 서버에 접근할 때의 속도는, 그 경로에 있는 가장 느린 네트워크의 속도와 같습니다. 만약 클라이언트가 빠른 LAN 에 있는 캐시로부터 사본을 가져온다면, 캐싱은 성능을 대폭 개선할 수 있을 것입니다.</p>
<h2 id="갑작스런-요청-쇄도flash-crowds">갑작스런 요청 쇄도(Flash Crowds)</h2>
<p>캐싱은 갑작스런 요청 쇄도에 대처하기 위해 특히 중요합니다. 갑작스런 사건으로 인해 많은 사람이 거의 동시에 웹 문서에 접근할 때 이런 일이 발생합니다. 이 결과로 초래된 불필요한 트래픽 급증은 네트워크와 웹 서버의 심각한 장애를 야기시킵니다.</p>
<h2 id="거리로-인한-지연">거리로 인한 지연</h2>
<p>모든 네트워크 라우터는 제각각 인터넷 트래픽을 지연시킵니다. 그리고 클라이언트와 서버 사이에 라우터가 그다지 많지 않더라도, 빛의 속도 그 자체가 유의미한 지연을 유발합니다.
<img src="https://images.velog.io/images/code_newb/post/dd1f5c76-75a0-482d-b154-698b16408e08/image.png" alt=""></p>
<h2 id="적중과-부적중🎯">적중과 부적중🎯</h2>
<p>캐시에 요청이 도착했을 때, 만약 그에 대응하는 사본이 있다면 그를 이용해 요청이 처리될 수 있습니다[<strong>캐시 적중(cache hit)</strong>]. 만약 대응하는 사본이 없다면 그냥 원 서버로 적중되기만 할 뿐입니다[<strong>캐시 부적중(cache miss)</strong>].</p>
<h3 id="재검사revalidation">재검사(Revalidation)</h3>
<p>원 서버 콘텐츠는 변경될 수 있기 때문에, 캐시는 반드시 그들이 갖고 있는 사본이 여전히 최신인짖 서버를 통해 때때로 점검해야 합니다. 이러한 &#39;신선도 검사&#39;를 <strong>HTTP 재검사</strong>라 부릅니다. 캐시는 스스로 원한다면 언제든지 사본을 재검사할 수 있습니다. 그러나 캐시가 문서를 수백만 개씩 갖고 있는 경우가 흔한데 비해 네트워크 대역폭은 부족하기 때문에, 대부분의 캐시는 <strong>클라이언트가 사본을 요청하였으며 그 사본이 검사를 할 필요가 있을 정도로 충분히 오래된 경우에만</strong> 재검사를 합니다. </p>
<p>캐시는 캐시된 사본의 재검사가 필요할 때, 원 서버에 작은 재검사 요청을 보냅니다. 콘텐츠가 변경되지 않았다면, 서버는 아주 작은 Not Modified 응답을 보냅니다. 그 사본이 유효함을 알게 된 캐시는 즉각 사본이 신선하다고 임시로 다시 표시한 뒤 그 사본을 클라이언트에 제공합니다. 이를 <strong>재검사 적중</strong> 혹은 <strong>느린 적중</strong>이라고 부릅니다. 
<code>속도: 순수 캐시 적중 &gt; 재검사 적중 &gt; 캐시 부적중</code></p>
<p>HTTP는 캐시된 객체를 재확인하기 위한 몇 가지 도구를 제공하는데, 그중에 가장 많이 쓰이는 것은 <code>If-Modified-Since</code> 헤더입니다. 서버에게 보내는 GET 요청에 이 헤더를 추가하면 캐시된 시간 이후에 변경된 경우에만 사본을 보내달라는 의미입니다. </p>
<p>재검사 적중: 서버 객체가 변경되지 않았다면, 서버➡클라이언트 <code>HTTP 304 Not Modified</code>
재검사 부적중: 서버 객체가 캐시된 사본과 다르다면, <code>HTTP 200 OK</code>
객체 삭제: 서버 객체가 삭제되었다면, <code>404 Not Found</code></p>
<h3 id="적중률">적중률</h3>
<p>캐시가 요청을 처리하는 비율을 <strong>캐시 적중률</strong>(혹은 캐시 적중비), 혹은 <strong>문서 적중률</strong>(혹은 문서 적중비)이라고 부르기도 합니다. 
0% (모두캐시 부적중) ~ 100% (모두 캐시 적중)
오늘날 적중률 40%면 웹 캐시로 괜찮은 편이며 보통 크기의 캐시라도 충분한 분량의 자주 쓰이는 문서들을 보관하여 상당히 트래픽을 줄이고 성능을 개선할 수 있다는 점입니다.</p>
<h3 id="바이트-적중률">바이트 적중률</h3>
<p>문서들이 모두 같은 크기인 것은 아니기 때문에 문서 적중률이 모든 것을 말해주지는 않습니다. 몇몇 큰 객체는 덜 접근되지만 그 크기 때문에 전체 트래픽에는 더 크게 기여합니다.
바이트 단위 적중률은 캐시를 통해 제공된 모든 바이트의 비율을 표현합니다. 이 측정값은 트래픽이 절감된 정도를 포착해냅니다. </p>
<p>문서 적중률은 얼마나 많은 웹 트랜잭션을 외부로 내보내지 않았는지 보여줍니다. - <u>전체 대기시간(지연) 감소</u>
바이트 단위적중률은 얼마나 많은 바이트가 인터넷으로 나가지 않았는지보여줍니다. - <u>대역폭 절약을 최적화</u></p>
<h3 id="적중과-부적중의-구별">적중과 부적중의 구별</h3>
<p>HTTP는 클라이언트에게 응답이 캐시 적중이었는지 아니면 원 서버 접근인지 말해줄 수 있는 방법을 제공하지 않습니다. 두 경우 모두 응답 코드는 응답이 본문을 갖고 있음을 의미하는 200 OK가 될 것입니다.</p>
<p>클라이언트가 응답이 캐시에서 왔는지 알아내는 한 가지 방법은 <code>Date 헤더</code>를 이용하는 것입니다. 응답의 Date 헤더 값을 현재 시각과 비교하여, 응답의 생성일이 더 오래되었다면 클라이언트는 응답이 캐시된 것임을 알아낼 수있습니다. 또 다른 방법은, 응답이 얼마나 오래되었는지 말해주는 <code>Age 헤더</code>를 이용하는 것입니다.</p>
<h2 id="캐시-토폴로지">캐시 토폴로지</h2>
<p>캐시는 한 명의 사용자에게만 할당할 수도 있고(개인 전용 캐시) 반대로 수천 명의 사용자들 간에 공유될 수도 있습니다(공용 캐시).
<img src="https://images.velog.io/images/code_newb/post/0ea0b680-afc9-4dfa-a110-7d3a00fe85ee/image.png" alt=""></p>
<h3 id="개인-전용-캐시">개인 전용 캐시</h3>
<p>개인 전용 캐시는 많은 에너지나 저장 공간을 필요로 하지 않으므로, 작고 저렴할 수 있습니다. 웹브라우저는 개인 전용 캐시를 내장하고 있습니다. 대부분의 브라우저는 자주 쓰이는 문서를 개인용 컴퓨터의 디스크와 메모리에 캐시해 놓고, 사용자가 캐시 사이즈와 설정을 수정할 수 있도록 허용하며 확인할 수 있습니다. </p>
<h3 id="공용-프락시-캐시">공용 프락시 캐시</h3>
<p>공용 캐시는 캐시 프락시 서버 혹은 더 흔히 프락시 캐시라고 불리는 특별한 종류의 공유된 프락시 서버입니다. 프락시 캐시는 로컬 캐시에서 문서를 제공하거나, 혹은 사용자의 입장에서 서버에 접근합니다. 공용 캐시에는 여러 사용자가 접근하기 때문에, 불필요한 트래픽을 줄일 수 있는 더 많은 기회가 있습니다.
공유 캐시에서, 캐시는 자주 찾는 객체를 단 한 번만 가져와 모든 요청에 대해 공유된 사본을 제공함으로써 네트워크 트래픽을 줄입니다. </p>
<h3 id="프락시-캐시-계층들">프락시 캐시 계층들</h3>
<p>작은 캐시에서 캐시 부적중이 발생했을 때 더 큰 부모 캐시가 그 &#39;걸러 남겨진&#39; 트래픽을 처리하도록 하는 계층을 만드는 방식이 합리적인 경우가 많습니다. 클라이언트 주위에는 작고 저렴한 캐시를 사용하고, 계층 상단에는 많은 사용자들에 의해 공유되는 문서를 유지하기 위해 더 크고 강력한 캐시를 사용하자는 것입니다. 캐시 계층이 깊다면 요청은 캐시의 긴 연쇄를 따라가게ㅔ 될 것이며 프락시 연쇄가 길어질수록 각 중간 프락시는 현저한 성능 저하가 발생할 것입니다.
<img src="https://images.velog.io/images/code_newb/post/194b2a84-bf81-474d-b06d-a08272025428/image.png" alt=""></p>
<h3 id="캐시망-콘텐츠-라우팅-피어링">캐시망, 콘텐츠 라우팅, 피어링</h3>
<p>캐시망의 프락시 캐시는 복잡한 방법으로 서로 대화하여, 어떤 부모 캐시와 대화할 것인지, 아니면 요청이 캐시를 완전히 우회해서 원 서버로 바로 가도록 할 것인지에 대한 캐시 커뮤니케이션 결정을 동적으로 내립니다.</p>
<ul>
<li>URL에 근거하여, 부모 캐시와 원 서버 중 하나를 동적으로 선택합니다.</li>
<li>URL에 근거하여 특정 부모 캐시를 동적으로 선택합니다.</li>
<li>부모 캐시에게 가기 전에, 캐시된 사본을 로컬에서 찾아봅니다.</li>
<li>다른 캐시들이 그들의 캐시된 콘텐츠에 부분적으로 접근할 수 있도록 허용하되, 그들의 캐시를 통한 <a href="https://en.wikipedia.org/wiki/Internet_transit">인터넷 트랜짓</a>은 허용하지 않습니다.</li>
</ul>
<p>더 복잡한 캐시 사이의 관계는, 서로 다른 조직들이 상호 이득을 위해 그들의 캐시를 연결하여 서로를 찾아볼 수 있도록 해줍니다. 선택적인 피어링을 지원하는 캐시는 <strong>형제 캐시</strong>라고 불립니다. HTTP는 형제 캐시를 지원하지 않기 때문에, 사람들은 <a href="https://en.wikipedia.org/wiki/Internet_Cache_Protocol">인터넷 캐시 프로토콜(ICP)</a>이나 <a href="https://en.wikipedia.org/wiki/Hypertext_caching_protocol">하이퍼텍스트 캐시 프로토콜(HTCP)</a> 같은 프로토콜을 이용해 HTTP를 확장했습니다.
<img src="https://images.velog.io/images/code_newb/post/d9ff8eb5-2f69-4bb1-85c1-41b95a3ef415/image.png" alt=""></p>
<h2 id="캐시-처리-단계">캐시 처리 단계</h2>
<p>HTTP GET 메시지 하나를 처리하는 기본적인 캐시 처리 절차는 일곱 단계로 이루어져 있습니다.
<img src="https://images.velog.io/images/code_newb/post/b0551274-4627-4d9e-814f-c7bfba21917f/image.png" alt="">1. 요청 받기 - 캐시는 네트워크로부터 도착한 요청 메시지를 읽습니다.
2. 파싱 - 캐시는 메시지를 파싱하여 URL과 헤더들을 추출합니다.
3. 검색 - 캐시는 로컬 복사본이 있는지 검사하고, 사본이 없다면 사본을 받아옵니다.
4. 신선도 검사 - 캐시는 캐시된 사본이 충분히 신선한지 검사하고, 신선하지 않다면 변경사항이 있는지 서버에게 물어봅니다.
5. 응답 생성 - 캐시는 새로운 헤더와 본문으로 응답 메시지를 만듭니다.
6. 발송 - 캐시는 네트워크를 통해 응답을 클라이언트에게 돌려줍니다.
7. 로깅 - 선택적으로, 캐시는 로그파일에 트랜잭션에 대해 서술한 로그 하나를 남깁니다. </p>
<h3 id="단계-1-요청-받기">단계 1: 요청 받기</h3>
<p>캐시는 <strong>네트워크 커넥션에서의 활동을 감지하고, 들어오는 데이터를 읽어들입니다</strong>. 고성능 캐시는 여러 개의 들어오는 커넥션들로부터 데이터를 동시에 읽어들이고 메시지 전체가 도착하기 전에 트랜잭션 처리를 시작합니다.</p>
<h3 id="단계-2-파싱">단계 2: 파싱</h3>
<p>캐시는 <strong>요청 메시지를 여러 부분으로 파싱</strong>하여 헤더 부분을 조작하기 쉬운 자료 구조에 담습니다. 이는 캐싱 소프트웨어가 헤더 필드를 처리하고 조작하기 쉽게 만들어줍니다.</p>
<h3 id="단계-3-검색">단계 3: 검색</h3>
<p>캐시는 URL을 알아내고 그에 해당하는 <strong>로컬 사본이 있는지 검사</strong>합니다. 로컬 복사본은 메모리에 저장되어 있을 수도 있고, 아니면 디스크나 심지어 근처의 다른 컴퓨터에 있을 수도 있습니다. 문서를 로컬에서 가져올 수 없다면, 캐시는 상황이나 설정에 따라서 그것을 원 서버나 부모 프락시에서 가져오거나 혹은 실패를 반환합니다</p>
<h3 id="단계-4-신선도-검사">단계 4: 신선도 검사</h3>
<p>HTTP는 캐시가 일정 기간 동안 서버 문서의 사본을 보유할 수 있도록 해줍니다. 캐시된 사본을 <strong>신선도 한계를 넘을 정도로 너무 오래 갖고 있었다면</strong> 그 객체는 &#39;신선하지 않은&#39; 것으로 간주되며, 캐시는 그 문서를 제공하기 전에 문서에 어떤 변경이 있었는지 검사하기 위해 <strong>서버와 재검사</strong>를 해야 합니다.</p>
<h3 id="단계-5-응답-생성">단계 5: 응답 생성</h3>
<p>우리는 캐시된 응답을 원 서버에서 온 것처럼 보이게 하고 싶기 때문에, 캐시는 <strong>캐시된 서버 응답 헤더를 토대로 응답 헤더를 생성</strong>합니다. 캐시는 클라이언트에 맞게 헤더를 조정해야 하는 책임이 있습니다. 캐시는 헤더를 적절하게 번역해야 하고 캐시 신선도 정보를 삽입하며, 또 요청이 프락시 캐시를 거쳐갔음을 알려주기 위해 종종 Via 헤더를 포함시킵니다.</p>
<h3 id="단계-6-전송">단계 6: 전송</h3>
<p>응답 헤더가 준비되면, 캐시는 <strong>응답을 클라이언트에게 돌려줍니다</strong>. 모든 프락시 서버들과 마찬가지로, 프락시 캐시는 클라이언트와의 커넥션을 유지할 필요가 있습니다. </p>
<h3 id="단계-7-로깅">단계 7: 로깅</h3>
<p>대부분의 캐시는 로그 파일과 캐시 사용에 대한 통계를 유지합니다. 각 캐시 트랜잭션이 완료된 후, 캐시는 통계 캐시 적중과 부적중 횟수에 대한 <strong>통계를 갱신</strong>하고 <strong>로그 파일에 요청 종류, URL 그리고 무엇이 일어났는지를 알려주는 항목을 추가</strong>합니다.</p>
<h3 id="캐시-처리-플로-차트">캐시 처리 플로 차트</h3>
<p><img src="https://images.velog.io/images/code_newb/post/ce45832d-44be-4e1f-9353-6a6e21597765/image.png" alt=""></p>
<h2 id="사본을-신선하게-유지하기">사본을 신선하게 유지하기</h2>
<p>캐시된 사본 모두가 서버의 문서와 항상 일치하는 것은 아닙니다. 결국 문서들은 시간에 따라 변경되기 때문에 캐시된 데이터는 서버의 데이터와 일치하도록 관리되어야 합니다. 
HTTP는 어떤 캐시가 사본을 갖고 있는지 서버가 기억하지 않더라도, 캐시된 사본이 서버와 충분히 일치하도록 유지할 수 있게 해주는 <strong>서버 재검사</strong>라고 불리는 단순한 메커니즘을 갖고 있습니다.</p>
<h3 id="문서-만료">문서 만료</h3>
<p>HTTP는 <code>Cache-Control</code>과 <code>Expires</code>라는 특별한 헤더들을 이용해서 원 서버가 각 문서에 유효기간을 붙일 수 있게 해줍니다. 캐시 문서가 만료되기 전에, 캐시는 필요하다면 서버와의 접촉 없이 사본을 제공할 수 있습니다. 그러나 캐시된 문서가 만료되면, 캐시는 반드시 서버와 문서에 변경된 것이 있는지 검사해야 하며, 그렇다면 신선한 사본을 얻어 와야 합니다.</p>
<h3 id="유효기간과-나이">유효기간과 나이</h3>
<p>서버는 응답 본문과 함께 하는, <code>HTTP/1.0+ Expires</code>나 <code>HTTP/1.1 Cache-Control: max-age</code> 응답 헤더를 이용해서 유효기간을 명시합니다.</p>
<table>
<thead>
<tr>
<th>헤더</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Cache-Control: max-age</td>
<td>문서의 최대 나이를 정의합니다. 최대 나이는 문서가 처음 생성된 이후부터, 신선하지 않다고 간주될 때까지 경과한 시간의 합법적인 최댓값(초 단위)입니다.<br><code>Cache-Control: max-age=484200</code></td>
</tr>
<tr>
<td>Expires</td>
<td>절대 유효기간을 명시합니다. 만약 유효기간이 경과했다면, 그 문서는 더 이상 신선하지 않음을 뜻합니다.<br><code>Expires: Fri, 05 Jul 2002, 05:0:00 GMT</code></td>
</tr>
</tbody></table>
<h3 id="서버-재검사">서버 재검사</h3>
<p>캐시된 문서가 만료되었다는 것은, 그 문서가 원 서버에 현재 존재하는 것과 실제로 다르다는 것을 의미하지는 않으며, 다만 이제 검사할 시간이 되었음을 뜻합니다. 캐시가 원 서버에게 문서가 변경되었는지의 여부를 물어볼 필요가 있음을 의미하는 이 검사를 ** 서버 재검사 **라고 부릅니다.</p>
<ul>
<li>재검사 결과 콘텐츠가 변경되었다면, 캐시는 그 문서의 새로운 사본을 가져와 오래된 데이터 대신 저장한 뒤 클라이언트에게도 보내줍니다.</li>
<li>재검사 결과 콘텐츠가 변경되지 않았다면, 캐시는 새 만료일을 포함한 새 헤더들만 가져와서 캐시 안의 헤더들을 갱신합니다.</li>
</ul>
<p>캐시는 문서의 신선도를 매 요청마다 검증할 필요가 없이** 문서가 만료되었을 때** 한번만 서버와 재검사하면 됩니다. </p>
<p>HTTP 프로토콜은 캐시가 다음 중 하나를 반환하는 적절한 행동을 할 것을 요구합니다.</p>
<ul>
<li>&#39;충분히 신선한&#39; 캐시된 사본</li>
<li>원 서버와 재검사되었기 때문에, 충분히 신선하다고 확신할 수 있는 캐시된 사본</li>
<li>에러 메시지(재검사해야 하는 원 서버가 다운된 경우)</li>
<li>경고 메시지가 부착된 캐시된 사본(부정확하다면)</li>
</ul>
<h3 id="조건부-메서드와의-검사">조건부 메서드와의 검사</h3>
<p>HTTP는 캐시가 서버에게 &#39;조건부 GET&#39;이라는 요청을 보낼 수 있도록 해줍니다. 이 요청은 <strong>서버가 갖고 있는 문서가 캐시가 갖고 있는 것과 다른 경우에만 객체 본문을 보내달라고 하는 것</strong>입니다. 조건부 GET은 GET 요청 메시지에 특별한 조건부 헤더를 추가함으로써 시작됩니다.</p>
<table>
<thead>
<tr>
<th>헤더</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>If-Modified-Since: &lt;date&gt;</td>
<td>만약 문서가 주어진 날짜 이후로 수정되었다면 요청 메서드를 처리. 이것은 캐시된 버전으로부터 콘텐츠가 변경된 경우에만 콘텐츠를 가져오기 위해 Last-Modified 서버 응답 헤더와 함께 사용됩니다.</td>
</tr>
<tr>
<td>If-None-Match: &lt;tags&gt;</td>
<td>마지막 변경된 날짜를 맞춰보는 대신, 서버는 문서에 대한 일련번호와 같이 동작하는 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/ETag">특별한 태그</a>를 제공할 수 있습니다.<br>캐시된 태그가 서버에 있는 문서의 태그와 다를 때만 요청을 처리합니다.</td>
</tr>
</tbody></table>
<h3 id="if-modified-since-날짜-재검사">If-Modified-Since: 날짜 재검사</h3>
<p>If-Modified-Since 재검사 요청은 &#39;IMS&#39; 요청으로 불립니다.</p>
<ul>
<li>만약 문서가 주어진 날짜 이후에 변경되었다면, If-Modified-Since 조건은 참이고, 따라서 GET 요청은 평범하게 성공합니다. 새 문서가, 새로운 만료 날짜와 그 외 다른 정보들이 담긴 헤더들과 함께 캐시에게 반환됩니다.</li>
<li>만약 주어진 날짜 이후에 변경되지 않았다면 조건은 거짓이고, 서버는 작은 <code>304 Not Modified</code>응답 메시지를 클라이언트에게 돌려줍니다. 효율을 위해 본문은 보내지 않고 갱신이 필요한 것만을 보내줍니다.</li>
</ul>
<p>몇몇 웹 서버는 If-Modified-Since를 실제 날짜 비교로 구현하지 않습니다. 대신 그들은 IMS 날짜와 최근 변경일 간의 문자열 비교를 수행합니다. 즉 &quot;이 날짜 이후로 변경되었다면&quot;이 아니라 &quot;<u>정확히 이 날짜에 마지막 변경이 일어난 것이 아니라면</u>&quot;이라는 의미로 동작
<img src="https://images.velog.io/images/code_newb/post/e06860b8-2ed8-4b2a-9629-07c01c7dd2a5/image.png" alt=""></p>
<h3 id="if-none-match-엔터티-태그-재검사">If-None-Match: 엔터티 태그 재검사</h3>
<p>최근 변경 일시 재검사가 적절히 행해지기 어려운 상황이 몇 가지 있습니다.</p>
<ul>
<li>어떤 문서는 일정시간 간격으로 다시 쓰여지지만 실제로는 같은 데이터를 포함하고 있습니다. 내용에는 아무 변화가 없더라도 변경시각은 바뀔 수 있습니다.</li>
<li>어떤 문서들의 변경은 전 세계의 캐시 들이 그 데이터를 읽어들이기엔 사소한 것일 수도 있습니다. (ex. 철자나 주석 변경)</li>
<li>어떤 서버들은 그들이 갖고 있는 페이지에 대한 최근 변경 일시를 정확하게 판별할 수 없습니다.</li>
<li>1초보다 작은 간격으로 갱신되는 문서를 제공하는 서버들에게는, 변경일에 대한 1초의 정밀도는 충분하지 않을 수 있습니다. </li>
</ul>
<p>문서를 변경했을 때, 문서의 엔터티 태그를 새로운 버전으로 표현할 수있습니다. <strong>엔터티 태그가 변경되었다면, 캐시는 새 문서의 사본을 얻기(GET) 위해</strong> If-None-Match 조건부 헤더를 사용할 수 있습니다. 만약 서버의 엔터티 태그가 변경되었다면 서버는 200 OK 응답으로 새 콘텐츠를 새 ETag와 함께 반환할 것입니다.
<img src="https://images.velog.io/images/code_newb/post/90bebc34-6d35-4f1f-8b1a-22d10b11fc21/image.png" alt=""></p>
<h3 id="약한-검사기와-강한-검사기">약한 검사기와 강한 검사기</h3>
<p>캐시는 캐시된 버전이 서버가 갖고있는 것에 대해 최신인지 확인하기 위해 엔터티 태그를 사용합니다. 이 경우, 엔터티 태그와 최근 변경일시는 둘 다 캐시 검사기입니다.
서버는 때때로 모든 캐시된 사본을 무효화시키지 않고 문서를 살짝 고칠 수 있도록 허용하고 싶은 경우가 있습니다. HTTP/1.1은, 비록 코넨츠가 조금 변경되었더라도 &quot;그 정도면 같은 것&quot;이라고 서버가 주장할 수 있도록 해주는 ** 약한 검사기(week validator)<strong>를 지원합니다. 
** 강한 검사기(strong validator)</strong>는 콘텐츠가 바뀔 때마다 바뀝니다. 조건부 특정범위 가져오기 같은 몇몇 동작은 약한 검사기로는 불가능하기 때문에, 서버는 <code>W/</code> 접두사로 약한 검사기를 구분합니다.</p>
<pre><code>ETag: W/&quot;v2.6&quot;
If-None-Match: W/&quot;v2.6&quot;</code></pre><p>강한 엔터티 태그는 대응하는 엔터티 값이 어떻게 바뀌든 매번 반드시같이 바뀌어야 합니다. 약한 엔터티 태그는 대응하는 엔터티에 유의미한 변경이 있을 때마다 같이 변경되어야 합니다.</p>
<h3 id="언제-엔터티-태그를-사용하고-언제-last-modified-일시를-사용하는지">언제 엔터티 태그를 사용하고 언제 Last-Modified 일시를 사용하는지</h3>
<p>HTTP/1.1 클라이언트는 만약 서버가 엔터티 태그를 반환했다면, 반드시 엔터티 태그 검사기를 사용해야 합니다. 만약 서버가 Last-Modified 값만을 반환했다면, 클라이언트는 If-Modified-Since 검사를 사용할 수 있습니다. 만약 엔터티 태그와 최근 변경일시가 모두 사용 가능하다면, HTTP/1.0과 HTTP/1.1 캐시 모두 적절히 응답할 수 있도록 클라이언트는 각각을 위해 두 가지의 재검사 정책을 모두 사용해야 합니다.</p>
<h2 id="캐시-제어">캐시 제어</h2>
<p>HTTP는 문서가 만료되기 전까지 얼마나 오랫동안 캐시될 수 있게 할 것인지 서버가 설정할 수 있는 여러 가지 방법을 정의합니다.</p>
<ul>
<li>Cache-Control: no-store 헤더를 응답에 첨부</li>
<li>Cache-Control: no-cache 헤더를 응답에 첨부</li>
<li>Cache-Control: must-revalidate 헤더를 응답에 첨부</li>
<li>Cache-Control: max-age 헤더를 응답에 첨부</li>
<li>Expires 날짜 헤더를 응답에 첨부</li>
<li>아무 만료 정보도 주지 않고, 캐시가 스스로 체험적인(휴리스틱) 방법으로 결정</li>
</ul>
<h3 id="no-cache와-no-store-응답-헤더">no-cache와 no-store 응답 헤더</h3>
<p>no-store와 no-cache헤더는 <strong>캐시가 검증되지 않은 캐시된 객체로 응답하는 것을 막습니다</strong>.</p>
<pre><code>Cache-Control: no-store
Cache-Control: no-cache
Pragma: no-cache</code></pre><p>&#39;no-store&#39;가 표시된 응답은 <u>캐시가 그 응답의 사본을 만드는 것을 금지</u>합니다. 
&#39;no-cache&#39;로 표시된 응답은 먼저 <u>서버와 재검사를 하지 않고서는 캐시에서 클라이언트로 제공할 수 없습니다</u>. 
Pragma: no-cache는 캐시가 검증을 위해 원래 서버에 요청을 보내도록 강제한다는 점에서 Cache-Control: no-cache와 유사합니다. Cache-Control HTTP/1.1 헤더가 없는 HTTP/1.0 클라이언트와의 하위 호환성을 위한 경우에만 사용하여야 합니다.</p>
<h3 id="max-age-응답-헤더">Max-Age 응답 헤더</h3>
<p>신선한다고 간주되었던 <strong>문서가 서버로부터 온 이후로 흐른 시간</strong>이고, 초로 나타냅니다. 또한 s-maxage 헤더는 max-age처럼 행동하지만 공유된(공용) 캐시에만 적용됩니다.</p>
<h3 id="expires-응답-헤더">Expires 응답 헤더</h3>
<p>더 이상 사용하지 않기를 권하는 Expires 헤더는 초 단위의 시간 대신 <strong>실제 만료 날짜를 명시</strong>합니다.</p>
<h3 id="must-revalidate-응답-헤더">Must-Revalidate 응답 헤더</h3>
<p>캐시는 성능을 개선하기 위해 신선하지 않은(만료된) 객체를 제공하도록 설정될 수 있습니다. 만약 캐시가 만료 정보를 엄
<code>Cache-Control: must-revalidate</code> 응답 헤더는 캐시가 이 객체의 신선하지 않은 사본을 원 서버와의 최초의 재검사 없이는 제공해서는 안 됨을 의미합니다. </p>
<h3 id="휴리스틱-만료">휴리스틱 만료</h3>
<p>만약 응답이 <code>Cache-Control: max-age</code> 헤더나 <code>Expires</code> 헤더 중 어느 것도 포함하지 않고 있다면, 캐시는 경험적인 방법으로(heuristic) 유효 기간을 추정합니다.</p>
<p>유명한 휴리스틱 만료 알고리즘의 하나인 LM 인자 알고리즘은 문서가 최근 변경 일시를 포함하고 있다면 사용할 수 있습니다. LM 인자 알고리즘은 최근 변경 일시를 문서가 얼마나 자주 바뀌는지에 대한 추정에 사용합니다.</p>
<ul>
<li>만약 캐시된 문서가 마지막으로 변경된 것이 상당히 예전이라면, 그것은 아마 안정적인 문서일 것이고 갑자기 바뀔 가능성은 크지 않을 것이므로, 캐시에 더 오래 보관하고 있어도 안전</li>
<li>만약 캐시된 문서가 최근에 변경되었다면, 그것은 아마 자주 변경될 것이고, 따라서 그것을 서버와 재검사하기 전까지 짧은 기간 동안만 캐시</li>
</ul>
<p>만약 최근 변경일조차 없다면, 캐시는 판단 근거가 될 정보를 그다지 갖지 못한 것이 됩니다. 캐시는 일반적으로 신선도에 대한 아무런 단서가 없는 문서에 대해 기본 신선도 유지기간을 설정합니다.</p>
<h3 id="클라이언트-신선도-제약">클라이언트 신선도 제약</h3>
<p>웹브라우저는 브라우저나 프락시 캐시의 신선하지 않은 콘텐츠를 강제로 갱신시켜 주는 리프레시나 리로드 버튼을 갖고 있습니다. 이 리프레시 버튼은 Cache-Control 요청 헤더가 추가된 GET 요청을 발생시켜서, 강제로 재검사하거나 서버로부터 콘텐츠를 무조건 가져옵니다.
클라이언트는 Cache-Control 요청 헤더를 사용하여 만료 제약을 엄격하게 하거나 느슨하게 할 수 있습니다.</p>
<p>** Cache-Control 요청 지시어 **</p>
<table>
<thead>
<tr>
<th>지시어</th>
<th>목적</th>
</tr>
</thead>
<tbody><tr>
<td>Cache-Control: max-stale<br>Cache-Control: max-stale = &lt;s&gt;</td>
<td>캐시는 신선하지 않은 문서라도 자유롭게 제공할 수 있습니다. 만약 &lt;s&gt; 매개변수가 지정되면, 클라이언트는 만료시간이 그 매개변수의 값만큼 지닌 문서도 받아들입니다.</td>
</tr>
<tr>
<td>Cache-Control: min-fresh = <s/></td>
<td>클라이언트는 지금으로부터 적어도 &lt;s&gt; 초 후까지 신선한 문서만을 받아들입니다.</td>
</tr>
<tr>
<td>Cache-Control: max-age = &lt;s&gt;</td>
<td>캐시는 &lt;s&gt; 초보다 오랫동안 캐시된 문서를 반환할 수 없습니다.</td>
</tr>
<tr>
<td>Cache-Control: no-cache<br>Pragma: no-cache</td>
<td>이 클라이언트는 캐시된 리소스는 재검사하기 전에는 받아들이지 않을 것입니다.</td>
</tr>
<tr>
<td>Cache-Control: no-store</td>
<td>이 캐시는 저장소에서 문서의 흔적을 최대한 빨리 삭제해야 합니다.</td>
</tr>
<tr>
<td>Cache-Control: only-if-cached</td>
<td>클라이언트는 캐시에 들어있는 사본만을 원합니다.</td>
</tr>
</tbody></table>
<h3 id="주의할-점">주의할 점</h3>
<p>문서 완료는 완벽한 시스템이 아닙니다. 유효기간을 까마득한 미래로 설정해버린다면, 만료되기 전까지는 그 문서에 대한 어떤 변경도 캐시에 반영되지 않을 것입니다.</p>
<h2 id="캐시와-광고">캐시와 광고</h2>
<p>캐시는 성능을 개선하고 트래픽을 줄입니다. 캐시는 사용자를 도와 더 좋은 경험을 제공하고, 또한 네트워크 사업자들이 트래픽을 줄일 수 있도록 도와줍니다.</p>
<h3 id="광고-회사의-딜레마">광고 회사의 딜레마</h3>
<p>만약 캐시가 모든 곳에 있다면 콘텐츠 제공자들은 수요를 견디기 위해 대용량 멀티프로세서 우베 서버를 살 필요가 없을 것이며, 같은 데이터를 방문자들에게 몇 번이고 반복해서 보여주기 위해 터무니없는 네트워크 서비스 요금을 지불할 필요도 없을 것입니다. 
많은 콘텐츠 제공자가 (사용자가 광고를 볼 때마다)광고를 통해 돈을 법니다. 그것이 캐시와 관련되면 문제가 되는데 캐싱이 완벽하게 동작한다면 원 서버는 HTTP 접근을 전혀 수신하지 않게 됩니다. 인터넷 캐시가 그 접근들을 모두 흡수하기 때문입니다.</p>
<h3 id="퍼블리셔의-응답">퍼블리셔의 응답</h3>
<p>오늘날 광고회사들은 캐시가 광고 시청 수를 가로채지 못하도록 모든 종류의 &#39;캐시 무력화&#39; 기법을 사용합니다.
이 캐시 무력화 기법은 단지 프락시 캐시만에 대한 것이 아니라 웹브라우저에서 켜져 있는 캐시를 주요 대상으로 하고 있습니다. 광고의 시청 수를 관리하려는 과하게 의욕적인 시도는, 몇몇 콘텐츠 제공자가 그들의 사이트에 대한 캐싱의 긍정적인 효과를 감소시키고 있습니다. 
이상적으로는, 콘텐츠 제공자는 캐시가 그들의 트래픽을 흡수하도록 내버려 두어야 하며, 캐시는 그들에게 적중이 얼마나 많이 일어났는지 알려주어야 합니다.</p>
<h3 id="로그-마이그레이션">로그 마이그레이션</h3>
<p>이상적인 해결책 하나는 서버로 요청이 가지 않도록 하는 것입니다. 결국 캐시는 모든 적중의 로그를 유지할 수 있습니다. 캐시는 이 로그를 서버에게 나누어 줄 수 있을 것입니다.
불행히도,적중 로그는 그 크기 때문에 옮기기 어렵고 캐시 로그는 개별 콘텐츠 제공자별로 분리될 수 있도록 표준화되어 있지도 조직되어 있지도 않습니다. 뿐만 아니라 인증과 프라이버시 이슈도 있습니다.</p>
<h3 id="적중-측정과-사용량-제한">적중 측정과 사용량 제한</h3>
<p>HTTP에 때때로 특정 URL에 대한 캐시 적중 횟수를 정기적으로 서버에게 돌려주는 Meter라고 하는 새 헤더 하나를 추가합니다. 이 방법은, 서버가 캐시된 문서가 적중한 횟수의 정기적인 업데이트를 캐시로부터 받습니다.</p>
<blockquote>
<p><a href="https://datatracker.ietf.org/doc/html/rfc2227">RFC2227</a></p>
</blockquote>
<h2 id="reference">Reference</h2>
<p>📗 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Caching">HTTP caching</a>
📗 HTTP 완벽 가이드</p>
]]></description>
        </item>
    </channel>
</rss>