<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dev-tinkerbell.log</title>
        <link>https://velog.io/</link>
        <description>🧚‍♀️  사람의 시선을 잡는 프론트엔드계의 팅커벨 주니어 개발자</description>
        <lastBuildDate>Wed, 02 Jun 2021 11:25:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dev-tinkerbell.log</title>
            <url>https://images.velog.io/images/dev-tinkerbell/profile/543e4fea-1180-4aa0-930b-6936dffebdd0/IMG_4230.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dev-tinkerbell.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev-tinkerbell" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[카카오톡 오픈그래프 이미지 업데이트]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1-OG-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8</link>
            <guid>https://velog.io/@dev-tinkerbell/%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1-OG-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8</guid>
            <pubDate>Wed, 02 Jun 2021 11:25:46 GMT</pubDate>
            <description><![CDATA[<p>프로젝트 중 공유 이미지를 업데이트 하고 확인해 보았더니 <strong>카톡에서만</strong> 업데이트 전 이미지가 계속 남아있는 것을 확인하였다. 나만 업데이트 전 이미지가 보이는건가 싶어 지인들에게 부탁드렸더니 지인들 역시 업뎃 전 이미지가 보였다. 
<img src="https://images.velog.io/images/dev-tinkerbell/post/a4d28d17-ab77-439a-9404-acb86419eeed/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.13.24.png" alt="오픈그래프 업데이트 전 이미지"></p>
<p><em>이건 분명 카톡 캐시문제일 것이다</em> 라는 것을 염두했는데 왜냐하면 meta태그에 넣어둔 og img url을 주소창에 검색해 보았을 때 내가 업데이트 한 이미지가 나왔기 때문이다.</p>
<p>그래서 열심히 구글링 해보았을 때 <a href="https://developers.kakao.com/tool/clear/og">카카오톡 개발자 사이트</a>에서 초기화 하라는 것을 확인하였고 url 입력창에 초기화 할 url을 입력하고 실행 해보았다.</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/8c622fa1-32cf-45df-ba1b-bcaadc0de7fc/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.38.06.png" alt="오픈그래프 이미지 초기화"></p>
<p>결과는 스크랩 정보가 잘 삭제되었다는 문구가 떴음에도 불구하고 난 어째서인지 업데이트가 되지 않았다. 참고로 다른 블로그들을 대부분 이 단계에서 업데이트가 되었다고 한다.</p>
<p>그래서 또 구글링을 해보았다. 같은 현상으로 앓던 <a href="https://popcorn16.tistory.com/237">블로그</a>의 글을 보았고 이 글쓴이의 말처럼 모바일은 시간이 지나 업데이트가 되었지만 PC는 카톡 재설치를 해보아도 업데이트가 되지 않았다. 더군다나 나는 지인들에게 확인해보았을 때 모바일 적용도 랜덤으로 업데이트가 되었다.</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/a58ce894-7455-4995-b096-c32f7572fa33/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.15.05.png" alt="오픈그래프 업데이트 전 이미지"></p>
<p>(업데이트 된 이미지는 블랙 배경에 흰 로고인데 지인이 보고 있는 공유이미지는 블랙배경으로 보이고 있었다고 했다.. 난 여전히 흰 배경인데......)</p>
<p><img src="https://www.kukgangmo.com/wysiwyg/PEG/se2_15508932946269.jpg" alt="깊은빡침"></p>
<p>캐시가 비워지고 업데이트 되는 시간이 좀 걸리는것 같았는데 난 아무래도 실무에서 작업하다보니 기다릴 시간이 없었고 얼마나 기다려야 할지 모르는 상태에서 _랜덤으로 업데이트 될꺼에요~ 시간이 얼마나 걸리는진 모르겠어요~_라는 답을 드리는건 무책임 하다는 생각이 들었다. 그래서 난 좀 더 확실한 방법을 찾길 원했고 찾았다..!</p>
<p>캐시 상관없이 오픈그래프 이미지를 업데이트 할 수 있는 가장 확실한 방법. 바로바로.. ⭐️<strong>이미지 파일명 수정</strong>⭐️하기!!!</p>
<p>이미지 파일명을 수정하고 다시 서버에 배포했더니 카톡에서도 바로 업데이트 되는 것을 확인할 수 있었다. PC, 모바일 둘 다 업데이트 확인 완료!! 뿌듯-⭐️</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/d0434fae-f6db-4ae6-8947-ff83c3d92058/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.10.41.png" alt="업데이트 된 오픈그래프 이미지"></p>
<blockquote>
<p>🧚‍♀️
학원에서 배우지 않았던.. 알 수 없는 에러가 가끔 너무 당황스럽지만 이렇게 또 하나 얻어간다 :)</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://imweb.me/faq?mode=view&amp;category=29&amp;category2=47&amp;idx=70639">카카오톡 오픈그래프 캐시 삭제 방법 (이미지 스크랩)</a></li>
<li><a href="https://popcorn16.tistory.com/237">카카오톡 오픈그래프(og) 캐시 삭제 안됨 해결방법</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[나의 마크업은 다르다.]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EB%82%98%EC%9D%98-%EB%A7%88%ED%81%AC%EC%97%85%EC%9D%80-%EB%8B%A4%EB%A5%B4%EB%8B%A4</link>
            <guid>https://velog.io/@dev-tinkerbell/%EB%82%98%EC%9D%98-%EB%A7%88%ED%81%AC%EC%97%85%EC%9D%80-%EB%8B%A4%EB%A5%B4%EB%8B%A4</guid>
            <pubDate>Mon, 18 Jan 2021 13:56:09 GMT</pubDate>
            <description><![CDATA[<p>코로나로 여러 사람이 피해를 입었지만 그 중에서도 소외 계층이 더 피해를 입었다는 사실을 부정하긴 어려울 것이다. 특히나 대면으로 이루어질 많은 부분이 비대면으로 대체 되어 가면서 이로 인해 받은 피해가 생겼다. 그 중에서도 나는 웹에 대하여 초점을 두었고 웹으로 많은 것들이 이루어지는 시대에 웹은 모두에게 평등하고 공평 해야하지만 <em>정말 모두에게 공평하다고 말할 수 있을지</em> 의문이 들었다.</p>
<p>이러한 측면에서 웹에 대하여 생각해보게 되었고 과연 웹이 모두에게 공평한 콘텐츠를 제공하는지 접근성 관점에서 이야기 하려고 한다.</p>
<h1 id="웹의-문서-html">웹의 문서, HTML</h1>
<p>가장 쉬우면서도 지키기 어려운 것은 <strong>의미에 맞는</strong> HTML 작성이라고 생각한다. 정말 &quot;눈&quot;에 보이는 것만 집중 한다면 쉽게 놓칠 수 있는 부분이 많다. 마크업을 할 때 고려되어야 하는 사항은 매우 많은데 시각적인 부분에 초점을 맞추고 그것이 편하니 놓치게 된다. 
이러한 부분의 예제를 몇 가지 이야기 해보고 차별 없는 콘텐츠 제공을 위해 어떻게 해야하는지 알아보자.</p>
<h2 id="📍-케이스로-보는-마크업">📍 케이스로 보는 마크업</h2>
<h3 id="정말-div가-최선입니까-😈">정말 div가 최선입니까? 😈</h3>
<blockquote>
<p><code>&lt;div&gt;</code> 요소는 &quot;순수&quot; 컨테이너로서 아무것도 표현하지 않습니다. 대신 다른 요소 여럿을 묶어 class나 id 속성으로 꾸미기 쉽도록 돕거나, 문서의 특정 구역이 다른 언어임을 표시(lang 속성 사용)하는 등의 용도로 사용할 수 있습니다. <code>&lt;div&gt;</code> 요소는 의미를 가진 다른 요소(<code>&lt;article&gt;, &lt;nav&gt;</code> 등)가 적절하지 않을 때만 사용해야 합니다.
<a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element/div">&lt;div&gt; MDN</a></p>
</blockquote>
<p>MDN에 따르면 <code>div</code>는 요소 의미를 가진 요소가 적절하지 않을 때만 사용해야 한다. *<em>즉 콘텐츠를 구분 짓고 싶지만 적당한 의미가 없을 때 사용하는 요소이다. *</em>
만약 콘텐츠의 의미가 아래 중 해당된다면 <code>div</code>요소를 사용하지 않고 콘텐츠의 의미에 맞게 마크업이 가능하다.</p>
<h4 id="div를-사용하기-전-고려해야-할-콘텐츠의-의미">div를 사용하기 전 고려해야 할 콘텐츠의 의미</h4>
<table>
<thead>
<tr>
<th>의미</th>
<th>요소</th>
</tr>
</thead>
<tbody><tr>
<td>소개 및 탐색에 도움을 주는 콘텐츠</td>
<td><code>&lt;header&gt;</code></td>
</tr>
<tr>
<td>문서의 부분 중 현재 페이지 내, 또는 다른 페이지로의 링크를 보여주는 콘텐츠</td>
<td><code>&lt;nav&gt;</code></td>
</tr>
<tr>
<td>문서의 독립적인 구획을 나타내는 콘텐츠</td>
<td><code>&lt;section&gt;</code></td>
</tr>
<tr>
<td>문서, 페이지, 애플리케이션, 또는 사이트 안에서 독립적으로 구분해 배포하거나 재사용할 수 있는 콘텐츠</td>
<td><code>&lt;article&gt;</code></td>
</tr>
<tr>
<td>구획의 작성자, 저작권 정보, 관련 문서 등의 콘텐츠</td>
<td><code>&lt;footer&gt;</code></td>
</tr>
<tr>
<td>위 요소들을 사용 시, <code>heading</code> 요소를 첨부해야 해당 콘텐츠들의 의미를 더 정확하게 제공할 수 있다. <code>heading</code> 요소에 관련한 이야기는 다음 섹션에서 더 자세히 얘기해 보려고 한다.</td>
<td></td>
</tr>
</tbody></table>
<h3 id="이거-제목-맞아-🙀">이거 제목 맞아? 🙀</h3>
<p><code>heading</code> 요소라고 하면, <code>&lt;h1&gt;, &lt;h2&gt; ... &lt;h6&gt;</code> 라는 것을 알고 있을 것이다. 가끔 사이트들을 둘러보면 분명 <code>heading</code> 요소인데 <code>heading</code>으로 작성되어 있지 않거나 단지 폰트 사이즈의 차이때문에 <code>&lt;h1&gt;</code>에서 <code>&lt;h3&gt;</code>를 사용하거나 하는 잘못된 마크업을 보았다. 이렇게 될 경우 모두에게(컴퓨터 포함)  제대로 된 콘텐츠가 제공 되지 않는다.</p>
<p>이해를 돕기 위해 예시를 보면서 설명해보자면, (악감정 없습니다,, 요즘 취업을 위해 애용하고 있는 사이트일 뿐..😘 )</p>
<h4 id="예시-1">예시 1.</h4>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/85638dba-7128-42b8-ab24-6882eef1f70e/ex.png" alt="스타일링에 집중한 잘못된 heading 예시 1"></p>
<p>네비의 개발 영역부분의 제목이 스타일링을 고려하여 두 번째 개발영역 제목을 <code>&amp;nbsp;</code>로만 작성되었다. 정확한 제목 제공이 안되어 있어 해당 콘텐츠의 정확한 의미 전달이 아쉬웠다.
이럴 경우 텍스트를 제공하나 <a href="https://velog.io/@ursr0706/%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1%EC%9D%84-%EA%B3%A0%EB%A0%A4%ED%95%98%EC%97%AC-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%88%A8%EA%B8%B0%EA%B8%B0">뷰에서 숨김처리</a>(IR기법)를 하거나 다른 로직을 고려해야 한다.</p>
<h4 id="예시-2">예시 2.</h4>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/3a0f90f3-0c0d-4a11-bdc6-ccfeaf29096a/ex2.png" alt="스타일링에 집중한 잘못된 heading 예시 2"></p>
<p><code>h1</code>다음 <code>h2</code>가 생략되고 <code>h3</code>가 사용되었다. 이렇게 될 경우 단지 폰트 사이즈에만 초점을 맞추어 스타일링 되었다고 생각이 된다. 이 역시 시각적인 부분 뿐만 아니라 제대로 된 콘텐츠를 위해 <code>p</code> 요소를 사용하거나 <code>h2</code>를 사용하는 것이 적합하다고 생각한다.</p>
<p>이처럼 단지 제목을 시각적인 부분에만 초점을 맞추어 <code>heading</code> 요소가 생략되거나 의미가 맞지 않는 요소를 추가할 수 있다. 정확한 콘텐츠를 제공하기 위해 시각적 부분 뿐만아니라 콘텐츠의 의미에 대하여 고려하고  해당 <code>heading</code> 요소를 작성해야 한다.</p>
<h3 id="콘텐츠에-이해를-돕기-위해-제공되어야-하는-이미지인가-단지-꾸밈-요소인가-🙄">콘텐츠에 이해를 돕기 위해 제공되어야 하는 이미지인가 단지 꾸밈 요소인가? 🙄</h3>
<p>웹에 이미지를 넣기 위해 HTML <code>img</code>요소를 사용하거나 CSS <code>background-image</code>속성을 사용할 것이다. 웹에 이미지 넣는 기능은 같으나 언제 사용 할 것이라는 목적에 대한 것은 다르다. </p>
<p><code>img</code> - 콘텐츠를 설명하기 위해 필요한 이미지
<code>background-image</code> - 콘텐츠의 배경, 꾸밈요소를 위한 이미지</p>
<p>특히나 웹 접근성 차원에서 보면 <code>img</code>는 <strong><code>alt</code>를 사용하여 대체텍스트를 필수</strong>로 제공하게 되어 있다. 이는 스크린리더 사용자가 대체텍스트로서 이미지 콘텐츠를 제공 받는다는 것을 뜻한다. 반면 <code>background-image</code>는 접근성 보조 기술이 제공 되지 않는다.</p>
<p>예시를 들어보면,
<img src="https://images.velog.io/images/dev-tinkerbell/post/a9dea1e6-fccd-47b7-aa7e-c2e6d65583fd/ex3.png" alt="img요소의 잘못된 사용 예시">
다음 섹션과의 연결 사이에 꾸밈요소로 존재하지만 <code>img</code> 요소를 사용하였고 꾸밈 요소이다 보니 대체 텍스트 또한 작성되지 않았다. 위 예제는 꾸밈요소로 존재하는 이미지임으로 <code>background-image</code> 속성을 사용해야 하는 좋은 예이다.</p>
<p>즉, 웹 페이지 내에서 목적과 설명이 필요한 이미지는 <code>img</code> 요소를 사용하며 단지 꾸밈을 위한 이미지일땐 <code>background-image</code> 속성을 사용한다. </p>
<h3 id="자자-이것은-링크입니다-무슨-링크냐구요-글쎄요-🤔">자자, 이것은 링크입니다. 무슨 링크냐구요? 글쎄요 🤔</h3>
<p><code>a</code>요소를 사용시, 텍스트가 아닌 이미지를 대신 넣거나 아이콘으로 대신할 때가 있다. 일반 사용자에겐 큰 무리 없이 콘텐츠의 정보 제공이 되지만 스크린리더 사용자가 보조기기장치를 이용한다면 단지 <code>링크</code> 라는 설명만 나올 뿐 어떤 링크인지에 대하여 알 수 없다.</p>
<p>이번에도 예시를 들어보면,
<img src="https://images.velog.io/images/dev-tinkerbell/post/a9b068d6-5119-42f4-92e6-ef325d454f44/ex4.png" alt="a요소의 잘못된 사용 예시">
현재 <code>a</code> 요소 안에 <code>i</code>요소만 있을 뿐 텍스트로 설명할 수 있는 부분이 없다. 이 부분을 보이스오버를 사용해서 들어보았다.</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/cd16f3b6-88f3-48eb-be82-414b4c14b069/ex5.png" alt="보이스오버 사용시 a요소의 읽힘">
만약 눈을 감고 사용해본다면 이 톱니바퀴 이미지 링크가 어디로 연결해주는 링크인지에 대한 정보가 없어 정보 제공에 불편함이 있을 것이다. 위에서 언급했듯 자식요소를 사용하여 IR기법으로 텍스트를 숨긴다거나 <code>title</code>을 사용하여 링크에 대한 정보를 제공해야 한다.</p>
<p>버튼요소 역시 같은 문제를 가지고 있음으로 이미지를 사용한다면 IR기법을 사용하거나 명확한 텍스트를 제공해야한다.</p>
<h2 id="📍-스크린리더-사용자를-위한-보조기기장치-보이스오버">📍 스크린리더 사용자를 위한 보조기기장치 (보이스오버)</h2>
<p>스크린리더 사용자를 이해하려고 하면 직접 그 사용자의 환경이 되어 확인하는 것이 가장 좋은 방법이라고 생각한다. 보조기기장치는 다양하게 있지만 그 중 보이스오버 사용법을 공유하려고 한다.</p>
<p><strong>시스템 환경설정 &gt; 손쉬운 사용 &gt; VoiceOver 활성화 확인</strong>
<img src="https://images.velog.io/images/dev-tinkerbell/post/c8200127-ea0f-40f5-93db-cb9cd564676d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-01-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.15.28.png" alt="VoiceOver 사용방법"></p>
<p>이 후 해당 웹 사이트를 들어가서 테스트해보면 된다.</p>
<h2 id="📍-추천-크롬-확장-프로그램">📍 추천 크롬 확장 프로그램</h2>
<p>웹사이트를 제작 중, 제작 완료 시 웹접근성을 높이기 위한 유용한 프로그램 몇 가지를 공유하려고 한다.</p>
<ol>
<li><a href="https://chrome.google.com/webstore/detail/web-developer/bfbameneiokkgbdmiekhjnmfkcnldhhm">Web Developer</a> - HTML, CSS 문법 체크
<img src="https://images.velog.io/images/dev-tinkerbell/post/ff130852-3e7f-424c-8c51-78823579b166/ex7.png" alt="Web Developer"></li>
<li><a href="https://chrome.google.com/webstore/detail/headingsmap/flbjommegcjonpdmenkdiocclhjacmbi">headingsmap</a> - heading 요소 확인
<img src="https://images.velog.io/images/dev-tinkerbell/post/ae41d1b4-da8c-47a4-8323-82d1ab1441df/ex8.png" alt="headingsmap"></li>
<li><a href="https://chrome.google.com/webstore/detail/openwax/bfahpbmaknaeohgdklfbobogpdngngoe">OpenWAX</a> - 웹접근성 확인
<img src="https://images.velog.io/images/dev-tinkerbell/post/1a3de341-d2ee-49e1-adf9-7e7b22b086a5/1.png" alt="OpenWAX"></li>
<li><a href="https://chrome.google.com/webstore/detail/tota11y-plugin-from-khan/oedofneiplgibimfkccchnimiadcmhpe">Tota11y Plugin, from Khan Academy</a> - 웹접근성 확인 (색상 대비 차이 확인 가능)
<img src="https://images.velog.io/images/dev-tinkerbell/post/f8ee9412-e3bb-498d-bcff-110df9c61d47/2.png" alt="Tota11y Plugin"></li>
</ol>
<blockquote>
<p>🧚‍♀️
아직 나도 접근성에 대해 고려해야 할 사항도 많고 부족한 부분도 많지만 작은 것부터 하나하나 신경쓰려고 노력하고 있다. 모두가 웹 제작시 웹 접근성에 대해 고려하고 누구나 공평한 웹 정보를 제공받았으면 좋겠다. 🙏</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://www.youtube.com/watch?v=e9bYgjAj2Gw">국내 웹사이트 정보 접근성 &#39;미흡&#39; 수준 / YTN 사이언스</a></li>
<li><a href="https://medium.com/@zac_heisey/7-alternatives-to-the-div-html-tag-7c888c7b5036">7 Alternatives to the &lt;div&gt; HTML Tag
</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element/header">header</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element/nav">nav</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element/section">section</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element/article">article</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/HTML/Element/footer">footer</a></li>
<li><a href="https://velog.io/@ursr0706/%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1%EC%9D%84-%EA%B3%A0%EB%A0%A4%ED%95%98%EC%97%AC-%ED%85%8D%EC%8A%A4%ED%8A%B8-%EC%88%A8%EA%B8%B0%EA%B8%B0">웹 접근성을 고려하여 텍스트 숨기기</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/background-image">background-image</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[바닐라 JS로 무한스크롤 구현을 위한 베이직 공부]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EB%AC%B4%ED%95%9C%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B5%AC%ED%98%84%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@dev-tinkerbell/%EB%AC%B4%ED%95%9C%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B5%AC%ED%98%84%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Fri, 01 Jan 2021 10:02:09 GMT</pubDate>
            <description><![CDATA[<h1 id="vanilla🍦js로-구현하기">Vanilla🍦JS로 구현하기</h1>
<p>페이징UI와 무한스크롤UI를 비교해보면 모바일 최적화로서 무한스크롤UI를 선호하는 추세이다. 스크롤 됨에 따라 비동기적으로 이미지나 콘텐츠를 가져오는데 일단, 서버통신을 하지 않고 무한스크롤이 어떻게 구현되는지 기본을 공부해보았다.</p>
<p>바닐라JS로 구현방법은 스크롤이벤트, 인터섹션 옵저버를 이용한 두가지 방법을 사용해 봤고 각각의 장단점과 인터섹션 옵저버에 관련하여 내용을 공유하려고 한다.</p>
<h2 id="계획">계획</h2>
<ol>
<li><code>li</code> 3개를 마련해둔다.</li>
<li>스크롤 할 때, 마지막 <code>li</code>가 보이면 <code>li</code>를 추가한다.</li>
</ol>
<p>매우 간단한 계획! 과연 계획대로 될 것인가,,?</p>
<h2 id="기본세팅">기본세팅</h2>
<p>[html]</p>
<pre><code class="language-html">&lt;body&gt;
  &lt;ul&gt;
    &lt;li&gt;1&lt;/li&gt;
    &lt;li&gt;2&lt;/li&gt;
    &lt;li&gt;3&lt;/li&gt;
  &lt;/ul&gt;
&lt;/body&gt;</code></pre>
<p>[css]</p>
<pre><code class="language-css">ul {
  padding-left: 0;
}

ul li {
  background-color: pink;
  margin-bottom: 20px;
  list-style: none;
  text-align: center;
  color: #fff;
  font-size: 100px;
  padding: 100px 0;
}

/* 짝수, 홀수 색상 구분하기 위해 */
li:nth-child(2n) {
  background-color: skyblue;
}</code></pre>
<h2 id="📍scroll-event">📍Scroll event</h2>
<p>첫 번째 방법은 스크롤 이벤트를 사용했다. 
스크롤이 마지막 <code>li</code>면 새로운 순번이 담긴 <code>li</code>를 추가하도록 하였다. 하지만 조건을 &#39;<strong>마지막 <code>li</code>면</strong>&#39;으로 하고 싶었는데 훨씬 까다로워지는 코드 덕에 다른 조건으로 구현했다. 바로 &#39;<strong>보이는 브라우저의 높이 + 윈도우의 스크롤 Y값이 해당 콘텐츠(<code>ul</code>)의 높이보다 같거나 크면</strong>&#39;이라는 조건으로 말이다...!</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/9d5e3def-4fc5-4208-9b36-39de7b3dcb0e/velog.png" alt="조건 그림"></p>
<p>[ js ]</p>
<pre><code class="language-js">(() =&gt; {
  const $ul = document.querySelector(&#39;ul&#39;);
  let $li;
  let count = $ul.children.length;

  document.addEventListener(&#39;scroll&#39;, () =&gt; {
    if ((window.innerHeight + window.scrollY) &gt;= document.body.offsetHeight) {
      $li = $ul.appendChild(document.createElement(&#39;li&#39;));
      $li.textContent = ++count;
    }
  })
})();</code></pre>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/69244cfc-edde-43d4-9125-41e6013581f4/scroll-event.gif" alt="스크롤 이벤트 결과">
결과적으로 구현은 잘되었다. 또한 코드들이 매우 직관적이다. 스크롤 이벤트 걸어서 원하는 동작을 시키면 되니까.. 하지만 스크롤 이벤트는 스크롤이 되는 순간 이벤트에 걸어두었던 모든 작업들이 실행된다. 요소 한두개이면 상관 없겠지만 백개, 천개를 생각하면 브라우저에 과부화가 걸릴 것이다.</p>
<p>그래서 추천하는 방법이 바로 인터섹션 옵저버이다!</p>
<h2 id="📍intersection-observer">📍intersection observer</h2>
<p>인터섹션 옵저버는 스크롤 되는 순간순간마다 이벤트를 확인하는 것이 아닌 내가 지켜보고자 하는 대상을 등록시켜 그 대상이 상위 요소 혹은 최상위 도큐먼트인 viewport와의 교차 영역에 대한 변화를 감지할 수 있도록 하는 방법이다.</p>
<p>간단하게 문법 설명을 해보자면,</p>
<ol>
<li><p>인터섹션 옵저버를 생성한다.
<code>const io = new IntersectionObserver(callback, options);</code></p>
</li>
<li><p>지켜볼 요소를 매개변수에 넣어 호출한다.
<code>io.observe(&#39;요소&#39;)</code></p>
</li>
<li><p>callback함수 내에서 주어진 매개변수로 하고자 하는 일을 구현한다. </p>
</li>
</ol>
<p>끝이다..!  
인터섹션 옵저버를 더 잘 사용하기 위해 세부기능을 소개하고자 한다.
하단 내용은 인터섹션 옵저버가 잘 정리되어 있는 <a href="https://heropy.blog/2019/10/27/intersection-observer/">HEROPY님의 블로그</a>를 참고했다.</p>
<h3 id="callback">callback</h3>
<p>관찰할 대상이 등록되거나 가시성에 변화가 생기면 관찰자는 콜백을 실행한다. 매개변수 <code>(entries, observer)</code>를 가진다.
<code>const io = new IntersectionObserver((entries, observer) =&gt; {}, options)</code></p>
<h4 id="entries">entries</h4>
<ul>
<li><code>boundingClientRect</code>: 관찰 대상의 사각형 정보(DOMRectReadOnly)</li>
<li><code>intersectionRect</code>: 관찰 대상의 교차한 영역 정보(DOMRectReadOnly)</li>
<li><code>intersectionRatio</code>: 관찰 대상의 교차한 영역 백분율(intersectionRect 영역에서 boundingClientRect 영역까지 비율, Number)</li>
<li><code>isIntersecting</code>: 관찰 대상의 교차 상태(Boolean)</li>
<li><code>rootBounds</code>: 지정한 루트 요소의 사각형 정보(DOMRectReadOnly)</li>
<li><code>target</code>: 관찰 대상 요소(Element)</li>
<li><code>time</code>: 변경이 발생한 시간 정보(DOMHighResTimeStamp)<h4 id="observer">observer</h4>
콜백이 실행되는 해당 인스턴스를 참조한다.</li>
</ul>
<h3 id="options">options</h3>
<ul>
<li>root
타겟의 가시성을 검사하기 위해 뷰포트 대신 사용할 요소객체를 지정
<code>{root: document.getElementById(&#39;my-viewport&#39;)}</code></li>
<li>rootmargin
<code>margin</code>을 이용해 root범위를 확장하거나 축소 가능
<code>{rootMargin: &#39;200px 0px&#39;}</code></li>
<li>threshold
옵저버가 실행되기 위해 타겟의 가시성이 얼마나 필요한지 백분율로 표시
<code>{threshold: 0}</code> viewport와 타켓이 교차하는 순간
<code>{threshold: 0.3}</code> viewport와 타켓이 30%일 교차했을 때
<code>{threshold: 1}</code> viewport에 타켓이 모두 교차했을 때</li>
</ul>
<h3 id="methods">methods</h3>
<ul>
<li><code>observe()</code>
대상 요소 관찰</li>
<li><code>unobserve()</code>
대상 요소 관찰 중지</li>
<li><code>disconnect()</code>
intersectionObserver 인스턴스가 관찰하는 모든 요소의 관찰을 중지</li>
</ul>
<p>그렇게 인터섹션 옵저버를 참고해서 구현해 본 무한스크롤!</p>
<p>[ js ]</p>
<pre><code class="language-js">(() =&gt; {
  const $ul = document.querySelector(&#39;ul&#39;);
  let $li = document.querySelector(&#39;li:last-child&#39;);
  let count = $ul.children.length;

  // 1. 인터섹션 옵저버 생성
  const io = new IntersectionObserver((entry, observer) =&gt; {
    // 3. 현재 보이는 target 출력
    const ioTarget = entry[0].target;

    // 4. viewport에 target이 보이면 하는 일
    if (entry[0].isIntersecting) {
      console.log(&#39;현재 보이는 타켓&#39;, ioTarget)
      // 5. 현재 보이는 target 감시 취소해줘
      io.unobserve($li);

      // 6. 새로운 li 추가해
      $li = $ul.appendChild(document.createElement(&#39;li&#39;));
      $li.textContent = ++count;
      // 7. 새로 추가된 li 감시해!
      io.observe($li);
    }
  }, {
    // 8. 타겟이 50% 이상 보이면 해줘!
    threshold: 0.5
  });

  // 2. li감시해!
  io.observe($li);

})();</code></pre>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/4bfeee38-8577-4031-a1d0-286dafbc6715/Intersection-%20observer.gif" alt="인터섹션 옵저버 결과"></p>
<p>이벤트 스크롤과 다른 점이라면 이벤트 스크롤은 페이지의 길이와 해당 요소의 길이를 비교했다면 인터섹션 옵저버는 추가되는 마지막 요소만을 감지하며 마지막 요소가 50% 교차하면 함수를 실행시켰다.(해당 이미지 스크롤을 잘보면 차이가 난다👀) 
스크롤에 따라 계속 실행되는 것이 아니다보니 브라우저 최적화에도 도움이 될 것이다. 다만, 인터넷 익스플로어에서 지원을 안한다.(폴리필을 이용하면 가능)</p>
<blockquote>
<p>🧚‍♀️
처음 접했을 때, 어떻게 접근 해야 하는지 잘 몰랐는데 하나하나 삽질?해보면서 하니 감이 훨씬 빠르게 익혔다. 처음에 리액트 된 무한 스크롤을 따라 해보려니 이리꼬이고 저리꼬였던 기억이 남는다.
오히려 바닐라로 처음부터 개념을 잡는 시간이라 더 좋았던거 같다. 다음번엔 더 활용해서 리액트에서 비동기 통신으로 무한스크롤 구현해봐야겠다.. 희희</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API">intersection-observer API MDN</a></li>
<li><a href="https://heropy.blog/2019/10/27/intersection-observer/">intersection-observer</a></li>
<li><a href="https://code-study.tistory.com/22">무한 스크롤</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[검색 엔진 최적화. SEO를 위한 방법]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EA%B2%80%EC%83%89-%EC%97%94%EC%A7%84-%EC%B5%9C%EC%A0%81%ED%99%94.-SEO%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@dev-tinkerbell/%EA%B2%80%EC%83%89-%EC%97%94%EC%A7%84-%EC%B5%9C%EC%A0%81%ED%99%94.-SEO%EB%A5%BC-%EC%9C%84%ED%95%9C-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sun, 27 Dec 2020 13:39:53 GMT</pubDate>
            <description><![CDATA[<p>웹사이트는 만들었다고 해서 끝이 아니다. 이쁜 내새끼 남들한테 보여주고 싶은 마음이 백퍼센트 일 것이다. 그렇다면 &quot;사람들이 내 사이트를 어떻게 하면 보게 만들 수 있을까?&quot;라는 고민을 하게 된다. 그 고민을 하려면 일단, 사람들이 어떻게 사이트를 찾는지부터 생각하면 된다. 사람들은 검색 사이트에서 자신이 찾고자 하는 단어 또는 문장을 검색하고 검색된 사이트들 중에 <strong>자신이 찾는 주제와 관련된 짧은 설명</strong>을 보고 들어온다. 
그렇다면 &quot;사람들이 검색했을 때 해당 주제와 맞게 나의 사이트와 해당 내용을 노출하려면 어떻게 해야할까?&quot;를 생각하게 된다. 이것이 검색 엔진 최적화에 대한 고민 일 것이다. 검색 엔진 제공하는 사이트로 대표적인 Google을 통해 알아보자. </p>
<h1 id="📍google-검색-작동-방식">📍Google 검색 작동 방식</h1>
<p>일단 Google이 어떻게 검색을 하고 작동하는지부터 알아보자.
Google에서는 세 가지 단계인 크롤링, 색인 생성, 게재를 통해 웹페이지를 소스로 결과를 생성한다.</p>
<h2 id="1️⃣-크롤링">1️⃣ 크롤링</h2>
<p>Google은 모든 것을 알 수 없기 때문에 끊임 없이 웹에 어떤 페이지가 존재하는지 검색하고 알려진 페이지 목록에 추가한다. <strong>새로운 페이지의 URL을 발견하여 내용을 확인하기 위해 페이지 방문을 하는데 이것을 크롤링이라고 한다.</strong> 이 과정에서 페이지를 렌더링하고 소스들을 모두 분석하여 <strong>검색결과의 어느 부분에 표시해야 할지 결정</strong>한다.
<img src="https://images.velog.io/images/dev-tinkerbell/post/65dc98d7-ab81-417a-a40f-608cc7a7a7fd/image.png" alt="지켜보는 짤">
Google이 직접 찾지 않고 먼저 알려주는 방법도 존재한다.</p>
<ul>
<li>웹 사이트 소유자가 Google에서 크롤링 할 수 있도록 페이지 목록(사이트맵)을 제출</li>
</ul>
<h3 id="사이트-크롤링-개선을-위한-방법">사이트 크롤링 개선을 위한 방법</h3>
<ul>
<li>사이트의 페이지에 엑세스 할 수 있고 페이지가 올바르게 표시되어 있는지 확인</li>
<li>단일 페이지를 만들거나 업데이트한 경우 Google에 개별 URL을 제출</li>
<li>Google에 하나의 페이지에 대한 크롤링을 요청하려면 링크 이동으로 모든 페이지에 도달할 수 있는 페이지를 홈페이지로 설정</li>
<li>Google이 이미 알고 있는 다른 페이지에서 내 페이지로 연결되게 한다. 그러나 광고 링크, 다른 사이트에서 구매한 링크, 댓글에 포함된 링크 등 Google 웹마스터 가이드라인을 위반한 링크는 Google에서 따라가지 않음</li>
</ul>
<h2 id="2️⃣-색인-생성">2️⃣ 색인 생성</h2>
<p>두 번째 단계인 색인 생성은 페이지가 발견되면 Google이 <strong>어떤 페이지인지 파악</strong>하려고 하는 것이다. 이 정보는 데이터베이스인 Google 색인에 저장된다.
<img src="https://images.velog.io/images/dev-tinkerbell/post/48064220-ac96-4fa8-8733-6de564d3319f/image.png" alt="저장 짤"></p>
<h3 id="색인-생성-개선을-위한-방법">색인 생성 개선을 위한 방법</h3>
<ul>
<li>페이지 제목은 짧고 의미있게 작성</li>
<li>페이지의 주제를 전달하는 페이지 제목을 사용</li>
<li>이미지보단 텍스트를 사용하여 콘텐츠 전달</li>
</ul>
<h2 id="3️⃣-게재및-순위-지정">3️⃣ 게재(및 순위 지정)</h2>
<p>세 번째 단계인 게재는 Google이 여러 요소를 바탕으로 색인에서 가장 관련된 답변을 찾아 상위에 노출 시키는 것이다. 
<img src="https://images.velog.io/images/dev-tinkerbell/post/2275253b-e9d4-4d42-9727-069a69e9638a/image.png" alt="선택 짤"></p>
<h3 id="게재및-순위-지정-개선을-위한-방법">게재(및 순위 지정) 개선을 위한 방법</h3>
<ul>
<li>빠르게 로드되는 모바일 친화적인 페이지를 만듦</li>
<li>페이지에 유용한 콘텐츠를 포함하고 최신 상태로 유지</li>
<li>양질의 사용자 환경을 보장하는 데 도움이 되는 <a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko">Google 웹마스터 가이드라인</a>을 따름</li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko">SEO 기본 가이드</a>의 도움말과 권장사항을 읽기</li>
<li><a href="https://static.googleusercontent.com/media/guidelines.raterhub.com/ko//searchqualityevaluatorguidelines.pdf">양질의 검색결과를 제공하기 위해 Google에서 품질 평가자에게 제공하는 가이드라인</a>을 비롯한 <a href="https://www.google.com/search/howsearchworks/?hl=ko">자세한 정보는 여기</a>에서 찾아본다.</li>
</ul>
<h1 id="📍seo-기본-가이드">📍SEO 기본 가이드</h1>
<p>웹사이트의 대상이 되는 사용자에 대한 경험을 바탕으로 웹사이트를 개발해야 하며, 모든 최적화는 사용자 환경을 개선하는 것을 목표로 해야 한다.</p>
<p>하기 내용은 <a href="(https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko)">Google SEO 기본 가이드</a>이며 자세한 내용은 해당 링크로 이동하여 확인 할 수 있다.</p>
<ul>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#google%EC%9D%B4-%EB%82%B4-%EC%BD%98%ED%85%90%EC%B8%A0%EB%A5%BC-%EC%B0%BE%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8F%84%EB%A1%9D-%EB%8F%95%EA%B8%B0">Google이 내 콘텐츠를 찾을 수 있도록 돕기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#google%EC%97%90-%ED%81%AC%EB%A1%A4%EB%A7%81%ED%95%98%EB%A9%B4-%EC%95%88-%EB%90%98%EB%8A%94-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%95%8C%EB%A6%AC%EA%B8%B0">Google에 크롤링하면 안 되는 페이지 알리기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#google-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EC%9E%90%EA%B0%80-%EB%82%B4-%EC%BD%98%ED%85%90%EC%B8%A0%EB%A5%BC-%EC%9D%B4%ED%95%B4%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8F%84%EB%A1%9D-%EB%8F%95%EA%B8%B0">Google 및 사용자가 내 콘텐츠를 이해할 수 있도록 돕기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#google-%EA%B2%80%EC%83%89%EA%B2%B0%EA%B3%BC%EC%97%90-%EC%82%AC%EC%9D%B4%ED%8A%B8%EA%B0%80-%ED%91%9C%EC%8B%9C%EB%90%98%EB%8A%94-%EB%B0%A9%EC%8B%9D-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0">Google 검색결과에 사이트가 표시되는 방식 관리하기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#%EC%82%AC%EC%9D%B4%ED%8A%B8-%EA%B3%84%EC%B8%B5%EA%B5%AC%EC%A1%B0-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0">사이트 계층구조 구성하기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#%EC%BD%98%ED%85%90%EC%B8%A0-%EC%B5%9C%EC%A0%81%ED%99%94%ED%95%98%EA%B8%B0">콘텐츠 최적화하기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94%ED%95%98%EA%B8%B0">이미지 최적화하기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#%EC%82%AC%EC%9D%B4%ED%8A%B8%EB%A5%BC-%EB%AA%A8%EB%B0%94%EC%9D%BC-%EC%B9%9C%ED%99%94%EC%A0%81%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0">사이트를 모바일 친화적으로 만들기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%ED%99%8D%EB%B3%B4%ED%95%98%EA%B8%B0">웹사이트 홍보하기</a></li>
<li><a href="https://developers.google.com/search/docs/beginner/seo-starter-guide?hl=ko#%EA%B2%80%EC%83%89-%EC%8B%A4%EC%A0%81-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EC%9E%90-%ED%96%89%EB%8F%99-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0">검색 실적 및 사용자 행동 분석하기</a></li>
</ul>
<p>결론적으로 웹사이트는 사용자에게 최적의 경험을 할 수 있도록 시맨틱 태그와 웹사이트에 대한 정보를 제공하여 콘텐츠를 구현하는 것을 목표로 삼으면 검색 엔진 최적화가 될 것이다.</p>
<h1 id="📍프로젝트에서-seo-점수-확인-및-높이기">📍프로젝트에서 SEO 점수 확인 및 높이기</h1>
<p>이번 매우 간단한 사이드 프로젝트를 사용하면서 SEO를 했다고 생각했지만 부족한 부분이 있었다. </p>
<h2 id="seo를-위한-나의-노력">SEO를 위한 나의 노력</h2>
<ol>
<li>적절한 타이틀 선정
<img src="https://images.velog.io/images/dev-tinkerbell/post/66c8a660-2a9c-49ad-80d1-d29c8e18f5a9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.57.42.png" alt="적절한 타이틀 선정"></li>
<li>사이트 정보 요약
<img src="https://images.velog.io/images/dev-tinkerbell/post/077ab79e-05be-4977-8e89-3207b1c01c79/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.01.40.png" alt="사이트 정보 요약"></li>
<li>시맨틱 태그 사용
<img src="https://images.velog.io/images/dev-tinkerbell/post/9ce56bb3-ff57-4c94-a50d-fdb5018e90e1/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.57.31.png" alt="시맨틱 태그 사용">
<img src="https://images.velog.io/images/dev-tinkerbell/post/ceaae402-7baf-496e-91be-9b25b9c2b086/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.00.36.png" alt="시맨틱 태그 사용"></li>
</ol>
<h2 id="크롬에서-seo-점수-확인">크롬에서 SEO 점수 확인</h2>
<h3 id="seo-점수-확인하는-방법">SEO 점수 확인하는 방법</h3>
<p>크롬 개발자 =&gt; Lighthouse =&gt; Categories에서 SEO 선택 =&gt; Generate report 
<img src="https://images.velog.io/images/dev-tinkerbell/post/b3e3d9af-823c-40b5-85eb-7b6fd7ff804f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.06.48.png" alt=""></p>
<p>하지만 크롬 개발자 도구를 통해 알아본 결과 나의 SEO점수는 90점이었고 <code>description</code> 메타태그가 없다고 경고가 나왔다.
<img src="https://images.velog.io/images/dev-tinkerbell/post/66d7b090-3c6e-4839-b788-0b1b58858611/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.09.46.png" alt="SEO 확인"></p>
<h2 id="seo-100점을-위햇">SEO 100점을 위햇..!!</h2>
<p>나는 공유하면 보이는 og태그들을 SEO라고 오해하고 있었다. 
그래서 웹사이트의 정보를 설명하는 <code>description</code> 태그부터 작성자 정보와 키워드 태그를 추가하였다.
<img src="https://images.velog.io/images/dev-tinkerbell/post/8a53bdb5-e6df-4dca-a031-07ebb3bdf9f7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.22.21.png" alt="추가한 meta태그"></p>
<p>그랬더니...!!
<img src="https://images.velog.io/images/dev-tinkerbell/post/f15065e4-cf3b-4d3d-8ab1-afa54558ff8b/image.png" alt="두근두근 짤"></p>
<p>당당하게 100점을 받았다! :)
<img src="https://images.velog.io/images/dev-tinkerbell/post/e146e117-2e91-46b6-a126-b84874653421/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202020-12-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.26.50.png" alt="SEO 결과">
물론 100점이 나왔다고 해서 무조건 검색엔진 상위 노출된다 라는 보장은 없지만 크롬 개발자를 통해 웹사이트 완성 후에 SEO를 확인 해보면 좋을 것 같다.</p>
<blockquote>
<p>🧚‍♀️
내 새끼 자랑하고 싶으면 사전 작업이 매우 필요하다는 것을 느꼈다. 
꼼꼼한 타켓 분석부터 그 타켓의 경험을 토대로 단단한 사이트 빌딩까지.. 
유명한 것은 이유가 있는 법..</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://developers.google.com/search/docs/beginner/how-search-works?hl=ko">Google 검색 작동 방식</a></li>
<li><a href="https://www.google.com/search/howsearchworks/crawling-indexing/">crawling-indexing/</a></li>
<li><a href="https://myseolabo.com/seo/meta-tag/">검색엔진 최적화 메타 태그! 2019년 업데이트</a></li>
<li><a href="https://hunit.tistory.com/312">검색로봇이 좋아하는 메타(Meta) 태그</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[*주니어* 프론트엔드 개발자가 정리한 REST API]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EC%A3%BC%EB%8B%88%EC%96%B4-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94-REST-API</link>
            <guid>https://velog.io/@dev-tinkerbell/%EC%A3%BC%EB%8B%88%EC%96%B4-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EC%83%9D%EA%B0%81%ED%95%98%EB%8A%94-REST-API</guid>
            <pubDate>Tue, 15 Dec 2020 14:32:00 GMT</pubDate>
            <description><![CDATA[<p>정적 웹사이트만 만들다가 API라는 개념을 접하면서 REST API의 개념도 같이 접했다. 그때 당시 정확한 개념보단 &quot;서버와 클라이언트에서 리소스를 요청하고 얻는다&quot; 정도로의 개념으로만 알고 사용했고 프로젝트를 진행했었다. 그러던중 강사님께서 <a href="https://youtu.be/RP_f5dMoHFc">그런 REST API로 괜찮은가</a>라는 영상을 추천해주셨고 REST API에 대해 다시 한번 생각해보게 되었다. </p>
<p>패스트캠퍼스 프론트엔드 스쿨 마지막 프로젝트를 끝낸 시점에서 제일 기억에 남았던 부분 중 하나가 API를 설계하고 수정했던 것인데 그 전까진 서버개발자들의 담당이라고만 생각했던 부분이 직접 만들고 난 후에 나는 아직도 이 개념에 대해 잘 모르고 있다는 생각이 들었고 그와 동시에 API와 REST API가 무엇인지 정확히 설명할 수 없는 나와 같은(?) 개발자가 많다고 생각했다. </p>
<p>이 기회를 통해 공부하면서 정리하려고 한다.</p>
<h1 id="📍어이어이-rest-api라고-들어봤나">📍어이어이 REST API라고 들어봤나?</h1>
<p>개발자인데 REST API에 대해 정확한 개념으로 설명할 수 없다고 하지만 들어보지 못했다는 개발자는 없을 것이다. 그만큼 개발자에게 중요하다고 생각하는 개념이고 주니어 프론트엔드 개발자라면 면접 질문 중 한번쯤 들어봤을 필수 질문 중 하나이다. </p>
<p><strong>&quot;REST API&quot;에 대해 설명해주세요.</strong></p>
<p>만약 이 개념에 대해 정확히 모르고 있다면..?
<img src="https://images.velog.io/images/dev-tinkerbell/post/eebe0dbe-eb80-4143-9628-3b62401e759f/image.png" alt="말문막힘 짤">
당연히 어버버버버 하고 나오겠지.. 생각만해도 끔찍하다. 개념을 정확히 다 알아야 한다고 생각하진 않지만 적어도 내가 어떤걸 사용하고 왜 사용하고 있는지는 알아야 하지 않을까? 하나하나 천천히 생각해보자. 매우 어렵지만은 않을 것이다. 다 사람이 생각했는걸~
<img src="https://images.velog.io/images/dev-tinkerbell/post/fc42f721-15fe-40ee-ba47-4b625311861e/image.png" alt="씨익 짤"></p>
<h2 id="그럼-api는-설명해줄-수-있어요-🧐">그럼 API는 설명해줄 수 있어요..? 🧐</h2>
<p>스스로 생각하고 답했을때 매끄럽게 설명할 수 있는 주니어 개발자는 몇 없을 것 같다. 
나는 API를 매 프로젝트에서 아이디어 회의를 할때 언급되었다. 음악 어플이나 날씨 어플 등을 만들고자 할때 그에 관한 데이터 또는 기능이 필요로 했고 그것을 두고 &quot;음악 관련 API가 필요하다&quot; 또는 &quot;날씨 관련 API가 필요하다&quot;라고 얘기했다. 하지만 정확히 API가 무엇인지 물었을때 나는 확답을 하지 못했다. 그러므로 다시 하나씩 찾아보자. 위키백과에서의 API는 뭐라고 설명할까?</p>
<blockquote>
<p>API(Application Programming Interface, 응용 프로그램 프로그래밍 인터페이스)는 응용 프로그램에서 사용할 수 있도록, 운영 체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 뜻한다. 주로 파일 제어, 창 제어, 화상 처리, 문자 제어 등을 위한 인터페이스를 제공한다.
<a href="https://ko.wikipedia.org/wiki/API">API 위키백과</a></p>
</blockquote>
<p>이해가 가는가?? 나는 솔직히 읽고 이해가 가지 않았다. 응용 프로그램 프로그래밍 인터페이스. 일단 인터페이스의 개념이 정확히 와닿지 않았다. 그래서 또 찾아보았다.</p>
<blockquote>
<p>인터페이스(interface)는 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면이다. 즉, 사용자가 기기를 쉽게 동작시키는데 도움을 주는 시스템을 의미한다. 컴퓨팅에서 컴퓨터 시스템끼리 정보를 교환하는 공유 경계이다. 이러한 교환은 소프트웨어, 컴퓨터 하드웨어, 주변기기, 사람 간에 이루어질 수 있으며, 서로 복합적으로 이루어질 수도 있다. 터치스크린과 같은 일부 컴퓨터 하드웨어 장치들은 인터페이스를 통해 데이터를 송수신할 수 있으며 마우스나 마이크로폰과 같은 장치들은 오직 시스템에 데이터를 전송만 하는 인터페이스를 제공한다.
<a href="https://ko.wikipedia.org/wiki/%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4_(%EC%BB%B4%ED%93%A8%ED%8C%85)">인터페이스 위키백과</a></p>
</blockquote>
<p>조금 더 풀어서 생각해보자면 인터페이스는 어떠한 두가지의 관계에서 상호간 소통할때의 매개체라고 이해했다. 다양한 관계가 있겠지만 마우스 예를 들어보면 사용자가 인터넷 아이콘을 클릭하고 싶을때 마우스를 이용하여 클릭을 하게 된다. 이때, 마우스는 사용자와 인터넷 사이에서의 신호를 주고 받을 수 있게 하는 매개체이다. 즉 이 관계에서 마우스는 인터페이스이다. </p>
<p>이러한 개념으로 생각해보았을 때 다시 위키백과에서 설명한 것을 참조해보자면, &quot;응용 프로그램에서 사용할 수 있도록 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 뜻한다.&quot; 라고 했다. 
<strong>즉, 내가 만드는 프로그램(응용 프로그램)에서 누군가가 만든 기능(운영체제나 프로그래밍 언어가 제공하는 기능)을 제어할 수 있게 하는 매개체가 API라고 설명할 수 있다.</strong></p>
<h2 id="rest-api를-설명해보자-😤">REST API를 설명해보자 😤</h2>
<p>와.. REST API를 위해 먼 길을 돌아왔다. 그래도 API의 개념을 알았으니 됐다. 그럼 REST가 무엇인지 알아볼까? </p>
<blockquote>
<p>REST(Representational State Transfer)는 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식이다. 이 용어는 로이 필딩(Roy Fielding)의 2000년 박사학위 논문에서 소개되었다. 
<a href="https://ko.wikipedia.org/wiki/REST">REST 위키백과</a></p>
</blockquote>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/696a50ac-d426-4baa-bba5-8e0ddb8735df/image.png" alt="동공지진 짤"></p>
<p>위키백과의 설명을 보고도 잘 이해가 가지 않아 REST를 설명한 사이트들을 참조했다. 참조한 내용을 바탕으로 풀어보자면 <strong>REST는 HTTP기반으로 필요한 자원에 접근하는 방식을 정해놓은 아키텍쳐</strong>라고 한다. </p>
<p>결국 W3상에서 정보를 주고받을 수 있는 프로토콜을 잘 활용하지 못하는 개발자들을 안타까워하며 로이 필딩이 직접 나서서 REST를 발표한 것이다. 그럼 REST를 사용하면서 어떠한 장점과 속성이 있고 구성요소가 어떻게 구성 되어 있는지 알아보자.</p>
<h3 id="rest의-장점">REST의 장점</h3>
<p>특정 요구 사항이 있는 SOAP(Simple Object Access Protocol)등의 규정된 프로토콜보다 사용하기 쉽고 속도가 빠르다.</p>
<h3 id="rest의-속성">REST의 속성</h3>
<ul>
<li>서버에 있는 모든 resource는 각 resource 당 클라이언트가 바로 접근 할 수있는 고유 URI가 존재한다.</li>
<li>모든 요청은 클라이언트가 요청할 때마다 필요한 정보를 주기 때문에 서버에서는 세션 정보를 보관할 필요가 없다. 즉, 서비스에 자유도가 높아지고 유연한 아키텍쳐 적응이 가능하다.</li>
<li>HTTP 메소드를 사용한다. 모든 resource는 일반적으로 HTTP 인터페이스인 GET,POST,PUT,DELETE 4개의 메소드로 접근 되어야 한다.</li>
<li>서비스 내에 하나의 resource가 주변에 연관 된 리소스들과 연결되어 표현이 되어야 한다.</li>
</ul>
<h3 id="rest의-구성-요소">REST의 구성 요소</h3>
<p>REST는 자원(Resource), 메소드(Method), 메세지(Message) 세 가지로 구성되어 있다.</p>
<h4 id="자원resource">자원(Resource)</h4>
<p>REST는 자원에 접근하는 방식을 정해놓은 아키텍쳐라고 했다. 그럼 자원에 어떻게 접근해야할까?
REST에서는 자원의 위치를 나타내는 URI(Uniform Resource Identifier)로 접근한다. 또한 URI를 설계시 지켜야하는 규칙이 있다.</p>
<ul>
<li><p><strong><code>/</code>의 쓰임새</strong>
<code>/</code>는 계층 관계를 나타내는데 사용함으로 URI 마지막 문자로 <code>/</code>를 포함하지 않는다.</p>
</li>
<li><p><strong>URI를 이루는 resource들은 동사보단 명사로 이루어져 있어야 한다.</strong>
자원의 정보를 표현해야 하는 URI는 PUT, POST 등 행위보다 자원의 표현으로 구성되어야 한다.</p>
</li>
<li><p><strong>URI에서는 <code>_</code>보다 <code>-</code>을 권장한다.</strong>
URI를 쉽게 읽고 해석하기 위해 밑줄 때문에 문자가 가려지기도 하는 문제점을 해소한다.</p>
</li>
<li><p><strong>URI 경로에는 소문자가 적합하다.</strong>
URI 문법 형식은 URI 스키마와 호스트를 제외하고 대소문자에 따라 다른 리소스로 인식한다.</p>
</li>
<li><p><strong>파일 확장자는 URI에 포함시키지 않는다.</strong>
Accept header를 사용한다.</p>
</li>
</ul>
<h4 id="메소드method">메소드(Method)</h4>
<p>자원에 접근할 때 어떤 행위로 요청인지 HTTP 메소드가 알려준다. GET, PUT, POST, DELETE를 사용하며 이것으로 CRUD를 구현한다.</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>역할</th>
</tr>
</thead>
<tbody><tr>
<td>GET</td>
<td>해당 리소스를 조회한다. 리소스를 조회하고 해당 도큐먼트에 대한 자세한 정보를 가져온다.</td>
</tr>
<tr>
<td>PUT</td>
<td>해당 리소스를 수정한다.</td>
</tr>
<tr>
<td>POST</td>
<td>해당 URI를 요청하면 리소스를 생성한다.</td>
</tr>
<tr>
<td>DELETE</td>
<td>해당 리소스를 삭제한다.</td>
</tr>
</tbody></table>
<ul>
<li>Endpoint
메소드는 같은 URI들에서도 다른 요청을 하게끔 구별해주는 항목이 있다. 예를 들면
<code>GET /user/books/1</code>
<code>POST /user/books/1</code>
<code>DELETE /user/books/1</code>
세 가지의 URI가 같더라도 메소드에 따라 다른 요청을 할 수 있으며 이것을 Endpoint라고 한다.</li>
</ul>
<h3 id="결론">결론</h3>
<p>REST API는 HTTP기반으로 필요한 리소스를 요청하는 아키텍처로 설계된 어플리케이션 프로그래밍 인터페이스이다.</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/3c35d42c-4498-4cdf-8357-669a76b38dd7/restful.jpg" alt="RESTful API"></p>
<h2 id="아니-잠깐만-graphql도-묶어서-많이-보이던데-🤪">아니 잠깐만 GraphQL도 묶어서 많이 보이던데? 🤪</h2>
<p>GraphQL은 Graph Query Language의 약어로서 REST API의 단점을 보안하고자 나왔다.</p>
<h3 id="rest-api-단점">REST API 단점</h3>
<p>REST API로는 다양한 기종에서 필요한 정보들을 일일히 구현하는 것이 힘들었다.</p>
<h3 id="graphql과-restful의-차이점">GraphQL과 RESTful의 차이점</h3>
<ul>
<li>HTTP 요청 회수를 줄일 수 있다.
GraphQL은 원하는 정보를 하나의 Query에 담아 요청하는 것이 가능하기 때문에 리소스 종류 별로 요청하는 REST보다 HTTP 요청 회수를 줄일 수 있다.</li>
<li>HTTP응답의 사이즈를 줄일 수 있다.
GraphQL은 원하는 대로 정보를 요청하는 것이 가능한 반면 REST는 응답의 형태가 정해져 있고 필요한 정보만 부분적으로 요청하는 것이 힘들다.</li>
</ul>
<h3 id="그래서-graphql만-사용해야-하는가">그래서 GraphQL만 사용해야 하는가?</h3>
<p>GraphQL은 REST의 단점을 보안하지만 GraphQL 또한 단점이 있다. </p>
<ul>
<li>file 전송 등 text만으로 하기 힘든 내용은 처리하기 복잡하다.</li>
<li>고정된 요청과 응답만 필요할 경우 REST보다 요청의 크기가 더 커진다.</li>
<li>재귀적인 Query가 불가능하다.</li>
</ul>
<p>무조건 적으로 사용한는 것보단 GraphQL과 RESTful의 장단점을 비교하여 내가 지금 어느 것이 더 필요한지 판단하여 사용하는 것이 맞다.</p>
<blockquote>
<p>🧚‍♀️
정리하면서 생각보다 더 어렵고 방대했다. 전체적으로 용어가 어려우니 이해하는데 시간이 걸렸다. 그래도 개발자라면 꼭 알아야할 개념 중 하나라고 생각하는데 이해하고 정리해서 좋다. 완벽하지 않아도 지속적으로 공부하고 보면서 틀린 부분이 있으면 수정할 계획이다.</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://dydrlaks.medium.com/api-%EB%9E%80-c0fd6222d34c">API란?</a></li>
<li><a href="http://blog.wishket.com/api%EB%9E%80-%EC%89%BD%EA%B2%8C-%EC%84%A4%EB%AA%85-%EA%B7%B8%EB%A6%B0%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8/">API란? 비개발자가 알기 쉽게 설명해드립니다!</a></li>
<li><a href="https://www.redhat.com/ko/topics/api/what-are-application-programming-interfaces">API(애플리케이션 프로그래밍 인터페이스)란 - 개념, 기능, 장점</a></li>
<li><a href="https://meetup.toast.com/posts/92">REST API 제대로 알고 사용하기</a></li>
<li><a href="https://www.redhat.com/ko/topics/api/what-is-a-rest-api">REST API(RESTful API, 레스트풀 API)란? 구현 및 사용법</a></li>
<li><a href="https://dydrlaks.medium.com/rest-api-3e424716bab">REST API ?</a></li>
<li><a href="https://velog.io/@stampid/REST-API%EC%99%80-RESTful-API">REST API와 RESTful API</a></li>
<li><a href="https://www.holaxprogramming.com/2018/01/20/graphql-vs-restful-api/">GraphQL과 RESTful API</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[내가 이해 하려고 정리한 리액트 리덕스]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EB%A6%AC%EB%8D%95%EC%8A%A4%EC%9D%98-%ED%9D%90%EB%A6%84</link>
            <guid>https://velog.io/@dev-tinkerbell/%EB%A6%AC%EB%8D%95%EC%8A%A4%EC%9D%98-%ED%9D%90%EB%A6%84</guid>
            <pubDate>Fri, 13 Nov 2020 10:34:53 GMT</pubDate>
            <description><![CDATA[<p>리액트를 한달만에 배우고 복습겸 <a href="https://github.com/tinkerbell93/React-Hackathon">하루 해커톤</a>을 진행했다. 사실 한달이라는 건 누구에게나 다르지만 나에게는 매우 짧은 시간임으로 전체를 이해하고 사용한다는 것보단 외워서 사용한 기술들이 더 많았다. </p>
<p>예를 들면 데이터를 비동기로 다루는 미들웨어 중에 redux-thunk, redux-saga를 사용할 수 있는데 saga가 내 나름 더 좋아보여?서 saga를 외워 프로젝트에 진행하였다. <del>이유없는 이유..</del></p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/8dcb4292-22d9-4fb5-889e-a6f396d1dfcf/image.png" alt="에? 짤"></p>
<p>개발자가 &quot;그런 이유에서 선택을 하다니..?&quot;라고 생각할 수도 있다. 하지만 나도 이런 비효율적인 프로그래밍을 하는것에 대해 말이 안되는거 알고 다음의 더 나은 프로젝트를 위해 정확이 이 기술을 왜 사용했고 어떤 장점이 있는지 확실하게 정리해야겠다는 생각이 들었다.</p>
<p>이번에도 역시 리덕스를 사용할때 전반적인 이해를 가지고 사용했다긴 보단 전역에서 데이터를 관리할 수 있다는 장점이 있다는 사실 하나만으로 <strong>외워서</strong> 사용했던 것 같다. 그래서 리덕스에 관련된 이해를 돕고 실수를 반복하지 않기 위해 리덕스를 제대로 알아보고 다음 활용시에 더 확장해서 사용할 수 있도록 리덕스에 대해 정리해보려고 한다. </p>
<h1 id="리덕스요">리덕스..요?</h1>
<p>리덕스... 리...덕.. 네..? 덕스는 아는데.. 꽥꽥 🦆🦆🦆🦆
<img src="https://images.velog.io/images/dev-tinkerbell/post/cd859ed0-8949-4074-ab09-5e4174612765/image.png" alt="윙크 짤">
리덕스가 뭘까? 리덕스의 개념부터 정리해보자면..</p>
<blockquote>
<p>Redux는 애플리케이션 상태를 관리 하기 위한 오픈 소스 JavaScript 라이브러리이다. 사용자 인터페이스 구축을 위해 React 또는 Angular 와 같은 라이브러리에서 가장 일반적으로 사용된다. Facebook의 Flux 아키텍처 와 유사하고 영감을 받아 Dan Abramov와 Andrew Clark이 만들었다. 
<a href="https://en.wikipedia.org/wiki/Redux_(JavaScript_library)">리덕스 위키백과</a></p>
</blockquote>
<p>그렇다. 단 한줄로 정리하면 <strong>어플리케이션의 상태를 관리하기 위한 라이브러리</strong>이다. 
그러면 왜 사용해야 하고 언제 사용해야 할까? </p>
<h2 id="왜-사용할까">왜 사용할까?</h2>
<p>나는야 아직 숲을 보지 못한 주니어 개발자.. 아직 큰 프로젝트에 대한 경험이 없어서 그런지 리덕스를 왜 사용하는지 이해를 못했다. 리덕스는 상태를 관리하기 위함인데 내가 여태 해왔던 프로젝트는 작은 프로젝트라 상태들이 크지 않았고 특별한 관리가 필요 없었다. </p>
<p>하지만 생각해보니 프로젝트가 커질수록 관리해야 하는 상태도 많아질 것이고 전역에서 관리하냐 지역에서 관리하냐 나눠질 것이다. 이때 리액트는 컴포넌트 내에서 지역으로 상태를 관리한다면 큰 상관이 없지만 만약 저 위에 있는 루트와 상태를 공유하고 업데이트 해야하는 상황이 생긴다면 어떻게 해야 할까?</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/461b4aac-f531-4f18-a6aa-f5e8b2cdeba5/%E1%84%91%E1%85%B3%E1%84%85%E1%85%B5%E1%84%82%E1%85%A9%E1%84%90%E1%85%B3-165.jpg" alt="일반적인 상태관리"></p>
<p>root에서 나에게 프롭스로 상태를 전달해야한다. 상태 변경 하나를 위해 이렇게 거쳐야할 것들이 많다니 당연히 작업해야 할 것이 늘어남과 동시에 오류의 가능성더 높아진다. </p>
<p>그렇다면 상태를 이렇게 받는 상황에서 타고타고타고를 반복하지 않고 리렌더링에 대한 고민 없이 한번에 똭!!! 상태를 받을 순 없을까? 내가 바꾸려는 상태들을 관리할 것들을 공간에 넣어 놓고 상태를 프롭스로 전달전달해서 받는 것이 아닌 다이렉트로 받을 수 있는 방법이 필요하다.</p>
<p>바로 이러한 상황에서 리덕스를 사용한다! 
상태 변경을 더 편리하고 오류는 더 적게 사용하기 위해.</p>
<h2 id="어떻게-사용할까">어떻게 사용할까?</h2>
<p>앞서 말한것과 같이 연결연결이 아닌 한 공간에서 다이렉트로 상태를 관리할 수 있는 공간이면 된다. 이것을 리덕스로 말하자면 상태를 관리할 수 있는 스토어라는 큰 덩어리를 만든다.
<img src="https://images.velog.io/images/dev-tinkerbell/post/39393388-9a4f-4d2a-ba9c-a9963fc29a9e/%E1%84%91%E1%85%B3%E1%84%85%E1%85%B5%E1%84%82%E1%85%A9%E1%84%90%E1%85%B3-165%204.jpg" alt="리덕스를 사용한 상태관리">
즉 리덕스를 어플리케이션에 설치하고 전역에서 상태 관리를 위한 스토어를 생성해야한다.  그리고 스토어의 입장에서 &quot;상태를 변경하겠다.&quot; 라는 요청이 들어오면 상태를 어떻게 변경할 것인지에 대한 함수를 생성해야 하고 &quot;상태를 변경하겠다.&quot; 라는 요청도 어떤 요청인지에 대해서도 지정해야한다. </p>
<p>또한 컴포넌트 입장에서 스토어의 상태가 변경 되었다는 것을 구독하고 변경된 상태를 가지고 리렌더링 할 수 있다.</p>
<blockquote>
<p><strong>MobX란?</strong>
상태 관리 라이브러리중에 Redux말고 MobX를 떠올릴 수도 있다. Redux는 하나의 어플리케이션 내에 하나의 스토어만 존재하지만 MobX는 여러개의 스토어 생성이 가능하다. 서비스가 커짐에 따라 스토어 내에 관련된 로직을 분리해서 관리한다면 더 효율적이지 않을까 싶다.</p>
</blockquote>
<blockquote>
<p><strong>Contaxt API와 Redux의 차이는?</strong>
Contaxt API는 Redux와 비슷한 개념으로 중앙에서 상태를 관리할 수 있는 도구이다. 하지만 Redux는 React뿐만 아니라 Vue, Angular에도 존재하는 개념이고 Contaxt API는 React내에만 존재한다. 또한 Contaxt API는 여러개의 저장소를 생성 할 수 있다.</p>
</blockquote>
<h2 id="store-action-reducer-들어는-봤다-손-🙌">store, action, reducer 들어는 봤다. 손 🙌</h2>
<ul>
<li>store : 상태를 관리하는 공간</li>
<li>action : 어떤 상태를 바꿀 것인지에 대한 타입으로 액션에 따라 리듀서가 동작</li>
<li>reducer : 어떻게 상태를 바꿀 것인지에 대한 함수</li>
</ul>
<h2 id="리액트에서-리덕스-이렇게-쓰면-될까">리액트에서 리덕스 이렇게 쓰면 될까?</h2>
<h3 id="redux-store생성">Redux store생성</h3>
<ol>
<li>action type 만든다.</li>
<li>action 생성 함수를 만든다.</li>
<li>reducer의 초기 상태(객체)를 만든다.</li>
<li>action type마다 실행 될 reducer 함수를 만든다.</li>
<li>createStore를 사용하여 <code>createStore(reducer)</code>로 스토어를 만든다.</li>
<li>root에 <code>Provider</code>를 사용하여 <code>store</code>를 props로 전달한다.<pre><code class="language-js">const store = createStore(reducer);
</code></pre>
</li>
</ol>
<p>ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById(&#39;root&#39;)
);</p>
<pre><code>### Redux 상태 가져오기 및 변경
- React의 `useSeletor`를 사용하여 상태를 가져온다.
```js
// 예시
  import { useSelector } from &#39;react-redux&#39;;

  const loading = useSelector((state) =&gt; state.auth.loading);</code></pre><ul>
<li><p>React의 <code>useDispatch</code>를 사용하여 상태를 변경한다.</p>
<pre><code class="language-js">// 예시
import { useDispatch } from &#39;react-redux&#39;;

const dispatch = useDispatch();
const login = useCallback(
  (email, password) =&gt; {
    dispatch(startLogin(email, password));
  },
  [dispatch]
);</code></pre>
</li>
</ul>
<blockquote>
<p>🧚‍♀️
<a href="https://github.com/tinkerbell93/React-Hackathon">리액트 리덕스를 사용한 해커톤 프로젝트</a>를 하기 전 많은 고민이 있었는데 결국 리덕스를 사용하는 프로젝트로 진행했다. 물론 프로젝트 자체가 크지 않았지만 나중을 대비해서 사용해보는 것도 정말 좋은 경험이라고 생각했기 때문이다. 하지만 앞서 말했듯이 잘 모르고 사용했기 때문에 리덕스를 한번 더 정리하고 가는게 맞다고 생각이 들었다. 정리한 내용이 완벽할 순 없겠지만 천천히라도 꾸준히 쌓아 가야겠다.</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/Redux_(JavaScript_library)">리덕스 위키백과</a></li>
<li><a href="https://velopert.com/3528">리덕스(Redux)를 왜 쓸까? 그리고 리덕스를 편하게 사용하기 위한 발악 (i)</a></li>
<li><a href="https://kimdabin.tistory.com/entry/React%EC%97%90%EC%84%9C-MobX-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-MobX%EB%9E%80">React에서 MobX 적용하기 + MobX란</a></li>
<li><a href="https://velog.io/@cada/React-Redux-vs-Context-API">React Redux vs Context API</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[display none이 transition이 안먹히는 이유]]></title>
            <link>https://velog.io/@dev-tinkerbell/display-none%EC%9D%B4-transition%EC%9D%B4-%EC%95%88%EB%A8%B9%ED%9E%88%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@dev-tinkerbell/display-none%EC%9D%B4-transition%EC%9D%B4-%EC%95%88%EB%A8%B9%ED%9E%88%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Tue, 03 Nov 2020 15:23:40 GMT</pubDate>
            <description><![CDATA[<p>간혹 자바스크립트를 사용하여 시각적으로 요소가 보였다 안보이는 작업을 할 경우가 있었는데 초반에는 애니메이션 같은 부드러운 효과에 대해 관심이 없었다가 점점 CSS의 기능들에 눈을 뜨면서 스르륵 하는 효과들에 대해 관심이 생겨 이곳 저곳에 적용해보았다. 하지만 <code>display</code>를 <code>none</code>, <code>block</code> 으로 제어했을때 <code>transition</code>을 먹였음에도 불구하고 스르륵하는 시각적인 효과를 볼 수 없었다.</p>
<p>코드로 좀 더 확실하게 짚고 넘어가자면 일단 버튼을 클릭하면 선택된 div요소의 높이가 커지는데 스르륵하는 것을 보여주고 싶다.</p>
<p>!codepen[Ellen27/embed/gOMmKdm?height=265&amp;theme-id=dark&amp;default-tab=css,result]</p>
<p>예제에도 있다시피 <code>transition</code>을 넣었는데도 불구하고 내가 원하는 효과는 없었고 딱.딱. 끊겨 생성이 된다. 조건을 모두 마춰줬는데 왜 그럴까 대체..?</p>
<p><img src="https://images.velog.io/images/dev-tinkerbell/post/a2553361-0f24-4fe9-b50d-b7966ecf9dcb/image.png" alt="박명수 나한테 어쩌라는 거야 짤"></p>
<p>하지만 그 이유의 답은 언제나 컴퓨터는 거짓말을 하지 않는다는 것이다. 컴퓨터는 잘못이 없으니 차근차근 그 이유를 살펴보고 해결방안까지 제안하려고 한다.</p>
<h1 id="📍display-none-block이-될-때-무슨일이-일어나길래">📍display none, block이 될 때 무슨일이 일어나길래..?</h1>
<p>요소가 화면에 출력되기 위해 무슨 과정을 거치는지부터 생각을 해보자. 일단 HTML과 CSS를 파싱후에 각각 DOM, CSSOM이 생성될 것이다. DOM과 CSSOM을 결합하여 렌더링 트리를 형성한다. 이 렌더링 트리는 화면에 출력될 요소들의 레이아웃을 계산하는 데 사용되고 픽셀을 화면에 렌더링하는 페인트 프로세스에 대한 입력으로 처리된다.</p>
<p>이때, 렌더링 트리는 화면에 출력되지 않아도 될 일부 노드(<code>meta</code>, <code>script</code> 등)와 CSS를 통해 숨겨지는 노드가 <strong>렌더링 트리에서 생략</strong>된다.</p>
<p><code>transition</code>은 두 상태에서 속성의 변화가 일정 기간에 걸쳐 일어나도록 하지만 <code>display: none</code> 상태에서 동적으로 클래스를 추가하여 <code>display: block</code>을 추가한다고 하면 렌더 트리에 없다가 추가되는 것이기 때문에 <code>transition</code>의 처음 시작점이 없다. 그래서 시각적으로<code>transition</code>이 동작되지 않는 것처럼 보이는 것이다. </p>
<h1 id="📍transition이-먹힐-수-있는-방법">📍Transition이 먹힐 수 있는 방법</h1>
<p>그렇다면 <code>tranition</code>이 되면서도 시각적으로 보였다 안보였다 할 수 있는 방법이 없을까?</p>
<p>없을리가...ㅎㅎ</p>
<p>일단 시각적인 요소만 숨기기 위함이라고 해도 2가지의 선택사항이 있는데,</p>
<ul>
<li>컨텐츠만 시각적으로 숨기지만 접근성 트리에는 있어야 하는 경우</li>
<li>컨텐츠도 시각적으로 숨기고 접근성 트리에도 없어야 하는 경우</li>
</ul>
<p>이 두가지의 경우로 예시를 들어보자</p>
<h2 id="컨텐츠만-시각적으로-숨기지만-접근성-트리에는-있어야-하는-경우">컨텐츠만 시각적으로 숨기지만 접근성 트리에는 있어야 하는 경우</h2>
<p>이 경우에는 시각적으로 화면에 요소는 보이지 않지만 접근성 트리에 있어야 하고 이럴땐 <code>diplay</code> <code>none</code> <code>block</code>으로 처리한다면 렌더링 트리에도 없기 때문에 접근성 트리에도 구현되지 않는다. 즉, 렌더링 트리에도 있어야 하지만 요소를 시각적으로만 숨겨져야 한다.</p>
<p>예제를 기준으로 방법은 매우 다양하다.</p>
<ul>
<li>height<pre><code class="language-css">/* box */
div {
width: 100%;
height: 0vh;
margin-top: 10px;
background: linear-gradient(180deg, rgba(238,174,202,1) 0%, rgba(148,187,233,1) 100%);
transition: all 0.3s;
}
.act {
height: 60vh;
}</code></pre>
</li>
<li>transform<pre><code class="language-css">div {
width: 100%;
height: 60vh;
transform: scaleY(0);
transform-origin: 0px 0px;
margin-top: 10px;
background: linear-gradient(180deg, rgba(238,174,202,1) 0%, rgba(148,187,233,1) 100%);
transition: all 0.3s;
}
.act {
transform: scaleY(1);
}</code></pre>
</li>
<li>opacity<pre><code class="language-css">div {
width: 100%;
height: 60vh;
opacity: 0;
margin-top: 10px;
background: linear-gradient(180deg, rgba(238,174,202,1) 0%, rgba(148,187,233,1) 100%);
transition: all 0.3s;
}
.act {
opacity: 1;
}</code></pre>
</li>
</ul>
<h2 id="컨텐츠도-시각적으로-숨기고-접근성-트리에도-없어야-하는-경우">컨텐츠도 시각적으로 숨기고 접근성 트리에도 없어야 하는 경우</h2>
<p>그리고 대부분의 경우, 요소를 시각적으로 숨긴다는 것은 컨텐츠를 숨긴다는 것을 의미하는데 이는 물론 스크린리더 또한 읽히면 안된다는 것을 의미한다고 생각한다. 이렇게 구현하기 위해서는 <code>visibility</code> 속성을 이용하면 된다.</p>
<p>!codepen[Ellen27/embed/Pozajya?height=265&amp;theme-id=dark&amp;default-tab=css,result]</p>
<p>또는 동적으로 클래스를 붙이기 전 <code>setTimeout</code>을 사용하여 렌더링트리가 생성 된 후 <code>transition</code>을 구현할 수도 있지만 리렌더링의 문제로 <code>visibility</code>속성을 추천한다.</p>
<blockquote>
<p>🧚‍♀️
코딩하면서 간혹 나는 잘 구현했다라고 생각했는데 생각대로 구현이 되지 않는 경우가 있다. 나의 코딩스타일이 처음엔 &quot;앗 왜 구현 안되지?&quot;라고 생각하면 바로 구글링해서 다른 해결방안부터 찾았는데 이제는 왜 그런지 이유를 찾아보니 매우 흥미롭고 다른 방안들의 장단점까지 알 수 있어서 매우 유익한것 같다. 
다른 해결방안만 찾아서 구현하는건 코딩에 매우 안좋은 습관 같지만 일단 시간이 급하다라고 생각이 들면 구현을 우선 시 하되, 그 부분은 필기 해놓고 나중에 어떤 원리로 왜 안됐는지에 대해 찾아보는 습관을 기르도록 해야겠다.
할 일 사서 만들기..ㅎㅎ (개발자는 매우 부지런해야한다... 할 일 너므너므 많음.. 😹</p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/display">display MDN</a></li>
<li><a href="https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction?hl=ko">렌더링 트리 생성, 레이아웃 및 페인트</a></li>
<li><a href="https://d2.naver.com/helloworld/59361">브라우저는 어떻게 동작되는가?</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Transitions/Using_CSS_transitions">transition MDN</a></li>
<li><a href="https://zephyrnet.com/ko/CSS%EC%97%90%EC%84%9C-%EC%9A%94%EC%86%8C%EB%A5%BC-%EC%88%A8%EA%B8%B0%EB%8A%94-10-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95/">CSS에서 요소를 숨기는 10 가지 방법</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹접근성 어디까지 신경써봤니?]]></title>
            <link>https://velog.io/@dev-tinkerbell/%EC%9B%B9%EC%A0%91%EA%B7%BC%EC%84%B1-%EC%96%B4%EB%94%94%EA%B9%8C%EC%A7%80-%EC%8B%A0%EA%B2%BD%EC%8D%A8%EB%B4%A4%EB%8B%88</link>
            <guid>https://velog.io/@dev-tinkerbell/%EC%9B%B9%EC%A0%91%EA%B7%BC%EC%84%B1-%EC%96%B4%EB%94%94%EA%B9%8C%EC%A7%80-%EC%8B%A0%EA%B2%BD%EC%8D%A8%EB%B4%A4%EB%8B%88</guid>
            <pubDate>Thu, 22 Oct 2020 16:29:13 GMT</pubDate>
            <description><![CDATA[<p>웹개발을 배우면서 중요하다고 강조되었던 웹접근성이었지만, 실무에서 당장 급하게 사용되는것이 아니다보니 뒤로 미뤄 놓기만 했고 실제로 적용하는 일이 드물었다. 
그러던 중 이디야 메뉴 페이지 프로젝트를 진행하게 되었고 웹접근성에 중점을 둔 사이트를 제작해보자는 목표가 생겼다. 처음으로 스크린리더 사용자까지 고려한 웹사이트를 제작하게 되었는데 특히나 WAI-ARIA라는 개념을 처음 접했고 웹을 제작할때 모두가 평등하고 편리한 웹을 위해 접근성을 더 고려해야 겠다는 생각으로 이번 프로젝트에서 사용한 WAI-ARIA와 웹접근성에 대해 정리해보려고 한다.</p>
<h1 id="📍웹접근성과-웹표준-헷갈리고-있니-hoxy">📍웹접근성과 웹표준 헷갈리고 있니 Hoxy..?</h1>
<p>실무에만 너무 급급하던 시절.. 웹이 돌아가기만 하면 된다는 아주아주 잘못된 생각으로 코딩을 했었다. 그리고 웹접근성과 웹표준의 개념을 접했을땐 뭔가 웹에 관련되고 웹을 사용할 때 편하게 해주는 것? 이라는 개념만 자리잡고 있을뿐 정확히 둘의 차이를 잘 몰랐다. 
<img src="https://images.velog.io/images/dev-tinkerbell/post/9205bae3-be12-45db-8025-9431e71fbb69/image.png" alt="윌리엄혹쉬 짤">
이런 개발자.. 나뿐이겠지만 혹시라도 이 둘의 차이를 모른다면 다시 한번 더 정리하자!</p>
<h2 id="웹접근성">웹접근성</h2>
<blockquote>
<p>웹 접근성(web accessibility)은 장애를 가진 사람과 장애를 가지지 않은 사람 모두가 웹사이트를 이용할 수 있게 하는 방식을 가리킨다. 사이트가 올바르게 설계되어 개발되고 편집되어 있을 때 모든 사용자들은 정보와 기능에 동등하게 접근할 수 있다.
📝 출처: 위키백과</p>
</blockquote>
<p>대표적으로 많이 알고 있는건 <code>image</code> 태그의 <code>alt</code> 속성이다. 이미지를 위한 대체텍스트를 넣을 수 있고 만약 시각적으로 제한된 상황이라면 보이스오버 등 보조기기로 어떤 이미지인지 알 수 있다.</p>
<p>하지만 웹기술이 발전됨에 따라 웹의 복잡성도 높아졌고 그만큼 일반 사용자, 장애를 가진 사람, 고령자 또한 웹의 사용성을 높이기 위해 <code>WAI-ARIA</code>등 다양한 방식으로 제공되어진다.</p>
<h2 id="웹표준">웹표준</h2>
<blockquote>
<p>웹 표준은 월드 와이드 웹의 측면을 서술하고 정의하는 공식 표준이나 다른 기술 규격을 가리키는 일반적인 용어이다. 최근에 이 용어는 웹 사이트를 작성하는 데 중요도가 높아지고 있으며 웹 디자인, 개발과 관계가 있다.
📝 출처: 위키백과</p>
</blockquote>
<p>위키백과에서 말하는 웹표준을 다시한번 정리해보자면 웹에서 표준적으로 사용되는 기술이나 규칙을 의미한다.</p>
<p>또한 웹표준은 웹접근성과 긴밀한 관계를 가지고 있다. 왜일까?
웹표준이 나온 이유부터 얘기하자면 각각 다른 브라우저들이 자신의 브라우저가 더 우수하다는 것을 보여주기위해 해당 브라우저만의 기능을 추가로 넣었는데 현재시점에서 다른 브라우저와 호환이 안되는 문제가 발생되었다. 그래서 오히려 웹접근성 측면에서는 마이너스가 되고 있기 때문에 웹접근성을 위해 기술들이 웹표준이 되어야하고 이러한 것으로 보았을때 이 둘은 긴밀한 관계가 이뤄진다.</p>
<p>웹표준을 준수하는 것은 W3C등의 표준화 기구에서 정의 해준 명세에 맞게 마크업을 하는 것이다.</p>
<h1 id="📍자-그래서-wai-aria가-뭔데">📍자, 그래서 WAI-ARIA가 뭔데?</h1>
<blockquote>
<p>WAI-ARIA(Web Accessibility Initiative – Accessible Rich Internet Applications)는 웹 페이지, 특히 동적 콘텐츠, 그리고 Ajax, HTML, 자바스크립트 및 관련 기술로 개발된 사용자 인터페이스 구성 요소의 접근성을 증가시키는 방법에 대해 규정한 W3C가 출판한 기술 사양이다.
📝 출처: 위키백과</p>
</blockquote>
<p>쉽게 말하자면 웹접근성을 높이기 위한 방법 중 하나이다. 
ARIA는 HTML을 보충해 일반적으로 보조 기술이 알 수 없는 상호작용 및 흔히 쓰이는 어플리케이션 위젯에 필요한 정보를 제공한다.</p>
<h2 id="왜-wai-aria가-필요하지">왜 WAI-ARIA가 필요하지?</h2>
<p>HTML, CSS, JavaScript를 사용하여 동적으로 웹 페이지가 구현됨에 따라 그 위젯들을 설명할 수 있는 것은 HTML4에서는 명세가 되어 있지 않았다. 그래서 대부분의 개발자들이 <code>&lt;div&gt;</code> <code>&lt;span&gt;</code> 을 덕지덕지 붙여놓는 상황을 많이 보았을 것이다.
<img src="https://images.velog.io/images/dev-tinkerbell/post/7084fd3e-03a4-4e1c-9d87-202273f02f44/image.png" alt="좌절 짤">
또한 슬라이드, 프로그레스 바 등등 동적 콘텐츠들은 보조기술이 제대로 인식하지 못하였다. 그래서 HTML5에서 위젯들의 충분한 정보를 제공할 수 있는 태그들이 나왔지만 동적 콘텐츠는 그렇지 못했고 그렇기 때문에 콘텐츠의 디테일한 설명을 제공하기 위해 ARIA가 필요하다.</p>
<h2 id="wai-aria-언제-사용해">WAI-ARIA 언제 사용해?</h2>
<p>WAI-ARIA는 상황에 따라 다른 속성을 제공해야한다. </p>
<p>대표적인 예)</p>
<ul>
<li>탭 목록, 탭, 탭 패널(role=&quot;tablist|tab|tabpanel&quot;).</li>
<li>툴팁(role=&quot;tooltip&quot;).</li>
<li>알럿(role=&quot;alert&quot;).</li>
<li>알럿 대화상자(role=&quot;alertdialog&quot;).</li>
<li>대화상자(role=&quot;dialog&quot;).</li>
<li>탐색(nav, role=&quot;navigation&quot;).</li>
<li>보충(aside, role=&quot;complementary&quot;).</li>
<li>의미 없음(role=&quot;none presentation&quot;).</li>
<li>현재 상태(aria-current=&quot;token&quot;).</li>
<li>선택 상태(aria-selected=&quot;true|false|undefined&quot;).</li>
<li>팝업 상태(aria-haspopup=&quot;token&quot;)</li>
<li>확장 상태(aria-expanded=&quot;true|false|undefined&quot;)</li>
<li>눌림 상태(aria-pressed=&quot;tristate&quot;)</li>
<li>숨김 상태(aria-hidden=&quot;true|false|undefined&quot;)</li>
<li>제어 대상(aria-controls=&quot;ID reference list&quot;)</li>
<li>실시간(aria-live=&quot;token&quot;)</li>
<li>간결한 설명 참조(aria-labelledby=&quot;ID reference list&quot;)</li>
<li>간결한 설명(aria-label=&quot;string&quot;)</li>
<li>자세한 설명 참조(aria-describedby=&quot;ID reference list&quot;)</li>
<li>모달(aria-modal=&quot;true|false&quot;)</li>
</ul>
<p>📝 출처 <a href="https://tech.lezhin.com/2018/04/20/wai-aria">레진 WAI-ARIA 가이드라인 소개.</a></p>
<h2 id="wai-aria-어떻게-사용해">WAI-ARIA 어떻게 사용해?</h2>
<p>나는 이번 프로젝트에서 <code>aria-label</code>, <code>aria-labelledby</code>, <code>aria-haspopup</code>, <code>aria-pressed</code> 을 사용했으므로 간단히 이 4가지예시를 들어 볼 수 있겠다.</p>
<h3 id="aria-labelstring"><code>aria-label=&quot;string&quot;</code></h3>
<p>간단한 설명을 제공할 태그에 속성을 부여한다.</p>
<pre><code class="language-html">&lt;button type=&quot;button&quot; aria-label=&quot;상세정보 닫기&quot; title=&quot;상세정보 닫기&quot;&gt;&lt;/button&gt;</code></pre>
<h3 id="aria-labelledbyid"><code>aria-labelledby=&quot;id&quot;</code></h3>
<p>디테일한 설명을 제공하고 있는 태그의 아이디를 삽입한다.</p>
<pre><code class="language-html">&lt;section aria-labelledby=&quot;hot-brownie-chocolate&quot;&gt;
  &lt;h3 id=&quot;hot-brownie-chocolate&quot;&gt;
    HOT 브라우니 쇼콜라
    &lt;span lang=&quot;en&quot;&gt;Brownie Chocolate&lt;/span&gt;
  &lt;/h3&gt;
  &lt;p&gt;
    깊고 진한 초콜릿의 맛에 부드러운 휘핑크림과 브라우니를 
    함께 어울러져 고급스러운 디저트 같은 초콜릿 음료
  &lt;/p&gt;
&lt;/section&gt;</code></pre>
<h3 id="aria-haspopuptruemenudialoglistboxtreegridfalsedefault"><code>aria-haspopup=&quot;true|menu|dialog|listbox|tree|grid|false(default)&quot;</code></h3>
<p>어떤 종류의 popup이 있다는 정보(상태)를 제공한다.</p>
<pre><code class="language-html">&lt;button type=&quot;button&quot; aria-haspopup=&quot;dialog&quot;&gt;
  클릭하시면 상세정보를 확인할 수 있습니다.
&lt;/button&gt;</code></pre>
<h3 id="aria-pressedtruefalsemixedundefineddefault"><code>aria-pressed=&quot;true|false|mixed|undefined(default)&quot;</code></h3>
<p>요소의 눌림 상태를 제공한다.</p>
<pre><code class="language-html">&lt;button type=&quot;button&quot; aria-pressed=&quot;false&quot;&gt;
  클릭하시면 상세정보를 확인할 수 있습니다.
&lt;/button&gt;</code></pre>
<p>내가 사용한 것은 ARIA에서 제공하는 것에 극히 일부분에 불과하다. 더 많은 ARIA 사용법을 알고 싶다면 해당 <a href="https://www.w3.org/TR/wai-aria-1.1/">링크</a>를 참조하기 바란다. <strong>또한 ARIA를 사용하는 것이 무조건적으로 맞는 것은 아니다.</strong> 일단 ARIA를 사용하기 전, 의미있는 HTML을 작성한 후에 웹접근성 관점에서 추가적으로 제공되어야 할 정보가 있을 때 사용해야 한다.</p>
<blockquote>
<p>🧚‍♀️
프로젝트에서 처음 이 개념을 접했을때 자신들의 주관에 따라 ARIA 속성이 다 달랐다. 하지만 조원들과의 협의를 통해 우리가 생각한 개념과 명세되어 있는 개념이 최대한 같은 의미인것을 제공하려고 노력했다. 
실질적으로 장애에 대한 차별은 외부적으로 많은 이슈가 되고 있는데 웹에 관련하여 크게 못느꼈다는 것은 그만큼 내가 관심이 없었다는 것에 대해 부끄러웠다.
이번 기회를 통해 더 많은 사람들이 웹접근성에 관심이 생겼으면 좋겠다. </p>
</blockquote>
<blockquote>
<p>그렇게 해서 완성된 <a href="https://tinkerbell93.github.io/edyia-clone/">이디야프로젝트</a> </p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://seulbinim.github.io/WSA/s">웹접근성과 웹표준</a></li>
<li><a href="https://enarastudent.tistory.com/entry/%EC%9B%B9-%ED%91%9C%EC%A4%80-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1-%ED%81%AC%EB%A1%9C%EC%8A%A4-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95%EC%97%90-%EB%8C%80%ED%95%9C-%EB%B0%94%EB%A5%B8-%EC%9D%98%EB%AF%B8">웹 표준, 웹 접근성, 크로스 브라우징에 대한 바른 의미</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/Accessibility/ARIA">ARIA MDN</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/Accessibility/An_overview_of_accessible_web_applications_and_widgets">An overview of accessible web applications and widgets</a></li>
<li><a href="https://github.com/lezhin/accessibility/blob/master/aria/README.md">레진 WAI-ARIA 가이드라인 GigHub</a></li>
<li><a href="https://www.youtube.com/channel/UCTI6h7Vb05Td63qHQ3wjySQ">AOA11Y 유튜브</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS Content 속성]]></title>
            <link>https://velog.io/@dev-tinkerbell/CSS-Content-%EC%86%8D%EC%84%B1</link>
            <guid>https://velog.io/@dev-tinkerbell/CSS-Content-%EC%86%8D%EC%84%B1</guid>
            <pubDate>Thu, 22 Oct 2020 06:32:25 GMT</pubDate>
            <description><![CDATA[<p>CSS content는 string뿐만 아니라 image, counter, attr 또한 값으로 지정할 수 있다.</p>
<h1 id="content-속성-값-리스트">content 속성 값 리스트</h1>
<h2 id="string">string</h2>
<p>값이 문자열인 속성</p>
<pre><code class="language-css">::before{
    content: “텍스트”;
}</code></pre>
<h2 id="image">image</h2>
<p>값이 이미지인 속성으로 <code>url(&quot;이미지경로&quot;)</code> 를 입력한다. 또한 이미지 로드 실패시 보여줄 대체텍스트를 <code>/</code> 로 구분하여 넣을 수 있다.</p>
<pre><code class="language-css">::before{
    content: url(&quot;이미지경로&quot;);
    content: url(&quot;이미지경로&quot;)/&quot;대체 텍스트&quot;;
    content: linear-gradient(#aaa, #ddd);
}</code></pre>
<h2 id="counter">counter</h2>
<p>자동으로 번호를 매길 수 있는 변수로 CSS규칙에 따라 값이 증가 또는 감소한다.</p>
<h3 id="counter-1">counter</h3>
<pre><code class="language-css">ol{
    /* 구현 할 conuter의 초기값 지정 */
    counter-reset: 함수명;
    list-style: none;
}

li::before{
    /* 카운터 값을 1씩 증가시킨다. */
    counter-increment: 함수명;
    /* 카운터 값을 표시한다. */
    content: counter(함수명);
}</code></pre>
<h3 id="counters">counters</h3>
<p>중첩된 다른 레벨의 카운터를 텍스트를 삽입하여 분리를 할 수 있다.</p>
<pre><code class="language-css">ol{
    /* 구현 할 conuter의 초기값 지정 */
    counter-reset: 함수명;
     list-style: none;
}

li::before{
    /* 카운터 값을 1씩 증가시킨다. */
    counter-increment: 함수명;
    /* 카운터 값을 표시한다. */
    content: counters(함수명, &quot;-&quot;) &quot; &quot;;
}</code></pre>
<p>!codepen[Ellen27/embed/wvWoadX?height=265&amp;theme-id=dark&amp;default-tab=css,result]</p>
<h2 id="attr">attr</h2>
<p>요소의 속성을 문자열로 변환하여 브라우저에 보여준다.</p>
<pre><code class="language-html">&lt;p title=“가사” data-text=&quot;마르고 닳도록” &gt; 
    동해물과 백두산이
&lt;/p&gt;</code></pre>
<pre><code class="language-css">p::before{
    /* attr의 값과 문자열 “ - ” 출력 */
    content: attr(title) &quot; - &quot;;
}
p::after{
    /* attr의 값 도출 */
    content: attr(data-text);
}</code></pre>
<p>!codepen[Ellen27/embed/KKpjyNz?height=265&amp;theme-id=dark&amp;default-tab=css,result]</p>
<blockquote>
<p>🧚‍♀️
나는 CSS의 content 속성을 주로 가상요소 선택자인 <code>::after</code>, <code>::before</code> 에 <strong>문자열 또는 빈 값</strong>으로 넣어 스타일링 용도로만 사용했다. 하지만 content의 값으로 문자열 이외에도 다양한 값들이 들어 갈 수 있다는 것을 배웠고 필요시에 유용하게 사용되어질 것 같아 기록하고 싶다는 욕구가 솟았다!!
자주 사용하는 속성들은 아니지만 필요시에 잊지말고 사용해보고 싶다. </p>
</blockquote>
<p><strong>📝 Reference</strong></p>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters">css 카운터 사용하기 MDN</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>