<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kimtaehoon_98.log</title>
        <link>https://velog.io/</link>
        <description>개발자(진)</description>
        <lastBuildDate>Mon, 29 May 2023 16:46:20 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kimtaehoon_98.log</title>
            <url>https://velog.velcdn.com/images/kimtaehoon_98/profile/76597c5a-4045-4eae-863d-5e50faf7264c/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kimtaehoon_98.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kimtaehoon_98" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[TIL #35]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-35</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-35</guid>
            <pubDate>Mon, 29 May 2023 16:46:20 GMT</pubDate>
            <description><![CDATA[<h1 id="section1lsn13">Section1(lsn1~3)</h1>
<h2 id="lsn1">lsn1</h2>
<ul>
<li>console.log(&#39;로그 - 기본적인 출력&#39;)</li>
<li>console.info(&#39;로그 - 기능적으로는 log와 같음. 사용하기에 따라 용도 구분 가능&#39;)</li>
<li>console.warn(&#39;경고 - 문제가 될 수 있는 부분&#39;)</li>
<li>console.error(&#39;오류 - 에러 발생 상황&#39;)</li>
</ul>
<h2 id="lsn3">lsn3</h2>
<h3 id="let">let</h3>
<p>let은 값의 의미를 나타내며, 재활용이 가능하다. 변경되는 상태를 기킨다.</p>
<p>undefined: &#39;아직 값이 정해지지 않았다&#39;라는 &#39;값&#39;</p>
<pre><code>let x = 1
let y = x
// x가 가진 값을 y에 할당
console.log(&#39;변경 전&#39;, x, y)

x = &#39;Hello!&#39;
console.log(&#39;변경 후&#39;, x, y)
// C 등의 언어와 달리, 메모리상 가리키는 위치가 변경
// 차지하는 자리가 다른 크기의 (자료형이 다른) 데이터가 재할당될 수 있으므로</code></pre><h3 id="const">const</h3>
<p>const는 담긴 값이 바뀔 수 없으며, 흔히 대문자로 명명 (여러 곳에서 사용 될 공통 값인 경우)</p>
<h3 id="주의사항">주의사항</h3>
<ul>
<li>영문, 한글 및 유니코드, 숫자 사용 가능</li>
<li>특수문자는 $ 또는 _</li>
<li>숫자로 시작할 수 없음</li>
<li>공백(스페이스) 사용 불가</li>
<li>예약어 사용 불가</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #34]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-34</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-34</guid>
            <pubDate>Thu, 20 Apr 2023 18:50:14 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><audio src=''></audio>: attr controls, attr (loop) autoplay 사용
<audio> <source src='' type='' /> <source /> <source /> </audio>형태도 가능, src 사용 시 type도 추가해주면 좋음</p>
</li>
<li><p>audio와 video 치환 가능
&lt;iframe src=&#39;&#39; frameborder=&#39;&#39;&gt;&lt;/iframe&gt;: HTML 문서 안에 다른 HTML 문서를 embed</p>
</li>
<li><p>&lt;abbr title=&#39;풀네임&#39;&gt;약어&lt;/abbr&gt;(abbreviation): attr title 필요
&lt;address&gt;연락처&lt;/address&gt;: (물리적)주소, URL, email, 전화번호, sns 등등
&lt;pre&gt;&lt;/pre&gt;(preformatted): 태그 안의 내용이 쓰인 그대로 출력됨</p>
</li>
<li><p>Document Type Declaration: DTD 선언 = 문서 형식 선언</p>
<!DOCTYPE html><p>: 브라우저에게 이 문서는 HTML5 버전으로 작성된 문서라는 것을 전달</p>
</li>
</ul>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
    &lt;head&gt;
    웹 문서에 관한 메타 데이터
    &lt;/head&gt;
    &lt;body&gt;
    웹 문서에 들어갈 내용
    &lt;/body&gt;
&lt;html&gt;</code></pre><ul>
<li><p>&lt;title&gt;문서의 대제목&lt;/title&gt;: 탭 제목에 들어가며, SEO에 매우 중요, 키워드 단순 나열 비추, 페이지마다 그에 맞게 변경, head
&lt;link rel=&#39;&#39; href=&#39;&#39;&gt;: css연동, head
&lt;style&gt;css코드&lt;/style&gt;:HTML 문서 내에 css코드를 사용할 때, body
&lt;script src=&#39;경로&#39;&gt;&lt;/script&gt; &lt;script&gt;js코드&lt;/script&gt;: HTML문서 내에 js파일을 첨부할 때 사용, 마지막에 작성해 주는 것이 좋음, body</p>
</li>
<li><p>&lt;meta name=&#39;&#39; content=&#39;&#39;&gt;: attr name(메타데이터 종류), content(메타데이터 값) 필요, name에서 viewport가 중요
&lt;meta name=&#39;viewport&#39; content=&#39;width=device=width, initial-scale=1.0&#39;&gt;
&lt;meta name=&#39;author&#39; content=&#39;작성자&#39;&gt;
&lt;meta name=&#39;keywords&#39; content=&#39;웹페이지의 키워드&#39;&gt;
&lt;meta name=&#39;description&#39; content=&#39;웹페이지의 설명&#39;&gt;</p>
</li>
</ul>
<p>markup 시 가장 중요한 것은 최소한의 단위로 요소를 자르는 것</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #33]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-33</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-33</guid>
            <pubDate>Tue, 18 Apr 2023 18:34:14 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>blockquote cite=&#39;인용 사이트&#39;: 내용 전체가 하나의 인용문일 경우 사용</p>
</li>
<li><p>q(quotation): 문장 내에 들어가는 인용문일 경우 사용</p>
</li>
<li><p>cite: 인용 출처</p>
</li>
<li><p>div(division): 의미가 없으나 css 스타일링에 유용</p>
</li>
<li><p>span: 의미가 없고, text level의 일부분을 grouping해 줄 때, css 스타일링에 유용</p>
</li>
<li><p>form action=&#39;&#39; method=&#39;&#39;: 사용자로부터 input을 받기 위한 태그, action=&#39;API 주소&#39;, method=&#39;get | post&#39;</p>
</li>
</ul>
<hr>
<ul>
<li><p>input type=&#39;#&#39;: type이라는 attr을 반드시 명시해야 함 (text, email, password, url, number, file ... ),</p>
</li>
<li><p>placeholder=&#39;&#39;(attr, 공란 상태 기본 문구), maxlength=&#39;&#39;(attr, 글자 수 제한),</p>
</li>
<li><p>minlength=&#39;&#39;(attr, 글자 수 제한), required(attr, 무조건 채워야 함), disabled(attr, 막아둠), value=&#39;&#39;(attr, 기본값),</p>
</li>
<li><p>max/min=&#39;&#39;(number attr, 수의 크기 제한), accept=&#39;&#39;(file attr, 확장자 제한)</p>
</li>
<li><p>label for=&#39;인풋id&#39;: 폼 양식에 이름을 붙히는 태그, for이라는 attr 명시해야 함</p>
</li>
<li><p>input type=&#39;radio&#39;: 여러 가지 항목 중에서 단 하나만 선택, label이랑 같이 쓰기, attr name=&#39;#&#39;으로 그루핑하기, value 명시</p>
</li>
<li><p>input type=&#39;check-box&#39;: 여러 가지 항목 중에서 여러 개 선택, label이랑 같이 쓰기, attr name=&#39;#&#39;으로 그루핑하기, value 명시</p>
</li>
<li><p>select: 자식 요소로 option사용, attr name은 select에만 주고 option에 value, attr multiple으로 여러 개 선택</p>
</li>
<li><p>textarea: 여러 줄에 걸쳐 글을 쓸 수 있음, attr rows=&#39;#&#39;와 attr cols=&#39;#&#39;를 통해 사이즈 조정 (css로 조정)</p>
</li>
<li><p>button: 버튼, attr type=&#39;#&#39;으로 button, submit(제출), reset(리셋) 명시</p>
</li>
</ul>
<hr>
<ul>
<li><p>table: tr으로 가로줄부터</p>
</li>
<li><p>tr (table row): table 가로줄, 상위 태그 thead로 감싸주면 좋음</p>
</li>
<li><p>th (table header): 상위 태그 tbody로 감싸주면 좋음</p>
</li>
<li><p>td (table data): 상위 태그 tbody로 감싸주면 좋음</p>
</li>
<li><p>attr rowspan=&#39;#&#39;: 여러 칸 병합, 병합된 열은 다음 행에서 생략</p>
</li>
<li><p>attr colspan=&#39;#&#39;: 여러 칸 병합</p>
</li>
<li><p>attr scope&#39;row|col&#39;: th에만 사용 가능, 브라우저에 인식 도움</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #32]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-32</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-32</guid>
            <pubDate>Mon, 17 Apr 2023 17:13:34 GMT</pubDate>
            <description><![CDATA[<h3 id="html이-왜-중요한가">HTML이 왜 중요한가</h3>
<p>브라우저를 통해 무언가를 보기 위해서는 tag로 표현되어야 함.
웹페이지라는 것은 결국 html을 통해 표현이 된다.
html이 결국 웹페이지를 통해 전달하고자 하는 모든 컨텐츠의 집합체이다.</p>
<h3 id="semantic-markup이-중요한-이유">semantic markup이 중요한 이유</h3>
<p>문서의 구조와 정보 위계가 명확하게 보이고, SEO에 도움이 된다.</p>
<p>코드를 짜는 것보다 남의 코드를 읽는 것이 더 어렵다. 본인 코드도 며칠 지나면 남의 코드가 된다.
div는 위계질서를 파악하는데 도움이 되지 않는다.
자기가 이 태그를 왜 썼는지 이해하고 있어야 한다.</p>
<blockquote>
<p>태그 안에 어떤 문자가 오느냐에 따라 markup하고 있는 정보의 성격이 달라진다.</p>
</blockquote>
<blockquote>
<p>attr(attribute):태그 하나만으로 표현할 수 없는 정보에 부가적인 정보를 추가해준다.</p>
</blockquote>
<ul>
<li><p>h1~6 (heading): 제목을 의미하며 번호순으로 중요하다.</p>
</li>
<li><p>p (paragraph): 문단 내용</p>
</li>
<li><p>em (emphasis), strong: 문장 강조</p>
</li>
<li><p>br (line break): 줄 바꿈, 남용 x</p>
</li>
<li><p>a href (anchor): 링크, href(hypertext reference)는 필수, 외부 페이지 이동, 내부 페이지 이동 (href=&#39;#id&#39;), 메일 작성 (href=&#39;mailto:메일@주소.com&#39;), 전화 걸기 (href=&#39;tel:전화번호&#39;), target=&#39;_blank&#39;라는 attr을 쓰면 새 탭에서 열기</p>
</li>
<li><p>img src=&#39;#&#39; alt=&#39;&#39;: src(source)는 이미지 주소, alt(alternative text)는 이미지에 대한 설명을 의미</p>
</li>
<li><p>ol (ordered list): 자식 요소는 무조건 li만 가능</p>
</li>
<li><p>ul (unordered list): 자식 요소는 무조건 li만 가능</p>
</li>
<li><p>li (list item): 모든 요소들을 각각 감싸줘야 함</p>
</li>
<li><p>dl (description list): 용어를 정의할 때, key-value로 정보를 제공할 때 사용, 자식 요소는 div / dt / dd만 가능</p>
</li>
<li><p>dt (description term)</p>
</li>
<li><p>dfn (definition)</p>
</li>
<li><p>dd (description data)</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[WIL #6]]></title>
            <link>https://velog.io/@kimtaehoon_98/WIL-6</link>
            <guid>https://velog.io/@kimtaehoon_98/WIL-6</guid>
            <pubDate>Sun, 19 Mar 2023 19:50:37 GMT</pubDate>
            <description><![CDATA[<h1 id="lifecycle-method">LifeCycle Method</h1>
<p>LifeCycle Method(생명주기 메서드)는 컴포넌트가 브라우저상에 나타나고, 업데이트되고, 사라질 때 호출되는 메서드들을 의미한다. 컴포넌트에서 에러가 발생했을 때 호출되는 메서드도 존재한다.
생명주기 메서드는 클래스형 컴포넌트에서만 사용할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/kimtaehoon_98/post/497d6b67-b7c7-41c7-a31d-1d4413ceb799/image.png" alt="">
출처: <a href="http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/">http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/</a></p>
<h3 id="mount생성될-때">Mount(생성될 때)</h3>
<ul>
<li>constructor: 컴포넌트 생섯ㅇ자 메서드, 컴포넌트가 생성되면 가장 먼저 실행된다. this.props,this.state에 접근이 가능하며 리액트 요소를 반환한다.</li>
<li>getDerivedStateFromProps: props로부터 파생된 state를 가져온다. 즉, props로 받아온 것을 state에 넣어준다.</li>
<li>render: 컴포넌트를 렌더링한다.</li>
<li>componentDidMount: 컴포넌트가 마운트됨, 즉 컴포넌트의 첫번째 렌더링이 끝나면 호출되는 메서드이다.
이 메서드가 호출되는 시점에는 화면에 컴포넌트가 나타난 상태이다.</li>
</ul>
<h3 id="updating업데이트할-때">Updating(업데이트할 때)</h3>
<ul>
<li>getDerivedStateFromProps: 컴포넌트의 props나 state가 바뀌었을 때도 이 메서드가 호출된다.</li>
<li>shouldComponentUpdate: 컴포넌트가 리렌더링을 할지 말지 결정하는 메서드이다.</li>
<li>componentDidUpdate: 컴포넌트가 업데이트 되고 난 후 발생한다.</li>
</ul>
<h3 id="unmount제거할-때">Unmount(제거할 때)</h3>
<ul>
<li>componentWillUnmount: 컴포넌트가 화면에서 사라지기 직전에 호출된다. 주로 DOM에 직접 등록했었던 이벤트를 제거하고, 만약에 setTimeOut을 걸은 것이 있다면 clearTimeout을 통하여 제거한다.</li>
</ul>
<hr>
<h1 id="react-hooks">React Hooks</h1>
<p>리액트에서 Hook은 함수형 컴포넌트에서 React state와 생명주기 기능을 연동할 수 있게 해주는 함수이다. Hook은 class 안에서는 동작하지 않고, class없이 React를 사용할 수 있게 한다.</p>
<h3 id="리액트-훅을-도입한-목적">리액트 훅을 도입한 목적</h3>
<ul>
<li>기존의 LifeCycle Method 기반이 아닌 로직 기반으로 나눌 수 있어서 컴포넌트를 함수 단위로 잘게 쪼갤 수 있다.</li>
<li>LifeCycle Method에는 관련 없는 로직이 자주 섞여 들어가는데, 이로 인해 버그가 쉽게 발생하고, 무결성을 쉽게 해친다.</li>
</ul>
<h3 id="hook-사용-규칙">Hook 사용 규칙</h3>
<ul>
<li>최상위에서만 Hook을 호출해야 한다.<ul>
<li>반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하면 안 된다.</li>
<li>이 규칙을 따르면 컴포넌트가 렌더링될 때마다 항상 동일한 순서로  Hook이 호출되는 것이 보장된다.</li>
</ul>
</li>
<li>리액트 함수 컴포넌트에서만 Hook을 호출해야한다.<ul>
<li>일반 JS함수에서는 Hook을 호출해서는 안된다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #31]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-31</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-31</guid>
            <pubDate>Fri, 17 Mar 2023 18:37:19 GMT</pubDate>
            <description><![CDATA[<h1 id="rest-api">REST API</h1>
<p>REST(Representational State Transfer) API는 다음의 구성으로 이루어져 있다.</p>
<ul>
<li>자원(Resource): URL</li>
<li>행위(Verb): HTTP METHOD</li>
<li>표현(Representations)</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li><p>Uniform (유니폼 인터페이스)
Uniform Interface는 URL로 지저한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일이다.</p>
</li>
<li><p>Stateless (무상태성)
REST는 무상태성 성격을 갖는다. 다시 말해 작업을 위한 상태 정보를 따로 저장하고 관리하지 않는다. 세션 정보나 쿠키 정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 된다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해진다.</p>
</li>
<li><p>Cacheable (캐시 가능)
REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹 표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능하다. 따라서 HTTP가 가진 캐싱 기능이 적용 가능하다. HTTP 프로토콜 표준에서 사용하는 Last-Modified 태그나 E-Tag를 이용하면 캐싱 구현이 가능하다.</p>
</li>
<li><p>Self-descriptiveness (자체 표현 구조)
REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조로 되어 있다는 것이다.</p>
</li>
<li><p>Client-Server 구조
REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트 (세션, 로그인 정보) 등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어든다.</p>
</li>
<li><p>계층형 구조
REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간 매체를 사용할 수 있게 한다.</p>
</li>
</ul>
<h3 id="rest-api-설계">REST API 설계</h3>
<ol>
<li>URL은 정보의 자원을 표현해야 한다.</li>
<li>자원에 대한 행위는 HTTP Method (GET, POST, PUT, DELETE)로 표현한다.</li>
</ol>
<pre><code>get /api/posts
</code></pre><p>POST, GET, PUT DELETE 를 통해 CRUD를 구현할 수 있다.</p>
<ul>
<li>POST: 해당 URL을 요청하면 리소스를 생성한다.</li>
<li>GET: 해당 리소스를 조회한다. 리소스를 조회하고 해당 document에 대한 자세한 정보를 가져온다.</li>
<li>PUT: 해당 리소스를 수정한다.</li>
<li>DELETE: 해당 리소스를 삭제한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #30]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-30</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-30</guid>
            <pubDate>Thu, 16 Mar 2023 16:40:59 GMT</pubDate>
            <description><![CDATA[<h1 id="thunk와-인증인가">Thunk와 인증/인가</h1>
<h3 id="redux-미들웨어">Redux 미들웨어</h3>
<p>리덕스에서 dispatch를 하면 action이 reducer로 전달이 되고, reducer는 새로운 state를 반환한다.
미들웨어를 사용하면 이 과정 사이에 우리가 하고 싶은 작업들을 넣어서 할 수 있다.</p>
<p>보통 Redux 미들웨어를 사용하는 이유는 서버와의 통신을 위해서 사용하는 것이 대부분이고, 또한 그 중에서도 많이 사용되고 있는 Redux 미들웨어는 Redux-thunk라는 것이 있다.</p>
<h3 id="thunk">Thunk</h3>
<p>Redux-Thunk란 Redux에서 많이 사용하고 있는 미들웨어 중 하나이다.
<em><strong>thunk를 사용하면 우리가 dispatch를 할 때 객체가 아닌 함수를 dispatch 할 수 있게 해준다.</strong></em> 즉 dispatch(객체)가 아니라 dispatch(함수)를 할 수 있게 되는 것이다.</p>
<pre><code>dispatch(함수) → 함수실행 → 함수안에서 dispatch(객체)</code></pre><p>RTK에서 thunk 함수를 생성할 때는 createAsyncThunk를 이용한다. 이 때 createAsyncThunk()의 첫 번째 자리에는 action value, 두 번째에는 함수가 들어간다.
두 번째로 들어가는 함수에서 2개의 인자를 꺼내 사용할 수 있는데, 첫 번째 인자는 component에서 보내준 payload이고, 두 번째 인자는 thunk에서 제공하는 여러가지 기능이다.</p>
<h3 id="인증--인가">인증 / 인가</h3>
<p><img src="https://velog.velcdn.com/images/kimtaehoon_98/post/9ace3d70-58de-49cb-8b78-9d06be7c3a2c/image.png" alt=""></p>
<ul>
<li>인증(Authentication)이란 서비스를 이용하려는 유저가 등록된 회원인지 확인하는 절차이다.</li>
<li>인가(Authorization)이란 특정 리소스에 접근할 수 있는 권한이 있는지 확인하는 절차이다.</li>
</ul>
<blockquote>
<h4 id="http-프로토콜-통신의-특징-2가지">http 프로토콜 통신의 특징 2가지</h4>
<p>무상태(Stateless): 서버는 클라이언트의 상태를 기억하지 않는다. 따라서 각 요청마다 서버에서 요구하는 모든 상태 정보를 담아서 요청해야 한다.</p>
</blockquote>
<ul>
<li>상태값은 매 요청마다 클라이언트가 가지고 오기 때문에, 서버는 클라이언트의 상태를 별도로 기억할 필요 없이 주문받은 대로 응답해준다.</li>
<li>무상태라는 특성 덕분에 동일한 서버를 여러 개로 확장시킬 수 있다. (Scale-Out)<blockquote>
</blockquote>
비연결성(Connectionless): 서버와 클라이언트는 연결되어 있지 않다. 서버 입장에서는 매번 새로운 요청이다.</li>
<li>비연결성으로 인해 최소한의 서버 자원으로 서버를 유지할 수 있게 해준다.</li>
<li>그러나, 각 사용자별 요청이 잦은 서비스의 경우 이러한 비연결성은 오히려 비효율적일 수 있다.</li>
</ul>
<h3 id="쿠키-세션-토큰">쿠키, 세션, 토큰</h3>
<h4 id="쿠키란">쿠키란?</h4>
<ul>
<li>무상태와 비연결성이라는 http 통신의 특징에도 불구하고, 마치 서버가 클라이언트의 인증 상태를 기억하는 것처럼 구현할 수 있는 수단으로 사용할 수 있다.</li>
<li>쿠키란 브라우저에 저장되는 텍스트 파일이며, key-value 형태로 저장된다.</li>
<li>쿠키는 별도로 삭제 처리하거나 유효기간이 만료되지 않는 이상 서버와 통신할 때 자동으로 주고 받게 된다.</li>
<li>서버에 특정 API 요청을 했을 때 서버가 응답 시 header 안에 set-cookie 속성으로 쿠키 정보를 담아주면 응답을 받은 브라우저는 쿠키를 브라우저에 자동으로 저장한다. (저장된 쿠키 정보는 &#39;개발자 도구 =&gt; 애플리케이션 =&gt; 저장용량 =&gt; 쿠키&#39;에서 확인 가능)</li>
<li>서버에 http 요청을 할 때마다 브라우저에 저장되어 있는 쿠키는 자동으로 서버에 보내진다. (단, 동일한 Origin 또는 CORS를 허용하는 Origin에만 쿠키를 보낸다. ex- 유튜브 서버에서 받은 쿠키는 유튜브 이용 시에만 주고 받을 수 있다.)</li>
<li>쿠키는 클라이언트에서 직접 추가/수정/삭제할 수 있다.<blockquote>
<p>Origin: 출처(Origin)이란 protocol + host + port를 의미한다.
CORS: Cross Origin Resource Sharing은 다른 출처에 리소스를 요청하는 것을 허용하는 정책이다. 브라우저는 보안상의 이유로 기본적으로 Same Origin Policy(SOP)를 원칙으로 하고 있지만, 서버와 클라이언트 각각 CORS 설정을 통해 상호합의된 웹사이트는 예외적으로 서로 다른 출처(Cross-Origin)임에도 API 요청이 가능하다.</p>
</blockquote>
</li>
</ul>
<h4 id="세션이란">세션이란?</h4>
<ul>
<li>세션이란 사용자와 서버간의 연결이 활성화된 상태를 의미하는 개념이다. (또는 인증이 유지되고 있는 상태)</li>
<li>로그인 성공 -&gt; 서버에서 세션 생성 및 저장 (key-value 형식) -&gt; key(sessionID)를 브라우저에 응답 (by 쿠키)</li>
</ul>
<h4 id="쿠키-세션-인증-방식">쿠키-세션 인증 방식</h4>
<ul>
<li><p>로그인/회원가입 시 세션 인증
<img src="https://velog.velcdn.com/images/kimtaehoon_98/post/e26b157d-6f09-4a19-99fc-9cd6a1a0cd2a/image.png" alt=""></p>
</li>
<li><p>로그인/회원가입 성공 시 서버에서 쿠키에 sessionID를 담아서 보내준다.</p>
</li>
<li><p>세션 유지 상태: 서버에서 관리하는 세션 저장소에 회원 데이터가 있다.</p>
</li>
<li><p>세션 만료 상태: 서버에서 관리하는 세션 저장소에 회원 데이터가 없다.</p>
</li>
<li><p>인가(Authorization)필요한 API 요청/응답!
<img src="https://velog.velcdn.com/images/kimtaehoon_98/post/56739d48-2bde-45e6-a704-4fae86112cc1/image.png" alt=""></p>
</li>
<li><p>서버는 인가가 필요한 API 요청을 받으면 클라이언트 쿠키에 들어있는 sessionID를 세션 저장소에 조회하여 있으면 DB에 데이터를 조회하여 응답한다.</p>
</li>
</ul>
<h4 id="토큰이란">토큰이란?</h4>
<ul>
<li>클라이언트에서 보관하는 암호화된 인증 정보를 의미한다.</li>
<li>세션처럼 서버에서 사용자의 인증 정보를 보관할 필요가 없기 때문에 서버 부담을 줄여주는 인증 수단이다.</li>
<li>웹에서 인증 수단으로 사용되는 토큰은 주로 JWT(Json Web Token)을 이용한다.</li>
</ul>
<blockquote>
<p>JWT</p>
</blockquote>
<ol>
<li>header.payload.signature 형식으로 3가지 데이터로 구성되어 있다.</li>
<li>국제 인터넷 표준 인증 규격 중 하나이다.</li>
<li>암호화된 토큰을 누구나 복호화하여 payload를 볼 수 있다. -&gt; 토큰의 용도는 인증 정보(payload)에 대한 보호가 아니라 위조 방지이다.<blockquote>
<ol start="4">
<li>정보(payload)를 토큰화할 때 signature에 secret key가 필요하고, secret key는 복호화가 아니라 토큰이 유효한지를 검증하는 데 사용된다.</li>
</ol>
</blockquote>
</li>
</ol>
<h4 id="jwt-토큰-인증-방식">JWT 토큰 인증 방식</h4>
<ol>
<li>JWT 토큰 인증 방식</li>
</ol>
<ul>
<li><p>로그인/회원가입 시 토큰 인증</p>
</li>
<li><p>인가(Authorization) 필요한 API 요청/응답</p>
</li>
<li><p>Refresh Token으로 보안 강화
리소스 접근 인가를 받기 위해 사용되는 토큰을 Access Token이라 부른다.
Access Token의 만료기간을 길게 잡고 인증 상태를 오래 가져갈 경우, 서버 부담은 줄어드나 보안성(탈취당할 경우)에 허점이 있다.
인증 보안이 중요한 서비스의 경우 인증 시 2개의 토큰 (Access Token, Refresh Token)을 발급하고 Access Token의 기간은 30분 정도로 짧게 가져가고, Refresh Token은 1~2주 정도로 길게 잡는 경우가 많다.
이 경우 서버에서는 Access Token이 만료되었을 때 Refresh Token이 유효한 상태면 새로운 Access Token을 클라이언트에 발급해주고 인증 상태를 유지할 수 있도록 하고, Refresh Token 만료 시 다시 로그인하라는 메시지를 응답한다.</p>
</li>
</ul>
<ol start="2">
<li>세션 인증 vs 토큰 인증</li>
</ol>
<ul>
<li>세션 인증: 서버에 인증 정보 저장, 확장성(Scale-Out) 나쁨, 보안성(상대적) 좋음, 비용(상대적) 비쌈</li>
<li>토큰 인증: 클라이언트에 인증 정보 저장, 확장성(Scale-Out) 좋음, 보안성(상대적) 나쁨, 비용(상대적) 저렴함</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #29]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-29</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-29</guid>
            <pubDate>Wed, 15 Mar 2023 19:37:47 GMT</pubDate>
            <description><![CDATA[<h1 id="objectkeys-values-entries">Object.keys, values, entries</h1>
<p>keys(), values(), entries()를 사용할 수 있는 자료구조는 다음과 같다.</p>
<ul>
<li>Map</li>
<li>Set</li>
<li>Array</li>
</ul>
<p>일반 객체엔 다음과 같은 메서드를 사용할 수 있다.</p>
<ul>
<li>Object.keys(obj)-객체의 키만 담은 배열을 반환한다.</li>
<li>Object.values(obj)-객체의 값만 담은 배열을 반환한다.</li>
<li>Object.entries(obj)-[키, 값] 쌍을 담은 배열을 반환한다.</li>
</ul>
<p>Map, Set, Array 전용 메서드와 일반 객체용 메서드의 차이를 비교하면 다음과 같다.</p>
<ol>
<li><p>obj.keys()가 아닌 Object.keys(obj)를 호출한다.
이렇게 문법이 다른 이유는 유연성 때문이다. JS에서는 복잡한 자료구조 전체가 객체에 기반하기 때문에 객체 data에 자체적으로 data.values()라는 메서드를 구현해 사용하는 경우가 있을 수 있다. 이렇게 커스텀 메서드를 구현한 상태라도 Object.values(data)같은 형태로 메서드를 호출할 수 있으면 커스텀 메서드와 내장 메서드 둘 다를 사용할 수 있다.</p>
</li>
<li><p>메서드 Object.*를 호출하면 iterable 객체가 아닌 객체의 한 종류인 배열을 반환한다는 점이다. &#39;진짜&#39;배열을 반환하는 이유는 하위 호환성 때문이다.</p>
</li>
</ol>
<h2 id="객체-변환">객체 변환</h2>
<p>객체엔 map, filter 같은 배열 전용 메서드를 사용할 수 없다.
하지만 Object.entries와 Object.fromEntries를 순차적으로 적용하면 객체에도 배열 전용 메서드를 사용할 수 있다.</p>
<ol>
<li>Object.entries(obj)를 사용해 객체의 키-값 쌍이 요소인 배열을 얻는다.</li>
<li>1에서 만든 배열에 map등의 배열 전용 메서드를 적용한다.</li>
<li>2에서 반환된 배열에 Object.fromEntries(array)를 적용해 배열을 다시 객체로 되돌린다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #28]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-28</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-28</guid>
            <pubDate>Tue, 14 Mar 2023 19:00:54 GMT</pubDate>
            <description><![CDATA[<p>본격적인 복습을 하는 중이다. 어제 TIL을 못 쓴 핑계를 대자면 복습하느라 피곤했다.</p>
<h2 id="1-component">1. Component</h2>
<ul>
<li>&#39;props&#39;가 input, return이 output</li>
<li>제목은 대문자로 시작</li>
<li>함수가 시작되는 부분부터 return 사이는 JavaScript 영역</li>
<li>return문 안쪽은 JSX(JavaScript + XML)문법, 이 안에서 JS문법은 {} 안에서 쓴다. (key, value페어의 객체가 들어갈 경우 {{ }}형태가 된다.)</li>
</ul>
<h2 id="2-props">2. Props</h2>
<ul>
<li>위에서 아래로, 부모에서 자식으로 (단방향)</li>
<li>읽기 전용</li>
<li>여는 태그, 닫는 태그 사이에 어떤 값이 있으면 React는 자동적으로 children이라는 props를 가지고 있다.</li>
<li>단순히 props라고 쓰여 있으면 내용물을 모르므로 구조분해할당으로 찢어놓는 것이 좋다.</li>
</ul>
<h2 id="3-usestate">3. useState</h2>
<ul>
<li>기본적인 형태는<pre><code>const [state, setState] = useState(initialState);</code></pre></li>
<li>state를 변수로 사용하고, setState를 이용해서 state값을 수정할 수 있다.</li>
<li>만약 state가 원시 데이터 타입이 아닌 객체 데이터 타입일 경우 불변성을 유지해줘야 한다.</li>
<li>함수형 컴포넌트 내에서 가변적인 상태를 갖게 한다.</li>
<li>setState를 사용하는 방식에는 두 가지가 있다.<pre><code>// 기존에 사용하던 방식
setState(number + 1);
</code></pre></li>
</ul>
<p>// 함수형 업데이트 
setState(() =&gt; {});</p>
<p>```
위 코드와 같이 setState의 ()안에 수정할 값이 아니라 함수를 넣을 수 있다. 그리고 그 함수의 인자 안에서는 현재의 state를 가져올 수 있고, {} 안에서는 이 값을 변경하는 코드를 작성할 수 있다.</p>
<ul>
<li>일반 업데이트 방식은 명령을 하나로 모아 최종적으로 한 번만 실행을 한다. 반면 함수형 업데이트 방식은 명령을 모아 순차적으로 각각 1번씩 실행을 시킨다.</li>
</ul>
<h2 id="4-useeffect">4. useEffect</h2>
<ul>
<li>렌더링 될 때, 특정한 작업을 수행해야 할 때 설정하는 훅이다. (컴포넌트가 화면에서 보여졌을/사라졌을 때)</li>
<li>의존성 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[WIL #5]]></title>
            <link>https://velog.io/@kimtaehoon_98/WIL-5</link>
            <guid>https://velog.io/@kimtaehoon_98/WIL-5</guid>
            <pubDate>Sun, 12 Mar 2023 10:03:01 GMT</pubDate>
            <description><![CDATA[<p>최근 급하게 쌓아온 모래성같은 실력이 손 틈새로 빠져나가는 느낌을 지울 수 없다.
그런 이유로 흐릿해진 중요 개념들을 복기해야겠다는 생각이 들었다.</p>
<h2 id="props">Props</h2>
<ul>
<li>props는 프로퍼티(properties)의 준말이다.</li>
<li>상위 컴포넌트가 하위 컴포넌트에 값을 전달할 때 사용한다. (단방향 데이터 흐름)</li>
<li>수정할 수 없다는 특징이 있다. (자식 입장에서는 읽기 전용 데이터이다.)</li>
<li>문자열을 전달할 때는 &quot;&quot;를, 문자열 외의 값을 전달할 때는 {}를 사용한다.</li>
</ul>
<h2 id="state">State</h2>
<p>state는 컴포넌트의 현재 상황에 대한 정보를 나타내기 위해 리액트에서 쓰는 일반 JavaScript 객체다. setState()는 컴포넌트의 state 객체에 대한 업데이트를 실행한다. state가 변경되면, 컴포넌트는 리렌더링된다.</p>
<h4 id="state와-props의-차이점">state와 props의 차이점</h4>
<p>props와 state는 일반 JavaScript 객체이다. 두 객체 모두 렌더링 결과물에 영향을 주는 정보를 갖고 있는데, 한 가지 중요한 방식에서 차이가 있다. props는 (함수 매개변수처럼) 컴포넌트에 전달되는 반면, state는 (함수 내에 선언된 변수처럼)컴포넌트 안에서 관리된다.
그 외에도
<img src="https://velog.velcdn.com/images/kimtaehoon_98/post/09f60511-6692-40bd-bdbe-a76f917ea671/image.png" alt="">
의 차이점이 있다.</p>
<h2 id="children">Children</h2>
<p>공식 문서에 따르면 props.children이란</p>
<blockquote>
<p>&#39;어떤 컴포넌트들은 어떤 자식 엘리먼트가 들어올지 미리 예상할 수 없는 경우가 있습니다. 범용적인 &#39;박스&#39; 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트에서 특히 자주 볼 수 있습니다.&#39;</p>
</blockquote>
<p>여기서 말하는 범용적인 &#39;박스&#39;역할을 하는 컴포넌트란 크게 봤을 때 Layout 역할을 하는 컴포넌트이다.</p>
<h2 id="usestate">useState</h2>
<p>useState는 가장 기본적인 hook이며, 함수 컴포넌트에서 가변적인 상태를 가지게 해 준다. useState의 기본적인 형태는 아래와 같다.</p>
<pre><code>const [state, setState] = useState(initialState);</code></pre><p>원래는 useState라는 함수가 배열을 반환하고, 이것을 구조 분해 문법으로 꺼내놓은 모습이다. state를 변수로 사용하고, setState를 이용해서 state값을 수정할 수 있다. <strong>만약 state가 원시 데이터타입이 아닌 객체 데이터 타입인 경우 불변성을 유지해줘야 한다.</strong></p>
<p>setState를 사용하는 방식에는 우리가 알고 있는 방식이 아닌 또 다른 방식이 있다. 바로 함수형 업데이트 방식이다.</p>
<pre><code>// 기존에 우리가 사용하던 방식
setState(number + 1);

// 함수형 업데이트 
setState(() =&gt; {});</code></pre><p>위 코드와 같이 setState의 ()안에 수정할 값이 아니라 함수를 넣을 수 있다. 그리고 그 함수의 인자 안에서는 현재의 state를 가져올 수 있고, {} 안에서는 이 값을 변경하는 코드를 작성할 수 있다.</p>
<pre><code>// 현재 number의 값을 가져와서 그 값에 +1을 더하여 반환한 것 입니다.
setState((currentNumber)=&gt;{ return currentNumber + 1 });</code></pre><p>일반 업데이트 방식은 명령을 하나로 모아 최종적으로 한 번만 실행을 한다.
반면 함수형 업데이트 방식은 명령을 모아 순차적으로 각각 1번씩 실행을 시킨다.
공식 문서에 따르면, &#39;리액트는 성능을 위해 setState()를 단일 업데이트(batch update)로 한꺼번에 처리할 수 있다.&#39;</p>
<h2 id="useparams">useParams</h2>
<p>useParams를 이용하면 같은 컴포넌트를 렌더링하더라도 각각의 고유한 id값을 조회할 수 있다.
만약 우리가 works/1로 이동하면 1이라는 값을 주고, works/100으로 이동하면 100이라는 값을 사용할 수 있게 해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #27]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-27</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-27</guid>
            <pubDate>Sat, 11 Mar 2023 19:26:24 GMT</pubDate>
            <description><![CDATA[<h2 id="redux-toolkit">Redux Toolkit</h2>
<p>리덕스 툴킷은 리덕스를 개량한 것으로 생각하면 된다.
리덕스를 사용하기 위해 작성했던 ducks 패턴의 요소들이 전체적인 코드의 양을 늘린다는 개발자들의 불만이 발생했고, 리덕스 팀에서는 이것을 수용하여 코드는 더 적게, 그리고 리덕스를 더 편하게 쓰기 위한 가능들을 흡수해서 만든 것이 리덕스 툴킷이다. 줄여서 RTK라고도 한다.</p>
<p>기존 리덕스와 비교했을 때 구조와 패러다임이 같다. 다만 전체 코드의 양을 줄이기 위해 새로운 API가 추가되었고, ducks 패턴의 요소들이 어느 정도 자동화되었다.</p>
<p><strong>또한 큰 차이점으로 Action Value와 Action Creator를 이제 직접 생성해주지 않고, Action Value, Action Creator, Reducer가 하나로 합쳐졌다는 점이 있다.</strong></p>
<hr>
<h3 id="slice">Slice</h3>
<p>그리고 Slice라는 새로운 API가 추가되었다.
Slice는 createSlice라는 API를 통해 만들 수 있다. 인자로 설정정보를 객체로 받는데, 그 안에 우리가 필수로 작성해줘야 하는 값으로는 name, initialState, reducers가 있다.</p>
<pre><code>//createSlice API 뼈대

const testSlice = createSlice({
    name: &#39;&#39;, // 이 모듈의 이름
    initialState : {}, // 이 모듈의 초기상태 값
    reducers : {}, // 이 모듈의 Reducer 로직
})</code></pre><p>counterSlice 리듀서 객체 안에서 만들어주는 함수는 리듀서의 로직이 되면서 동시에 Action Creator가 된다. 그리고 Action Value까지 함수의 이름을 따서 자동으로 만들어진다. 그러므로 우리는 Reducer만 만들어주면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #26]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-26</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-26</guid>
            <pubDate>Fri, 10 Mar 2023 17:37:30 GMT</pubDate>
            <description><![CDATA[<h1 id="axios-fetch">Axios, Fetch</h1>
<h3 id="axios란">Axios란?</h3>
<p>Axios는 node.js와 브라우저를 위한 Promise 기반 HTTP 클라이언트이다. 동일한 코드베이스로 브라우저와 node.js에서 실행할 수 있다. 서버 사이드에서는 네이티브 node.js의 http 모듈을 사용하고, 클라이언트(브라우저)에서는 XMLHttpRequests를 사용한다.</p>
<ul>
<li>Promise: 비동기 처리에 활용되는 객체</li>
<li>XMLHttpRequest(XHR): 서버와 상호작용할 때 사용되는 객체. XHR을 사용하면 페이지의 새로고침 없이도 URL에서 데이터를 가져올 수 있다. 이를 활용하면 사용자의 작업을 방해하지 않고 페이지의 일부를 업데이트할 수 있다. AJAX 프로그래밍에 많이 사용된다.</li>
</ul>
<h3 id="특징">특징</h3>
<ul>
<li>브라우저를 위해 XMLHttpRequests 생성</li>
<li>node.js를 위해 http요청 생성</li>
<li>Promise API를 지원</li>
<li>요청 및 응답 인터셉트</li>
<li>요청 및 응답 데이터 변환</li>
<li>요청 취소</li>
<li>JSON 데이터 자동 변환</li>
<li>XSRF를 막기 위한 클라이언트 사이드 지원</li>
</ul>
<hr>
<h3 id="get">GET</h3>
<p>GET은 서버의 데이터를 조회할 때 사용한다. 기본적인 사용방법은 아래와 같다.</p>
<pre><code>// url에는 서버의 url이 들어가고, config에는 기타 여러가지 설정을 추가할 수 있다.
// config는 axios 공식 문서에서 확인 가능하다.

axios.get(url[, config]) //GET</code></pre><p>Axios를 사용해서 GET 요청 코드를 작성하기에 앞서, 어떤 방식으로 요청해야 할지는 우리가 사용하는 json-server의 방식을 알아야 한다.</p>
<blockquote>
<p>다시 말해, _<strong>Axios는 GET 요청을 할 수 있도록 도와주는 패키지일 뿐이지, &#39;어떻게 요청을 해야하지?&#39;와 같은 방식에 대한 확인은 우리가 사용할 API 명세서를 보아야 한다</strong>_는 뜻이다.</p>
</blockquote>
<p>예를 들어, GET 요청을 할 때 path variable로 해야할지, query로 보내야할지는 API를 만든 사람이 하라는 대로 해야 하기 때문이다.</p>
<p>json-server의 공식 문서를 보면, 전체 정보나 상세 정보는 path variable로 url을 작성해야 하고,
filter와 같은 기능을 위해서 GET요청을 할 때는 query로 보내라고 명시되어 있다.</p>
<hr>
<h3 id="post">POST</h3>
<pre><code>axios.post(url[, data[, config]])   // POST</code></pre><p>POST는 보통 서버에 데이터를 추가할 때 사용한다. 다만 post 요청에 대한 로직은 BE 개발자가 구현하는 것이기 때문에 추가 외에 다른 용도로 사용될 수 있지만, 보통은 클라이언트의 데이터를 body 형태로 서버에 보내고자 할 때 사용한다.</p>
<blockquote>
<p><em><strong>네트워크 쪽 개발을 할 때는 항상 브라우저에 있는 네트워크 탭을 확인하면서 개발을 진행해야 한다.
어떤 문제가 생겼을 때 이 정보를 통해 디버깅을 할 수 있기 때문이다.</strong></em></p>
</blockquote>
<ol>
<li>headers</li>
</ol>
<ul>
<li>Request URL을 통해서 우리가 의도한 URL로 post 요청을 보냈음을 알 수 있다.</li>
<li>Request Method를 동해서 우리가 POST 메서드를 사용했음을 알 수 있다.</li>
<li>Status Code는 자동으로 생서오디는 것이 아니라 BE개발자가 직접 개발을 하고 설정한 code가 브라우저에 보이게 된다. 그래서 <strong>만약 BE개발자가 구현을 해놓지 않았다면 문맥과 다른 status code가 브라우저에 보일 수 있다.</strong></li>
</ul>
<ol start="2">
<li>payload</li>
</ol>
<ul>
<li>payload에서는 우리가 보낸 body를 확인할 수 있다.</li>
</ul>
<ol start="3">
<li>response</li>
</ol>
<ul>
<li>response에서는 우리가 보낸 post에 요청에 대한 서버의 응답값을 확인할 수 있다. 이 response값은 자동으로 생성되는 것이 아니라, FE개발자가 BE개발자에게 요청한 것을 직접 개발을 해야 생기는 값이다. json-server의 경우 POST 요청을 했을 때, 클라이언트가 보낸 body를 그대로 응답해주도록 만들어진 패키지이다.</li>
</ul>
<hr>
<h3 id="delete">DELETE</h3>
<p>DELETE는 저장되어 있는 데이터를 삭제하고자 요청을 보낼 때 사용한다.</p>
<pre><code>axios.delete(url[, config])  // DELETE</code></pre><hr>
<h3 id="patch">PATCH</h3>
<p>PATCH는 보통 어떤 데이터를 수정하고자 서버에 요청을 보낼 때 사용하는 메서드이다. 다만, 이것은 http 환경에서 서로가 한 약속이자 문맥이기 때문에, 수정을 하고자 반드시 patch, put을 써야만 하는 것은 아니다. BE에 의한 POST를 통해서 &#39;수정&#39;이라는 기능은 충분히 만들 수 있기 때문이다. 다만 이러한 약속을 대부분의 개발자들이 지키고 있다.</p>
<pre><code>axios.patch(url[, data[, config]])  // PATCH</code></pre><hr>
<h2 id="env">.env</h2>
<p>.env는 API key, port, DB 등 민감한 정보를 환경변수에 담아 관리하는 방법이다.</p>
<h4 id="주의사항">주의사항</h4>
<ul>
<li>root 폴더에 env 파일이 위치하지 않으면 정상적으로 작동하지 않는다.</li>
<li>변수명이 &#39;REACT_APP_&#39;으로 시작하지 않으면 React가 인식하지 못하여 정상적으로 작동하지 않는다.</li>
<li>.gitignore에 등록해주어야 git에 등록할 때 파일이 올라가지 않는다.</li>
</ul>
<h4 id="사용법">사용법</h4>
<ul>
<li>root 폴더에 .env 파일을 생성한다.</li>
<li>key, value 형식으로 환경변수를 입력해준다. 이 때 key 앞에 무조건 &#39;REACT_APP_&#39;을 붙혀야 한다.</li>
<li>소스코드에서 import 없이 process.env.REACT _ APP__ 변수명으로 불러와 적용한다. (뒤 언더바 1칸)</li>
<li>env의 값을 변경하여 적용하고 싶다면 변경 후 server를 다시 실행시켜주어야 한다.</li>
</ul>
<hr>
<h3 id="fetch">Fetch</h3>
<p>Fetch는 ES6부터 도입된 JavaScript 내장 라이브러리이다. Promise 기반 비동기 통신 라이브러리며, axios처럼 데이터를 다루기 쉽고, 내장 라이브러리이기 때문에 별도의 설치 및 import를 필요로 하지 않는다.
하지만 다음과 같은 단점을 가진다.</p>
<ul>
<li>미지원 브라우저 존재</li>
<li>개발자에게 불친절한 response</li>
<li>axios에 비해 부족한 기능</li>
</ul>
<h4 id="fetch와-axios의-차이">fetch와 axios의 차이</h4>
<p>CASE 1. 데이터 읽어오기</p>
<p>(1) fetch</p>
<pre><code>const url = &quot;https://jsonplaceholder.typicode.com/todos&quot;;

fetch(url)
.then((response) =&gt; response.json())
.then(console.log);</code></pre><ul>
<li>fetch().then을 한 상태여도 여전히 JSON 포맷의 응답이 아니기 때문에 response.json()을 한 번 더 해주는 과정이 필요하다.</li>
<li>따라서, fetch로 데이터를 요청하는 경우 두 개의 .then()이 필요하다.</li>
</ul>
<p>(2) axios</p>
<pre><code>const url = &quot;https://jsonplaceholder.typicode.com/todos&quot;;

axios.get(url).then((response) =&gt; console.log(response.data));</code></pre><ul>
<li>axios는 response를 기본적인 JSON 포맷으로 제공한다. 우리는 단순히 response.data로 사용한다.</li>
</ul>
<p>CASE 2. 에러 처리</p>
<p>(1) fetch</p>
<pre><code>const url = &quot;https://jsonplaceholder.typicode.com/todos&quot;;

fetch(url)
  .then((response) =&gt; {
    if (!response.ok) {
      throw new Error(
        `This is an HTTP error: The status is ${response.status}`
      );
    }
    return response.json();
  })
  .then(console.log)
  .catch((err) =&gt; {
    console.log(err.message);
  });</code></pre><p>fetch의 경우, catch()가 발생하는 경우는 오직 네트워크 장애 케이스이다. 따라서 개발자가 일일히 then() 안의 모든 케이스에 대한 HTTP 에러 처리를 해야한다.</p>
<p>(2) axios</p>
<pre><code>const url = &quot;https://jsonplaceholder.typicode.com/todos&quot;;

axios
  .get(url)
  .then((response) =&gt; console.log(response.data))
  .catch((err) =&gt; {
    console.log(err.message);
  });</code></pre><ul>
<li>axios.get() 요청이 반환하는 Promise 객체가 갖고 있는 상태코드가 2xx의 범위를 넘어가면 reject를 한다.</li>
<li>따라서, 곧바로 catch() 부분을 통해 error handling이 가능하다. 예시는 다음과 같다.<pre><code>const url = &quot;https://jsonplaceholder.typicode.com/todos&quot;;
</code></pre></li>
</ul>
<p>// axios 요청 로직
axios
  .get(url)
  .then((response) =&gt; console.log(response.data))
    .catch((err) =&gt; {</p>
<pre><code>    // 오류 객체 내의 response가 존재한다 = 서버가 오류 응답을 주었다    
    if (err.response) {

    const { status, config } = err.response;

        // 없는 페이지
    if (status === 404) {
      console.log(`${config.url} not found`);
    }

        // 서버 오류
    if (status === 500) {
      console.log(&quot;Server error&quot;);
    }

    // 요청이 이루어졌으나 서버에서 응답이 없었을 경우
  } else if (err.request) {
    console.log(&quot;Error&quot;, err.message);
    // 그 외 다른 에러
  } else {
    console.log(&quot;Error&quot;, err.message);
  }
});</code></pre><p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #25]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-25</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-25</guid>
            <pubDate>Thu, 09 Mar 2023 18:03:15 GMT</pubDate>
            <description><![CDATA[<p>useSelector에 대해 다시금 생각해보는 시간을 전 조원들과 함께 가졌다.
<img src="https://velog.velcdn.com/images/kimtaehoon_98/post/683b56cb-7526-4486-9c71-28ba7a037d9f/image.png" alt="">
정리를 하고 나니 원리가 머릿속에 좀 더 명료하게 그려졌다.
여러 번 써보면서 익숙해지는 건 별개의 문제지만...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #24]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-24</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-24</guid>
            <pubDate>Wed, 08 Mar 2023 09:56:24 GMT</pubDate>
            <description><![CDATA[<p>새 TodoList를 실행하는데 오류가 났다.</p>
<p>Can&#39;t resolve &#39;react-redux&#39;</p>
<p>구글링을 해보니 대체로 yarn 이용자는 node_modules 폴더와 yarn.lock, npm이용자는 node_modules 폴더와 package.lock.json파일을 지운 후 각각 install을 다시 해보라고 되어 있었다.</p>
<p>먼저 yarn을 재설치 했는데 실패했다.
그래서 혹시 몰라 npm도 재설치 후 실패했다.</p>
<p>가만 생각해보다... 혹시나 redux 자체를 제대로 깐 것이 아닐 수도 있다는 생각이 들었다.</p>
<p>그래서 yarn add redux, yarn add react-redux를 다시 실행했더니 다행히 해당 오류는 사라졌다.</p>
<p>react-id-generator도 오류가 떴었는데 yarn add react-id-generator로 해결했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #23]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-23</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-23</guid>
            <pubDate>Tue, 07 Mar 2023 17:10:54 GMT</pubDate>
            <description><![CDATA[<h2 id="동기synchronous적-방식">동기(Synchronous)적 방식</h2>
<blockquote>
<p>현재 실행중인 코드가 끝나야 다음 코드를 실행하는 방식, 일반적인 프로그래밍 세계에서는 코드는 모두 동기적으로 실행된다. 즉, 앞선 코드가 끝나야만 그 다음 코드가 수행이 된다.</p>
</blockquote>
<h2 id="비동기asynchronous적-방식">비동기(Asynchronous)적 방식</h2>
<p>실행중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어가는 방식</p>
<blockquote>
<ul>
<li>setTimeout, addEventListner 등</li>
</ul>
</blockquote>
<ul>
<li>별도의 요청, 실행 대기, 보류 등과 같은 코드는 모두 비동기적 코드</li>
<li>대표적으로 서버 통신과 관련된 로직들 포함</li>
</ul>
<p><img src="https://velog.velcdn.com/images/kimtaehoon_98/post/044888cd-4091-44ac-9c19-d40c5008c6fd/image.png" alt=""></p>
<h2 id="콜백지옥">콜백지옥</h2>
<blockquote>
<ul>
<li>콜백 함수를 익명 함수로 전달하는 과정이 반복되어 코드의 들여쓰기 수준이 헬 수준인 경우</li>
</ul>
</blockquote>
<ul>
<li>주로 이벤트 처리 및 서버 통신과 같은 비동기적 작업을 수행할 때 발생한다.</li>
<li>가독성 하락, 수정이 어렵다.</li>
<li>이를 극복하기 위해 then ~ catch, async / await 등장하였다.</li>
</ul>
<h2 id="promise">Promise</h2>
<blockquote>
<ul>
<li>Promise 객체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타낸다.</li>
</ul>
</blockquote>
<ul>
<li>Promise 객체에 담기는 주요한 상태정보<ol>
<li>대기(pending): localhost에서 서버에 요청을 한 직후. 아직 성공(resolve)또는 실패(rejected)되지 않은 상태이다.<ol start="2">
<li>이행(fulfilled): 서버가 정상적으로 데이터를 localhost한테 전달한 상태이다.</li>
<li>거부(rejected): 서버가 localhost에게 데이터를 전달하지 못한 경우.</li>
</ol>
</li>
</ol>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #22]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-22</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-22</guid>
            <pubDate>Mon, 06 Mar 2023 15:58:35 GMT</pubDate>
            <description><![CDATA[<h2 id="lexical-scoping-lexical-scope">Lexical Scoping (Lexical Scope)</h2>
<blockquote>
<ul>
<li>자바스크립트의 컴파일러는 토큰화(Tokenizing)와 렉싱(Lexing)을 처음에 하는데 이는 코드를 토큰 단위로 분리하여 의미를 매핑시키는 단계이다.</li>
</ul>
</blockquote>
<ul>
<li>Lex-time이란 토큰에 의미를 부여하는 렉싱 과정을 말하며, 이 때 자바스크립트의 스코핑 개념인 렉시컬 스코프가 형성된다.</li>
<li>함수를 선언할 때 정의되는 스코핑 형태</li>
<li>함수가 어디에 적혀있는가에 따라서 스코프가 구성되는 방식<ul>
<li>Lexical Scope는 함수를 어디서 선언하였는지에 따라 상위 스코프를 결정 (함수가 호출이 아님)</li>
</ul>
</li>
</ul>
<h2 id="scope-chain-scopes">Scope Chain, [[Scopes]]</h2>
<blockquote>
<p>EC -&gt; Execution Context (실행 컨텍스트)</p>
</blockquote>
<ul>
<li>EC안에 스코프 체인을 참조하는 [[Scopes]]를 갖게 된다.</li>
<li>[[Scopes]]는 연결리스트 형식으로 현재 스코프부터 상위 스코프를 참조하게 되는데, 이는 변수식별(Identifier Resolution)을 할 때 사용한다.</li>
</ul>
<h2 id="closure">Closure</h2>
<blockquote>
<ul>
<li>내부 함수에서 외부 함수 범위에 대한 접근을 제공하는 것<ul>
<li>함수가 속한 렉시컬 스코프를 기억하여 함수가 렉시컬 스코프 밖에서 실행될 때에도 이 스코프에 접근할 수 있게 하는 기능</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li>생명 주기가 끝난 외부 함수의 변수를 참조하는 함수</li>
<li>함수와 함수가 선언된 어휘적 환경의 조합</li>
</ul>
<h2 id="react-hook">React Hook</h2>
<blockquote>
<ul>
<li>공식문서에 따르면, Hook을 통해 해결하려는 문제는 다음과 같다.<ul>
<li>컴포넌트간에 재사용이 어려운 stateful logic</li>
<li>이해하기 어렵게 복잡해지는 컴포넌트들</li>
<li>모두를 혼동시키는 클래스형 컴포넌트</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li>함수형 컴포넌트에서 React의 상태 및 라이프사이클 기능에 연결할 수 있는 함수</li>
<li>클래스형 컴포넌트에서 동작하지 않으며, 클래스 없이 React의 여러 기능을 사용할 수 있다.</li>
<li>Hook은 React 개념에 대한 지식을 대체하지 않는다.<ul>
<li>Hooks는 props, state, context, refs 및 lifecycle과 같이 이미 알고 있는 개념에 보다 직접적인 API를 제공한다.</li>
</ul>
</li>
<li>Hook을 사용하면 수명 주기 방법에 따라 분할을 강제하는 대신 관련된 부분에 따라 하나의 구성 요소를 더 작은 기능으로 나눌 수 있다. (ex. useEffect)</li>
<li>컴포넌트에서 상태가 있는 로직을 추출하여 독립적으로 테스트하고 재사용할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[WIL #4]]></title>
            <link>https://velog.io/@kimtaehoon_98/WIL-4</link>
            <guid>https://velog.io/@kimtaehoon_98/WIL-4</guid>
            <pubDate>Sun, 05 Mar 2023 12:08:51 GMT</pubDate>
            <description><![CDATA[<p>이미 TIL로 정리한 내용이지만 과제 제출용으로 한 번 더 정리하는 Virtual DOM, props, state이다.</p>
<h2 id="dom의-의미와-특징">DOM의 의미와 특징</h2>
<p>-DOM ( The Document Object Model, 문서 객체 모델)은 HTML, XML(Extensible Markup Language) 문서의 프로그래밍 interface이다.
-nodes와 objects로 문서를 표현한다.
-웹페이지의 객체 지향 표현이며, 웹페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다.
-DOM은 프로그래밍 언어는 아니지만 DOM이 없다면 자바스크립트 언어는 웹페이지 또는 XML 페이지 및 요소들과 관련된 모델이나
개념들에 대한 정보를 갖지 못하게 된다.
-DOM의 구현은 어떠한 언어에서도 가능하다.</p>
<h4 id="재조정">재조정:</h4>
<p>UI가 표현된 객체를 메모리에 저장하고, React DOM과 같은 라이브러리에 의해 &#39;실제&#39;DOM과 동기화 하는 과정</p>
<p>1) UI가 변경되면 전체 UI를 Virtual DOM으로 렌더링한다.
2) 현재 Virtual DOM과 이전 Virtual DOM을 비교해 차이를 계산한다.
3) 변경된 부분을 실제 DOM에 반영한다.</p>
<hr>
<h2 id="props의-개념">props의 개념</h2>
<p>-부모 컴포넌트가 자식 컴포넌트에게 물려준 데이터, 다시 말해 컴포넌트 간의 정보 교류 방법.
-props는 반드시 위에서 아래 방향으로 흐른다. 즉 [부모] -&gt; [자식] 방향으로만 흐른다.(단방향)
-props는 반드시 읽기 전용으로 취급하며, 변경하지 않는다.</p>
<h4 id="prop-drilling">prop drilling</h4>
<p>-데이터가 전달되는 과정이 반복되는 것이 prop drilling, props가 아래로 뚫고 내려간다.라고 한다. 유지/보수 측면에서 곤란하다.</p>
<p>state를 쓰는 목적 =&gt; UI를 바꾸기 위함 (렌더링을 다시)</p>
<p>React안에서 변경되는 값은 반드시 state로 선언</p>
<p>리액트는 화면을 렌더링할지를 state의 변화에 따라 결정한다. 단순 변수는 무시한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #21]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-21</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-21</guid>
            <pubDate>Sat, 04 Mar 2023 19:47:53 GMT</pubDate>
            <description><![CDATA[<h2 id="redux는-javascript-상태관리-라이브러리이며-그-본질은-nodejs-모듈이다">Redux는 JavaScript 상태관리 라이브러리이며, 그 본질은 Node.js 모듈이다.</h2>
<h3 id="세-가지-원칙">세 가지 원칙</h3>
<h4 id="1-single-source-of-truth">1. Single source of truth</h4>
<p>-동일한 데이터는 항상 같은 곳에서 가지고 온다.
-즉, 스토어라는 하나뿐인 데이터 공간이 있다는 의미이다.</p>
<h4 id="2-state-is-read-only">2. State is read-only</h4>
<p>-리액트에서는 setState 메서드를 활용해야만 상태 변경이 가능하다.
-리덕스에서도 액션이라는 객체를 통해서만 상태를 변경할 수 있다.</p>
<h4 id="3-changes-are-made-with-pure-functions">3. Changes are made with pure functions</h4>
<p>-변경은 순수함수로만 가능하다.
-리듀서와 연관되는 개념이다.
-Store(스토어) - Action(액션) - Reducer(리듀서)</p>
<p><img src="https://velog.velcdn.com/images/kimtaehoon_98/post/aa3584c7-5cc8-40e9-b71e-de2d1314f2fa/image.png" alt=""></p>
<blockquote>
<p>Store
-Store는 상태가 관리되는 오직 하나의 공간이다.
-컴포넌트와는 별개로 스토어라는 공간이 있어서 그 스토어 안에 앱에서 필요한 상태를 담는다.
-컴포넌트에서 상태 정보가 필요할 때 스토어에 접근한다.</p>
</blockquote>
<blockquote>
<p>Action
-Action은 앱에서 스토어에 운반할 데이터를 말한다.
-Action은 자바스크립트 객체 형식으로 되어있다.</p>
</blockquote>
<blockquote>
<p>Reducer
-Action을 Store에 바로 전달하는 것이 아니다.
-Action을 Reducer에 전달해야 한다.
-Reducer가 주문을 보고 Store의 상태를 업데이트하는 것이다.
-Action을 Reducer에 전달하기 위해서는 dispatch()메서드를 사용해야 한다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/kimtaehoon_98/post/cab6bf91-4bd1-40c1-829f-fa5c69a8c37f/image.png" alt=""></p>
<p>Redux에서 위 개념을 구현하기 위해서 mapStateToProps()와 Redux hooks(useSelector, useDispatch)를 이용할 수 있다.</p>
<blockquote>
<p>Redux의 장점
-상태를 예측 가능하게 만든다.
-유지보수
-디버깅
-테스트</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #20]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-20</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-20</guid>
            <pubDate>Fri, 03 Mar 2023 17:52:20 GMT</pubDate>
            <description><![CDATA[<p>오늘 공부한 부분 정리</p>
<h3 id="usestate">useState</h3>
<p>-일반적인 방법: 배치성으로 처리 (배치 업데이트 = React에서 렌더링을 위해 state를 파악)
-함수형 업데이트: 명령들을 모아서 순차적으로 한 번씩 시행</p>
<p>렌더링이 잦다 =&gt; 성능 이슈 =&gt; React에서는 명령들을 모아 한 번에 처리하는 &#39;배치 업데이트&#39;</p>
<h3 id="useeffect">useEffect</h3>
<p>-렌더링 될 때, 특정한 작업을 수행해야 할 때 설정하는 훅
-컴포넌트가 화면에서 보여졌을 / 사라졌을(return) 때</p>
<p>*의존성 배열: 이 배열에 값을 넣으면, 그 값이 바뀔 때만 useEffect를 실행한다.</p>
<h3 id="useref">useRef</h3>
<p>-DOM 요소에 접근할 수 있도록 하는 React Hook.</p>
<ol>
<li><p>저장공간
a. state와 비슷한 역할. state는 병화가 일어나면 다시 렌더링이 일어나고 내부 변수들이 초기화된다는 차이.
b. ref에 저장된 값은 렌더링을 일으키지 x. 즉, 내부 변수의 초기화 방지.
c. 컴포넌트가 여러 번 렌덜이 =&gt; ref 저장값은 유지
d. 정리하면 state는 리렌더링이 꼭 필요한 값을 다룰 때, ref는 리렌더링을 발생시키지 않는 값을 다룰 때 사용한다.</p>
</li>
<li><p>DOM</p>
</li>
</ol>
<p>-렌더링 되자마자 특정 input이 focusing되어야 한다면 useRef를 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL #19]]></title>
            <link>https://velog.io/@kimtaehoon_98/TIL-19</link>
            <guid>https://velog.io/@kimtaehoon_98/TIL-19</guid>
            <pubDate>Thu, 02 Mar 2023 13:28:24 GMT</pubDate>
            <description><![CDATA[<h2 id="시멘틱-태그-sementic-tag">시멘틱 태그 (sementic tag)</h2>
<p>시멘틱 태그는 div 태그의 기능과 마찬가지로 block element이면서 사이트의 구조(레이아웃)을 설계하기 위한 태그이다.
HTML의 구조를 설계하는 데 있어 태그에 의미를 부여함으로써 사이트의 구조를 파악하기 용이할 수 있도록 도와주기 위해 만들어졌다.</p>
<h3 id="장점">장점</h3>
<ol>
<li>SEO 최적화에 유리하다.</li>
</ol>
<ul>
<li>검색 엔진이 태그의 목적에 부합하게 설계되어 있는 구조의 사이트에서 더욱 빨리 효율적으로 정보를 파악할 수 있어 검색 결과의 노출에 유리하다.</li>
</ul>
<ol start="2">
<li>웹 접근성에 효율적이다.</li>
</ol>
<ul>
<li>일반적인 브라우저에서는 차이가 없지만 스크린리더(시작장애인을 위한 웹 서핑 프로그램)와 같은 환경에서는 웹 접근성과 사용성을 향상시켜준다.</li>
</ul>
<ol start="3">
<li>유지보수의 용이성.</li>
</ol>
<ul>
<li>많은 div사용으로 관리가 어려워지는 문제점에서 벗어나 태그의 이름만 보고도 어떤 영역인지 바로 확인이 가능하며 해당 태그 영역의 특성에 맞는 작업을 구분하여 진행하기에 용이하다.</li>
</ul>
<h3 id="종류">종류</h3>
<pre><code>&lt;header&gt; 머리글, 제목, 헤더

&lt;nav&gt; 네이게이션, 목차, 리스트 등 다른 페이지로의 이동을 위한 링크 공간을 위주로 표현

&lt;aside&gt; 좌측과 우측 사이드 위치의 공간을 의미하며, 본문 외에 부수적인 내용을 주로 표현하는 태그

&lt;section&gt; 말그데로 주제, 카테고리 별로 섹션을 구분하는 용도의 태그로 주로 사용. 같은 테마를 가진 여러개의 콘텐츠의 그룹화

&lt;article&gt; 기사, 블로그 등 텍스트 위주의 페이지를 구성할때 주로 사용. 

&lt;footer&gt; 바닥글, 문서 하단에 들어가는 정보 구분 공간을 표현하는 태그

&lt;address&gt; 콘텐츠 작성자나 사이트 소유자의 정보등을 부가적으로 담는 기능

&lt;hgroup&gt; 제목과 관련된 부제목을 묶는 태그

&lt;main&gt; 이름처럼 문서 &lt;body&gt;의 중심 주제, 주요 내용 또는 응용 프로그램의 중심 기능과 직접 관련되어나 확장되는 콘텐츠를 나타낸다.

&lt;details&gt; 주변 문맥에서 표시된 구절의 관련성 또는 중요성으로 인해 참조 또는 표기 목적으로 표시되거나 강조된 텍스트를 나타냅니다.

&lt;figure&gt; 이미지, 다이어그램, 사진 등 독립적인 컨튼츠 정의시 사용

&lt;figcaption&gt; &lt;figure&gt; 요소의 설명 캔션(caption) 정의

&lt;mark&gt; 현재 맥락에 관련이 깊거나 중요한 부분 강조

&lt;time&gt; 시간의 특정 지점 또는 구간, datetime과 같은 속성을 이용해 알림같은 기능 구현

&lt;summary&gt; details 요소에 대한 요약, 캡션 또는 범례를 지정합니다. summary 요소를 클릭하면 상위 details 요소의 상태가 열리고 닫힙니다.</code></pre><p>전 조원에게 HTML 문법을 구상하는 데 있어 어려움을 토로했더니 좋은 자료를 알려주어 정리하였다. 다음에 파일을 만들 때 의식적으로 여기 있는 태그들을 써봐야겠다.</p>
]]></description>
        </item>
    </channel>
</rss>