<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Juyeon.it.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 18 Jul 2022 10:56:13 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Juyeon.it.log</title>
            <url>https://images.velog.io/images/jay_jykim91/profile/81dfd68e-c184-48d5-967c-0c3bcec0000b/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Juyeon.it.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jay_jykim91" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Project Log] AllThatWord]]></title>
            <link>https://velog.io/@jay_jykim91/Project-Log-AllThatWord</link>
            <guid>https://velog.io/@jay_jykim91/Project-Log-AllThatWord</guid>
            <pubDate>Mon, 18 Jul 2022 10:56:13 GMT</pubDate>
            <description><![CDATA[<p><strong>You can check this website on <a href="https://github.com/Jay-JYKim91/AllThatWord">Github repo</a> or <a href="https://all-that-word.vercel.app/">this link</a>.</strong></p>
<h2 id="day-1">Day 1</h2>
<h3 id="what-i-did">What I did</h3>
<ol>
<li>Set up for the project: Install React, Typescript, Tailwind, react-router-dom, ESLint, Prettier</li>
<li>Update README.md</li>
<li>Style Header, Footer using tailwind</li>
</ol>
<p>*<em>Source: *</em></p>
<ul>
<li><a href="https://koras02.tistory.com/106">[React] create-react-app &amp; Typescript 초기 세팅법</a></li>
<li><a href="https://velog.io/@he0_077/React-Typescript-eslint-prettier-%EC%84%A4%EC%A0%95">[React] Typescript + eslint + prettier 설정</a></li>
</ul>
<h3 id="troubleshooting">Troubleshooting</h3>
<ul>
<li>VSCode prettier format on save doesn&#39;t work, So I followed <a href="https://stackoverflow.com/a/64510650">this stackoverflow answer</a> and changed &#39;Editor: Default Formatter&#39; to &#39;esbenp.prettier-vscode&#39; on setting.json file.</li>
</ul>
<h2 id="day-2">Day 2</h2>
<h3 id="what-i-did-1">What I did</h3>
<ol>
<li>Create SearchBar component</li>
<li>Install react-qurey, axios</li>
<li>Create Search page and fetch data using react-query and axios</li>
<li>Install react-icon</li>
<li>Style isLoading and isError using tailwind</li>
</ol>
<p>*<em>Source: *</em></p>
<ul>
<li><a href="https://reactrouter.com/docs/en/v6/hooks/use-params">react-router-dom useParams</a></li>
<li><a href="https://reactrouter.com/docs/en/v6/components/link">react-router-dom Link</a></li>
</ul>
<h3 id="troubleshooting-1">Troubleshooting</h3>
<ul>
<li>I got an error message said &quot;Argument of type &#39;string | undefined&#39; is not assignable to parameter of type &#39;string&#39;&quot;. But I know that it is string, so I used non-null assertion operator. <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator">TypeScript Documentation</a></li>
</ul>
<h2 id="day-3">Day 3</h2>
<h3 id="what-i-did-2">What I did</h3>
<ol>
<li>Style Search page</li>
<li>Install firebase for login function</li>
<li>Implement &#39;log in with google&#39;, &#39;log in with github&#39; function</li>
</ol>
<p>*<em>Source: *</em></p>
<ul>
<li><a href="https://firebase.google.com/docs/auth/web/start">firebase Documentation Authentication</a></li>
<li><a href="https://reactjs.org/docs/hooks-reference.html#usecontext">react useContext</a></li>
</ul>
<h3 id="troubleshooting-2">Troubleshooting</h3>
<ul>
<li>I want something to handle login status.<ul>
<li>followed <a href="https://workshop-code.tistory.com/63?category=723300">this blog</a></li>
<li>and I&#39;m not used to the concept of &#39;useContext&#39; and <a href="https://cocoon1787.tistory.com/801">this blog post</a> helped me understand.</li>
</ul>
</li>
</ul>
<h2 id="day-4">Day 4</h2>
<h3 id="what-i-did-3">What I did</h3>
<ol>
<li>Implement &#39;save word&#39; function and connect to firebase Realtime Database</li>
<li>Implement Admin page to show saved words</li>
</ol>
<p>*<em>Source: *</em></p>
<ul>
<li><a href="https://firebase.google.com/docs/database/web/start">firebase Documentation Realtime Database</a></li>
</ul>
<h3 id="troubleshooting-3">Troubleshooting</h3>
<ul>
<li>I want to add key(string type)-value(object) object to &#39;words&#39; object, but I got an error message said &#39;Element implicitly has an &#39;any&#39; type because expression of type &#39;string&#39; can&#39;t be used to index type &#39;{}&#39;.&#39; And I realized that I need to define the key type of the object. So I made an interface called LooseObj. <a href="https://velog.io/@dongdong98/index-Signature-%EB%8F%99%EC%A0%81%EC%9C%BC%EB%A1%9C-Object%EC%97%90-property-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0">index Signature</a><pre><code>export interface LooseObj {
  [key: string]: object;
}</code></pre></li>
</ul>
<h2 id="day-5">Day 5</h2>
<h3 id="what-i-did-4">What I did</h3>
<ol>
<li>Implement change viewmode function on admin page</li>
<li>Implement flashcard function on admin page</li>
</ol>
<p>*<em>Source: *</em></p>
<ul>
<li><a href="https://www.section.io/engineering-education/how-to-create-a-carousel-using-react-class-components-and-tailwind-css/">How to Create a Carousel using React Class Components and Tailwind CSS</a></li>
<li><a href="https://codepen.io/mondal10/pen/WNNEvjV">Card flip on onClick</a></li>
</ul>
<h3 id="troubleshooting-4">Troubleshooting</h3>
<ul>
<li>I want to get blue box element(the parent elemenept) whenever I click that element. But when I clicked green box part, I got green box instead of blue box. I need kind of the opposite function of e.stopPropagation(). I couldn&#39;t find the exact function that works exactly what I want. But I can implement by checking the element has specific class that I assigned to the blue box element manually. </li>
</ul>
<img src="https://velog.velcdn.com/images/jay_jykim91/post/27eea924-0705-4c77-91e0-7c8d44b36701/image.png" width="40%" style="margin: auto" />

<h2 id="day-6">Day 6</h2>
<h3 id="what-i-did-5">What I did</h3>
<ol>
<li>Style responsive design</li>
<li>Fix minor errors</li>
</ol>
<h3 id="troubleshooting-5">Troubleshooting</h3>
<ul>
<li><p>I made a function that moves to another page when I clicked synonyms or antonyms. But when I move to another page with a different keyword, the input value on the search bar doesn&#39;t change to the changed keyword. So I made an optional prop called &#39;query&#39; and used useEffect to change the input value whenever the query changed.</p>
<pre><code>  type Prop = {
        query?: string;
  };

  const SearchBar: React.FC&lt;Prop&gt; = ({ query }) =&gt; {
        const [inputValue, setInputValue] = useState(query || &#39;&#39;);

        useEffect(() =&gt; {
          setInputValue(query || &#39;&#39;);
        }, [query]);

        ...
  }</code></pre></li>
</ul>
<h2 id="day-7">Day 7</h2>
<h3 id="what-i-did-6">What I did</h3>
<ol>
<li>Implement dark mode</li>
<li>Deploy using vercel</li>
<li>Update README.md</li>
</ol>
<p>*<em>Source: *</em></p>
<ul>
<li><a href="https://tailwindcss.com/docs/dark-mode">tailwindcss Dark Mode</a></li>
</ul>
<h3 id="troubleshooting-6">Troubleshooting</h3>
<ul>
<li>I deployed using vercel but got an error about firebase api keys. So I googled &#39;how to add environment variables on vercel&#39; and I set some firebase api keys by following <a href="https://vercel.com/support/articles/how-to-add-vercel-environment-variables">this article</a>.</li>
</ul>
<h2 id="day-8">Day 8</h2>
<h3 id="what-i-did-7">What I did</h3>
<ol>
<li>Fix minor errors</li>
</ol>
<h3 id="troubleshooting-7">Troubleshooting</h3>
<ul>
<li><p>When I searched &#39;sp&#39;, the result was like the image under this paragraph. There were many Noun definition. So I made an empty array. And when I mapped definitions of word, I pushed &#39;part of speech&#39; of one definition to array. After that, I checked if this part of speech is already in the array. If so, I didn&#39;t return that definition. </p>
<img src="https://velog.velcdn.com/images/jay_jykim91/post/61d60c8a-f258-4ab4-96a0-697a6eea6158/image.png" width="50%" style="margin: auto" />
```
  {data.meanings.map((meaning: Meaning, index: number) => {
      if (index > 0) {
          arr.push(data.meanings[index - 1].partOfSpeech);
        }

<pre><code>    return (
      !arr.includes(meaning.partOfSpeech) &amp;&amp; (
        &lt;div key={meaning.partOfSpeech}&gt;
            ...
        &lt;/div&gt;
    )</code></pre><p>  }</p>
<pre><code></code></pre></li>
</ul>
<h2 id="day-9-10-11">Day 9, 10, 11</h2>
<h3 id="what-i-did-8">What I did</h3>
<ol>
<li>Implement multiple folder function</li>
<li>Deploy using vercel</li>
<li>Update README.md</li>
</ol>
<h3 id="troubleshooting-8">Troubleshooting</h3>
<ul>
<li>I used firebase realtime database to save users&#39; words. When I deleted all words, the database deleted all data including userId. So that makes a lot of errors on my app. So I saved &#39;isSignin&#39; data when the user signs in at first. It prevents deleting all data of the user. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[후기] 데이터리안 SQL 데이터분석캠프]]></title>
            <link>https://velog.io/@jay_jykim91/%ED%9B%84%EA%B8%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A6%AC%EC%95%88-SQL-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B6%84%EC%84%9D%EC%BA%A0%ED%94%84</link>
            <guid>https://velog.io/@jay_jykim91/%ED%9B%84%EA%B8%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A6%AC%EC%95%88-SQL-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B6%84%EC%84%9D%EC%BA%A0%ED%94%84</guid>
            <pubDate>Sun, 03 Jul 2022 06:38:42 GMT</pubDate>
            <description><![CDATA[<h2 id="수강-계기">수강 계기</h2>
<p>2년 전 쯤에 코딩 부트캠프를 수강하면서 PostgreSQL을 배웠었다. 그때는 풀스택 웹개발을 배우면서 데이터베이스를 다루는 데 필요한 정도(DB를 만들고 보여주는 정도)로만 배워서 그 당시에도 &#39;이거 제대로 배워보면 재미있겠다&#39;라는 생각을 했었다. 그 후 프론트엔드 개발에 집중하면서 공부도 하고 일을 하기도 했지만 내가 진짜 개발자가 맞나 라는 의심이 자꾸 들어 평소에 관심이 있었던 다른 것들도 많이 배워보면서 앞으로의 정체성을 찾아가고 싶어서 SQL 데이터 분석 관련 공부도 해보기로 했다.</p>
<p>데이터리안을 처음 알게 된 건 스여일삶이 운영하는 오픈카톡방에서였고, 데이터리안이 운영하는 SQL 데이터분석 캠프가 있다는 것은 22년 1,2월 정도부터 알게되어 홈페이지를 여러번 방문했다. 이때 매번 방문 할 때마다 홈페이지에 업데이트가 있어서 &#39;열심히 운영을 하고 계시는구나, 발전을 시키고 계시는구나&#39; 하는 생각이 들어 &#39;데이터 분석 관련을 수업을 듣는다면 꼭 여기서 들어야지&#39; 라는 생각을 했다. 하지만 구경만 하고 결제를 하지 못하다가 4월에 일을 그만두면서 시간이 생겨 5월 입문반, 6월 실전반 패키지를 구매했다.</p>
<h2 id="수강-후기">수강 후기</h2>
<h3 id="난이도-⭐️-⭐️-⭐️">난이도: ⭐️ ⭐️ ⭐️</h3>
<p>입문반까지는 전혀 어렵다고 느끼지 않았던 것 같다. 온라인 세션 때마다 워낙 쉽게 잘 풀어서 설명해주시기도 하고, 매주 과제를 하면서 자연스럽게 예습, 복습이 돼서 아주 좋았다. 과제가 많아서 힘들다는 후기도 꽤 있는 거 같지만 난 온라인 세션 만큼이나 과제로 내주신 인프런 강의듣기, SQL 문제 풀어보기 등을 하면서 더 많이 배우고 SQL 문법에 익숙해지는 시간이었다고 느낀다.
실전반에 들어와서는 머리가 꽤 아팠다. 확실히 원하는 결과를 뽑아내기 위해 SQL 쿼리를 짜는 과정을 이해하는데 시간이 더 들어갔고 특히 과제로 EDA(Exploratory Data Analysis)를 할 땐 힘들었지만 하고 나면 확실히 다음 온라인 세션 들을 때 도움이 많이 돼서 이 과정이 중요하구나를 한번 더 깨닫는 계기가 되기도 했다. 과제를 하면서 연습문제를 풀고나서 온라인 세션 때 다시 풀어주시는 경우가 있는데 그럴 때마다 내가 문제를 푼 방법과 수업 때 설명해주시는 방법이 다르면 &#39;이렇게 풀 수도 있구나&#39;를 느끼면서 &#39;어떤 게 더 효율적인 쿼리일까&#39;를 개인적으로 생각 해볼 수 있게 됐다. 실전반 들어오면서는 리텐션 분석, 퍼널 분석 등 현업에서 사용할 수 있는 SQL 쿼리를 작성해보았는데 처음엔 무슨 말인지 이해가 안될 수 있지만 온라인 세션을 듣다보면 분석을 하기 위해 단계를 나누어 설명을 해주셔서 이해에 도움이 됐다. 그리고 그 과정에서 데이터 분석 결과를 반영하여 합리적인 의사결정을 할 수 있게 도움을 줄 수 있다는 면에서 데이터 분석이 아주 매력적으로 느껴졌다.</p>
<h3 id="만족도-⭐️-⭐️-⭐️-⭐️-⭐️">만족도: ⭐️ ⭐️ ⭐️ ⭐️ ⭐️</h3>
<p>일단 지금 내 상황에서는 &#39;와, 너무 재밌네. 그럼 난 이제 데이터 분석가가 될테야!&#39; 이건 아닌 것 같다. 개인적으로는 DB를 보면서 원하는 데이터를 뽑아내는 과정이 아주 재미있고, 데이터 분석 결과가 어떤 의사 결정에 단단한 근거가 될 수도 있다는 것 또한 아주 매력적이지만 그것들이 지금 웹개발을 중심으로 공부를 하고 있는 내가 완전히 데이터분석가가 되기로 마음을 바꿀 정도는 아니라는 뜻이다. 오히려 원하는 데이터를 마음대로 뽑아낼 수 있는, SQL쿼리도 잘 짜는 개발자가 더 끌리는 거 같다. <del>개인적으로는 어쨌든 웹 개발 쪽으로 마음을 좀 더 단단하게 갖게되어 오히려 좋다(?)</del></p>
<p>그럼에도 불구하고 만족도가 별 5개인 이유는 8주라는 짧은 기간동안 </p>
<ol>
<li>SQL 코딩테스트 문제 푸는 것에 별로 두려움을 갖지 않게 되었다.</li>
<li>실제 분석가들이 어떻게 데이터를 바라보고 필요한 데이터를 어떻게 뽑아서 거기서 어떤 인사이트를 뽑아내는지를 실제로 경험해 볼 수 있는 시간이었다. </li>
<li>수업을 진행하시는 선미님, 민주님, 보민님, 더불어 조교님들까지 꼼꼼하게 설명해주시고 결국 스스로 해낼 수 있게 도와주시는 분위기가 좋았다. </li>
<li>캠프에 포함되어 받을 수 있는 인프런 강의, 수업자료, 복습자료, SQL cheat sheet, 데이터리안 블로그 글 등의 자료들이 너무 잘 정리가 되어있다. 앞으로도 종종 꺼내 보려고 개인적으로도 잘 정리해 두었다.</li>
<li>캠프 수강했던 사람들은 매달 열리는 &lt;데이터리안 세미나&gt;가 무료다! 지금까지 2번 들었는데 만족스러워서 매달 들어볼 예정!</li>
<li>중간에 스터디 원하는 사람들을 위해 스터디 그룹도 짜주신다. 우리 팀은 매주 주말에 한번씩 SQL 문제를 같이 풀었다.</li>
<li>수료는 했지만 앞으로도 슬랙 채널에서 정보를 주고 받거나 SQL 관련 질문을 할 수 있다!</li>
</ol>
<p>이번에 학습한 SQL을 잊지 않게 위해 앞으로도 꾸준히 Leetcode, HackerRank 등에서 SQL 문제를 풀어볼 예정이다.(실제로 지난주부터 하고 있다) 그리고 종종 데이터리안 블로그 글도 읽고 홈페이지 구경도 하면서 항상 발전하는 데이터리안을 응원하고 싶다 🎉</p>
<p>데이터리안에 관심이 생기신다면? <a href="https://www.datarian.io/">datarian</a> 홈페이지에 방문 해보세요 :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React-redux_생활코딩]]></title>
            <link>https://velog.io/@jay_jykim91/React-redux%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9</link>
            <guid>https://velog.io/@jay_jykim91/React-redux%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9</guid>
            <pubDate>Sun, 19 Jun 2022 09:39:25 GMT</pubDate>
            <description><![CDATA[<h3 id="구현하려고-하는-것">구현하려고 하는 것</h3>
<ul>
<li>Right3 아래에 있는 +버튼을 누르면 Root, Left1,2,3에 있는 숫자가 하나씩 늘어나도록 만들기
<img src="https://velog.velcdn.com/images/jay_jykim91/post/30df5739-3859-47b5-817a-499341fcd85c/image.png" alt="Without redux"></li>
</ul>
<h4 id="redux-없이-구현">redux 없이 구현</h4>
<ul>
<li>prop에 onIncrease를 넣어 위로 쭉 올려서 구현함</li>
<li>박스가 1000개라고 해보면 너무 번거로운 일이 됨</li>
</ul>
<h4 id="redux를-이용하여-구현">redux를 이용하여 구현</h4>
<ul>
<li><p>redux는 독립적인 도구! </p>
<ul>
<li>react라는 독립적인 도구와 redux라는 독립적인 도구를 연결하는 도구가 react redux임</li>
<li>npm install redux react-redux</li>
</ul>
</li>
<li><p>react-redux 3대장</p>
<ul>
<li>Provider: state들을 어떤 컴포넌트에 제공할 것인가. 울타리처럼 감쌀 때 씀, props으로 반드시 store를 가지고 있어야 함</li>
<li>useSelector: state를 무선으로 연결할 때 사용. 함수를 인자로 받음</li>
<li>useDispatch</li>
</ul>
</li>
<li><p>장점!!!</p>
<ul>
<li><ul>
<li>버튼을 클릭해서 Left3에 있는 값이 바뀔 때, number라는 state를 사용하고 있는 Left3만 다시 랜더링 되고 이것의 부모 요소들(Left2, Left1 등)을 다시 랜더링하지 않음 -&gt; 퍼포먼스에 좋음</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>import React, { useState } from &#39;react&#39;;
import &#39;./style.css&#39;;
import { createStore } from &#39;redux&#39;;
import { Provider, useSelector, useDispatch, connect } from &#39;react-redux&#39;;

// 스토어 생성시 반드시 필요한 것
// 스토어 안에 있는 state를 어떻게 바꿀 것인가를 결정함
// parameter로 현재 상태인 currentState와 어떻게 바꿀 것인가 하는 action을 받음
function reducer(currentState, action) {
  if (currentState === undefined) {
    // 기본 상태 설정
    return {
      number: 1,
    };
  }
  // 과거의 값을 복제하여 복제된 값을 수정하면 불변성 유지 가능
  const newState = { ...currentState };
  // useDispatch 관련
  if (action.type === &#39;PLUS&#39;) {
    newState.number++;
  }
  // 새로운 값 리턴
  return newState;
}

// 수정하면 안되니까 상수로 선언
// 스토어 생성
const store = createStore(reducer);

export default function App() {
  return (
    &lt;div id=&quot;container&quot;&gt;
      &lt;h1&gt;Root&lt;/h1&gt;
      &lt;div id=&quot;grid&quot;&gt;
        &lt;Provider store={store}&gt;
          &lt;Left1&gt;&lt;/Left1&gt;
          &lt;Right1&gt;&lt;/Right1&gt;
        &lt;/Provider&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}
function Left1(props) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Left1 &lt;/h1&gt;
      &lt;Left2&gt;&lt;/Left2&gt;
    &lt;/div&gt;
  );
}
function Left2(props) {
  console.log(&#39;2&#39;);
  return (
    &lt;div&gt;
      &lt;h1&gt;Left2 : &lt;/h1&gt;
      &lt;Left3&gt;&lt;/Left3&gt;
    &lt;/div&gt;
  );
}
function Left3(props) {
  console.log(&#39;3&#39;);
  // store에 저장되어 있는 number state와 Left3의 number를 무선으로 연결
  const number = useSelector((state) =&gt; state.number);
  return (
    &lt;div&gt;
      &lt;h1&gt;Left3 : {number}&lt;/h1&gt;
    &lt;/div&gt;
  );
}
function Right1(props) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Right1&lt;/h1&gt;
      &lt;Right2&gt;&lt;/Right2&gt;
    &lt;/div&gt;
  );
}
function Right2(props) {
  return (
    &lt;div&gt;
      &lt;h1&gt;Right2&lt;/h1&gt;
      &lt;Right3&gt;&lt;/Right3&gt;
    &lt;/div&gt;
  );
}
function Right3(props) {
  const dispatch = useDispatch();
  return (
    &lt;div&gt;
      &lt;h1&gt;Right3&lt;/h1&gt;
      &lt;input
        type=&quot;button&quot;
        value=&quot;+&quot;
        onClick={() =&gt; {
          // reducer가 호출됨
          dispatch({ type: &#39;PLUS&#39; });
        }}
      &gt;&lt;/input&gt;
    &lt;/div&gt;
  );
}</code></pre><h3 id="참고자료">참고자료</h3>
<p><a href="https://www.youtube.com/watch?v=yjuwpf7VH74">react-redux (2022년 개정판)</a> by 생활코딩</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript_Handbook]]></title>
            <link>https://velog.io/@jay_jykim91/TypeScriptHandbook</link>
            <guid>https://velog.io/@jay_jykim91/TypeScriptHandbook</guid>
            <pubDate>Sat, 11 Jun 2022 09:02:40 GMT</pubDate>
            <description><![CDATA[<h3 id="타입스크립트란">타입스크립트란?</h3>
<p>자바스크립트에 타입을 부여한 언어</p>
<ul>
<li>자바스크립트와 달리 브라우저에서 실행하려면 컴파일 과정을 거쳐야함</li>
</ul>
<p>장점<del>(드디어 각종 에러에서 벗어날 수 있는 것인가)</del></p>
<ul>
<li><p>에러의 사전 방지</p>
</li>
<li><p>코드 자동 완성과 가이드</p>
<h3 id="fundamentals">Fundamentals</h3>
<h4 id="기본-타입">기본 타입</h4>
<p>String</p>
<pre><code>let str: string = &#39;hi&#39;;</code></pre><p>Number</p>
<pre><code>let num: number = 10;</code></pre><p>Boolean</p>
<pre><code>let isLoggedIn: boolean = false;</code></pre><p>Object
Array</p>
<pre><code>let arr1: number[] = [1,2,3];
let arr2: Array&lt;number&gt; = [1,2,3];</code></pre><p>Tuple: 배열의 길이가 고정되고 각 요소의 타입이 지정되어 있음</p>
<pre><code>let arr: [string, number] = [&#39;hi&#39;, 10];</code></pre><p>Enum: C, Java에서 쓰이는 타입으로 특정 값의 집합을 의미함</p>
<pre><code>enum Avengers { Capt, IronMan, Thor }
let hero: Avengers = Avengers.Capt;</code></pre><p>Any: 모든 타입을 허용<del>, 남발한다면 타입스크립트를 쓰는 이유가 없겠지</del></p>
<pre><code>let str: any = &#39;hi&#39;;
let num: any = 10;
let arr: any = [&#39;a&#39;, 2, true];</code></pre><p>Void: 변수에는 undefined, null만 할당하고, 함수에는 반환 값을 설정할 수 없는 타입</p>
<pre><code>let unuseful: void = undefined;
function notuse(): void {
console.log(&#39;sth&#39;);
}</code></pre><p>Null
Undefined
Never: 함수의 끝에 절대 도달하지 않는다는 의미를 지닌 타입</p>
<pre><code>// 이 함수는 절대 함수의 끝까지 실행되지 않는다는 의미
function neverEnd(): never {
while (true) {

}
}</code></pre><h4 id="함수">함수</h4>
<p>자바스크립트 함수 선언 방식에서 매개변수와 함수의 반환 값에 타입을 추가</p>
<pre><code>function sum(a: number, b: number): number {
return a + b;
}</code></pre><p>optional argument 설정</p>
<pre><code>function sum(a: number, b?: number): number {
return a + b;
}</code></pre><p>변수 디폴트 값 설정</p>
<pre><code>function sum(a: number, b = &#39;100&#39;): number {
return a + b;
}</code></pre><p>Rest 문법 적용</p>
<pre><code>function sum(a: number, ...nums: number[]): number {
const totalOfNums = 0;
for (let key in nums) {
  totalOfNums += nums[key];
}
return a + totalOfNums;
}</code></pre><h4 id="인터페이스">인터페이스</h4>
<p>상호 간에 정의한 규칙을 말함</p>
<pre><code>interface personAge {
age: number;
}
</code></pre></li>
</ul>
<p>function logAge(obj: personAge) {
  console.log(obj.age);
}
let person = { name: &#39;Capt&#39;, age: 28 };
logAge(person);</p>
<p>// &#39;logAge()의 인자는 personAge 라는 타입을 가져야한다&#39;는 것을 알 수 있음
// 인터페이스를 인자로 받아 사용할 때는 인터페이스에 정의된 속성, 타입의 조건만 만족한다면 객체의 속성 갯수가 더 많아도 상관 없으며, 인터페이스에 선언된 속성 순서를 지키지 않아도 됨</p>
<pre><code>옵션 속성</code></pre><p>interface 인터페이스_이름 {
  속성?: 타입;
}</p>
<pre><code>읽기 전용 속성: 인터페이스로 객체를 처음 생성할 때만 값을 할당하고 이후에는 변경 불가능한 속성</code></pre><p>interface CraftBeer {
  readonly brand: string;
}</p>
<pre><code>읽기 전용 배열</code></pre><p>let arr: ReadonlyArray<number> = [1,2,3];
arr.splice(0,1); // error
arr.push(4); // error
arr[0] = 100; // error</p>
<pre><code>인터페이스에서 정의하지 않은 속성들을 추가하고 싶을 때</code></pre><p>interface CraftBeer {
  brand?: string;
  [propName: string]: any;
}</p>
<pre><code>인터페이스에서 함수의 타입 정의하기</code></pre><p>interface login {
  (username: string, password: string): boolean;
}</p>
<p>let loginUser: login;
loginUser = function(id: string, pw: string) {
  console.log(&#39;로그인 했습니다&#39;);
  return true;
}</p>
<pre><code>인터페이스 확장</code></pre><p>interface Person {
  name: string;
}
interface Developer extends Person {
  skill: string;
}
let fe = {} as Developer;
fe.name = &#39;josh&#39;;
fe.skill = &#39;TypeScript&#39;;</p>
<pre><code>하이브리드 타입: 여러 가지 타입 조합</code></pre><p>interface CraftBeer {
  (beer: string): string;
  brand: string;
  brew(): void;
}</p>
<p>function myBeer(): CraftBeer {
  let my = (function(beer: string) {}) as CraftBeer;
  my.brand = &#39;Beer Kitchen&#39;;
  my.brew = function() {};
  return my;
}</p>
<p>let brewedBeer = myBeer();
brewedBeer(&#39;My First Beer&#39;);
brewedBeer.brand = &#39;Pangyo Craft&#39;;
brewedBeer.brew();</p>
<pre><code>#### Enums
숫자형 Enum</code></pre><p>enum Direction {
  Up = 1,
  Down, // 2
  Left, // 3
  Right // 4
}</p>
<p>enum Response {
  No = 0,
  Yes = 1,
}</p>
<p>function respond(recipient: string, message: Response): void {
  // ...
}</p>
<p>respond(&quot;Captain Pangyo&quot;, Response.Yes);</p>
<pre><code>
문자형 Enum</code></pre><p>enum Direction {
    Up = &quot;UP&quot;,
    Down = &quot;DOWN&quot;,
    Left = &quot;LEFT&quot;,
    Right = &quot;RIGHT&quot;,
}</p>
<pre><code>
숫자형 Enum과 문자형 Enum을 혼합한 복합 Enum이 있지만 사용을 권고 하지 않음

런타임 시점에서 Enum은 실제 객체 형태로 존재함</code></pre><p>enum E {
  X, Y, Z
}</p>
<p>function getX(obj: { X: number }) {
  return obj.X;
}
getX(E); // 이넘 E의 X는 숫자이기 때문에 정상 동작</p>
<pre><code>-&gt; 그렇지만 컴파일 시점에서는 keyof 대신 keyof type of를 사용할 것</code></pre><p>enum LogLevel {
  ERROR, WARN, INFO, DEBUG
}</p>
<p>// &#39;ERROR&#39; | &#39;WARN&#39; | &#39;INFO&#39; | &#39;DEBUG&#39;;
type LogLevelStrings = keyof typeof LogLevel;</p>
<p>function printImportant(key: LogLevelStrings, message: string) {
    const num = LogLevel[key];
    if (num &lt;= LogLevel.WARN) {
       console.log(&#39;Log level key is: &#39;, key);
       console.log(&#39;Log level value is: &#39;, num);
       console.log(&#39;Log level message is: &#39;, message);
    }
}
printImportant(&#39;ERROR&#39;, &#39;This is a message&#39;);</p>
<pre><code>
Reverse Mapping
- Enum에만 존재하는 특징임
- Enum의 key로 value를 얻을 수 있고 value로 key를 얻을 수도 있음</code></pre><p>enum Enum {
  A
}
let a = Enum.A; // 키로 값을 획득 하기
let keyName = Enum[a]; // 값으로 키를 획득 하기</p>
<pre><code>
#### Type
Union Type
- 자바스크립트의 OR 연산자와 비슷
- any를 사용하는 것보다 타입스크립트의 장점을 살리면서 코딩 가능</code></pre><p>// logText의 파라미터 text에는 string이나 number가 모두 올 수 있음
function logText(text: string | number) {
  // ...
}</p>
<pre><code>Intersection Type
- 여러 타입을 모두 만족하는 하나의 타입</code></pre><p>interface Person {
  name: string;
  age: number;
}
interface Developer {
  name: string;
  skill: number;
}</p>
<p>type Capt = Person &amp; Developer;</p>
<p>// 이것은 결국
// {
//  name: string;
//  age: number;
//  skill: string;
// }</p>
<pre><code>
#### Class
readonly</code></pre><p>class Developer {
    readonly name: string;
    constructor(readonly name: string) {
        this.name = theName;
    }
}
let john = new Developer(&quot;John&quot;);
john.name = &quot;John&quot;; // error! name is readonly.</p>
<pre><code>Accessor: 객체의 특정 속성의 접근과 할당에 대해 제어 가능(get, set 사용)</code></pre><p>class Developer {
  private name: string;</p>
<p>  get name(): string {
    return this.name;
  }</p>
<p>  set name(newValue: string) {
    if (newValue &amp;&amp; newValue.length &gt; 5) {
      throw new Error(&#39;이름이 너무 깁니다&#39;);
    }
    this.name = newValue;
  }
}</p>
<pre><code>Abstract Class: 특정 클래스의 상속 대상이 되면서 좀 더 상위 레벨에서 속성, 메서드의 모양을 정의함</code></pre><p>abstract class Developer {
  abstract coding(): void; // &#39;abstract&#39;가 붙으면 상속 받은 클래스에서 무조건 구현해야 함
  drink(): void {
    console.log(&#39;drink sth&#39;);
  }
}</p>
<p>class FrontEndDeveloper extends Developer {
  coding(): void {
    // Developer 클래스를 상속 받은 클래스에서 무조건 정의해야 하는 메서드
    console.log(&#39;develop web&#39;);
  }
  design(): void {
    console.log(&#39;design web&#39;);
  }
}
const dev = new Developer(); // error: cannot create an instance of an abstract class
const josh = new FrontEndDeveloper();
josh.coding(); // develop web
josh.drink(); // drink sth
josh.design(); // design web</p>
<pre><code>#### Generics
타입을 함수의 파라미터처럼 사용하는 것, 즉 함수를 호출할 때 함수 안에서 사용할 타입을 넘겨줄 수 있음</code></pre><p>function getText<T>(text: T): T {
  return text;
}</p>
<pre><code>아래 코드는 T라는 변수 타입을 받고, 인자 값으로는 배열 형태의 T를 받는다. 
예를 들어 [1,2,3]을  배열을 받고 number를 돌려줌</code></pre><p>function logText<T>(text: T[]): T[] {
  console.log(text.length); // 제네릭 타입이 배열이기 때문에 <code>length</code>를 허용합니다.
  return text;
}</p>
<pre><code>첫 번째 코드를 제네릭 인터페이스로 쓰면?</code></pre><p>interface GenericLogTextFn {
  <T>(text: T): T;
}
function logText<T>(text: T): T {
  return text;
}
let myString: GenericLogTextFn = logText; // Okay</p>
<pre><code>Generics class</code></pre><p>class GenericMath<T> {
  pi: T;
  sum: (x: T, y: T) =&gt; T;
}</p>
<p>let math = new GenericMath<number>();</p>
<pre><code>제네릭 제약 조건을 사용하여 두 객체 비교하기</code></pre><p>// 첫번째 인자로 받는 개체에 없는 속성은 접근할 수 없게 제한함
function getProperty&lt;T, O extends keyof T&gt;(obj: T, key: O) {
  return obj[key];<br>}
let obj = { a: 1, b: 2, c: 3 };</p>
<p>getProperty(obj, &quot;a&quot;); // okay
getProperty(obj, &quot;z&quot;); // error: &quot;z&quot;는 &quot;a&quot;, &quot;b&quot;, &quot;c&quot; 속성에 해당하지 않습니다.</p>
<pre><code>#### 타입 추론
타입스크립트가 코드를 해석해 나가는 동작을 의미함
보통 변수를 선언하거나 초기화 할 때 그리고 변수, 속성, 함수의 반환 값 등을 설정할 때 타입이 추론됨
타입 추론 방식
- Best Common Type: 코드를 바탕으로 추론한 가장 근접한 타입
- 문맥 상으로 결정
타입 체킹
- Duck Typing: 동적 타이핑의 한 종류로 객체의 변수 및 메서드의 집합이 객체의 타입을 결정하는 것을 의미함
- Structural Subtyping: 객체의 실제 구조나 정의에 따라 타입을 결정하는 것을 말함
#### 타입 호환
타입스크립트 코드에서 특정 타입이 다른 타입에 잘 맞는지를 의미함

구조적 타이핑: 코드 구조 관점에서 타입이 서로 호환되는지의 여부를 판단하는 것</code></pre><p>interface Avengers {
  name: string;
}</p>
<p>let hero: Avengers;
// 타입스크립트가 추론한 y의 타입은 { name: string; location: string; } 입니다.
let capt = { name: &quot;Captain&quot;, location: &quot;Pangyo&quot; };
hero = capt;
// capt의 속성 중에 name이 있기 때문에 capt이 hero 타입에 호환될 수 있음</p>
<pre><code>Soundness: 타입스크립트는 컴파일 시점에 타입을 추론할 수 없는 특정 타입은 일단 안전하다고 봄
#### 타입 별칭(Type Aliases)
특정 타입이나 인터페이스를 참조할 수 있는 타입 변수
새로운 타입 값을 생성하는 것이 아니라 정의한 타입에 대해 나중에 쉽게 참고할 수 있게 이름만 붙이는 것</code></pre><p>// string 타입을 사용할 때
const name: string = &#39;capt&#39;;</p>
<p>// 타입 별칭을 사용할 때
type MyName = string;
const name: MyName = &#39;capt&#39;;</p>
<pre><code>type vs. interface
인터페이스는 확장 가능, 타입은 확장 불가능
-&gt; 좋은 소프트웨어는 언제나 확장이 용이해야 한다는 원칙에 따라 가능한 type 보다는 interface로 선언해서 사용하는 것이 좋다

### Usage
모듈: ES6+의 Modules의 개념과 유사하며 export, import와 같은 키워드를 사용한다
선언 파일
- d.ts 파일은 타입스크립트 코드의 타입 추론을 돕는 파일
- 타입스크립트 파일에서 사용할 수는 있지만 선언되어 있지 않은 전역변수나 전역 함수를 아래와 같이 선언함</code></pre><p>// 전역 변수
declare const pi = 3.14;</p>
<p>// 전역 함수
declare namespace myLib {
  function greet(person: string): string;
  let name: string;
}</p>
<p>myLib.greet(&#39;캡틴&#39;);
myLib.name = &#39;타노스&#39;;</p>
<pre><code>인덱싱</code></pre><p>// 타입스크립트에서 배열 요소와 객체의 속성에 접근 할 때는 인터페이스를 이용하자
interface StringArray {
  [index: number]: string;
}</p>
<p>const arr: StringArray = [&#39;Thor&#39;, &#39;Hulk&#39;];
arr[0]; // &#39;Thor&#39;</p>
<pre><code>Utility type
- 이미 정의해 놓은 타입을 변환할 때 사용하기 좋은 타입 문법
- partial: 특정 타입의 부분 집합을 만족하는 타입을 정의</code></pre><p>interface Address {
  email: string;
  address: string;
}</p>
<p>type MayHaveEmail = Partial<Address>;
const me: MayHaveEmail = {}; // 가능
const you: MayHaveEmail = { email: &#39;test@abc.com&#39; }; // 가능
const all: MayHaveEmail = { email: &#39;capt@hero.com&#39;, address: &#39;Pangyo&#39; }; // 가능</p>
<pre><code>- pick: 특정 타입에서 몇 개의 속성을 선택하여 타입을 정의</code></pre><p>interface Hero {
  name: string;
  skill: string;
}
const human: Pick&lt;Hero, &#39;name&#39;&gt; = {
  name: &#39;스킬이 없는 사람&#39;,
};</p>
<pre><code>- omit: 특정 타입에서 지정된 속성만 제거한 타입을 정의</code></pre><p>interface AddressBook {
  name: string;
  phone: number;
  address: string;
  company: string;
}
const phoneBook: Omit&lt;AddressBook, &#39;address&#39;&gt; = {
  name: &#39;재택근무&#39;,
  phone: 12342223333,
  company: &#39;내 방&#39;
}
const chingtao: Omit&lt;AddressBook, &#39;address&#39;|&#39;company&#39;&gt; = {
  name: &#39;중국집&#39;,
  phone: 44455557777
}</p>
<pre><code>Mapped type
기존에 정의되어 있는 타입을 새로운 타입으로 변환해주는 문법</code></pre><p>// 기본 문법
{ [ P in K ] : T }
{ [ P in K ] ? : T }
{ readonly [ P in K ] : T }
{ readonly [ P in K ] ? : T }</p>
<p>// 기본 예제
type Heroes = &#39;Hulk&#39; | &#39;Thor&#39; | &#39;Capt&#39;;
type HeroProfiles = { [K in Heroes]: number };
const heroInfo: HeroProfiles = {
  Hulk: 54,
  Thor: 1000,
  Capt: 33,
}</p>
<p>// 실용 예제
// 사용자 프로필 조회 API
interface UserProfile {
  username: string;
  email: string;
  profilePhotoUrl: string;
}</p>
<p>function fetchUserProfile(): UserProfile {
  // ...
}</p>
<p>// 프로필 정보 수정 API
interface UserProfileUpdate {
  username?: string;
  email?: string;
  profilePhotoUrl?: string;
}</p>
<p>function updateUserProfile(params: UserProfileUpdate) {
  // ...
}</p>
<p>// 이때 동일한 타입에 대해 반복 선언하는 것은 좋지 않음
type UserProfileUpdate = {
  username?: UserProfile[&#39;username&#39;];
  email?: UserProfile[&#39;email&#39;];
  profilePhotoUrl?: UserProfile[&#39;profilePhotoUrl&#39;];
}</p>
<p>// 이것에 keyof를 적용하면?
type UserProfileUpdate = {
  [p in keyof UserProfile]?: UserProfile[p]
}</p>
<p>```</p>
<h3 id="config">Config</h3>
<h4 id="tsconfig">tsconfig</h4>
<p>tsconfig.json 파일은 타입스크립트를 자바스크립트로 변환할 때의 설정을 정의해놓는 파일
&#39;tsc app.ts&#39;라고 치면 app.ts파일이 app.js파일로 컴파일 됨</p>
<p>@types 라이브러리:일반적으로 index.d.ts 파일과 package.json 파일로 구성되어 있음</p>
<h3 id="참고자료">참고자료</h3>
<p><a href="https://joshua1988.github.io/ts/intro.html">TypeScript Handbook</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React JS_goormedu]]></title>
            <link>https://velog.io/@jay_jykim91/React-JSgoormedu</link>
            <guid>https://velog.io/@jay_jykim91/React-JSgoormedu</guid>
            <pubDate>Wed, 01 Jun 2022 07:21:58 GMT</pubDate>
            <description><![CDATA[<h4 id="react-소개">React 소개</h4>
<p>A JavaScript library for building user interfaces: 화면을 만들기 위한 기능들을 모아놓은 것
장점</p>
<ul>
<li>빠른 업데이트와 렌더링 속도: Virtual DOM을 사용하여 Browser DOM을 직접 수정하는 것이 아니라 업데이트할 최소한의 부분만을 찾아서 업데이트 한다</li>
<li>Component-Based: 레고 블록을 조립하듯 컴포넌트들을 모아서 개발할 수 있다 -&gt; Reusability -&gt; 개발 속도가 빨라진다</li>
<li>페이스북에서 만들었기 때문에 하루아침에 사라질 확률이 낮다</li>
<li>활발한 지식 공유 &amp; 커뮤니티<h4 id="jsx-소개">JSX 소개</h4>
A syntax extension to JavaScript: JavaScript + XML/HTML<pre><code>const element = &lt;h1&gt;Hello, world!&lt;/h1&gt;</code></pre>React에서 JSX를 쓰는 것이 필수가 아님<pre><code>// JSX를 사용한 경우
class Hello extends React.Component {
render() {
  return &lt;div&gt;Hello {this.props.toWhat}&lt;/div&gt;;
}
}
</code></pre></li>
</ul>
<p>ReactDOM.render(
  <Hello toWhat="World" />
  document.getElementById(&#39;root&#39;)
);</p>
<p>// JSX를 사용하지 않고 JS를 사용한 경우
class Hello extends React.Component {
  render() {
    return React.createElement(&#39;div&#39;, null, <code>Hello ${this.props.toWhat}</code>);
  }
}</p>
<p>ReactDOM.render(
  React.createElement(Hello, {toWhat: &#39;World&#39;}, null),
  document.getElementById(&#39;root&#39;)
);</p>
<pre><code>JSX는 객체를 나타냄</code></pre><p>const element = React.createElement(
  &#39;h1&#39;,
  {className: &#39;greeting&#39;},
  &#39;Hello, world!&#39;
);</p>
<p>// 위 코드의 결과로 아래와 같은 객체(React elements)가 만들어짐
const element = {
  type: &#39;h1&#39;,
  props: {
    className: &#39;greeting&#39;,
    children: &#39;Hello, world!&#39;
  }
};</p>
<pre><code>JSX의 장점
- 간결한 코드
- 가독성 향상 -&gt; 버그를 발견하기 쉬움
- Injection Attack 방어
#### Rendering Elements
Element
- Elements are the smallest building blocks of React Apps.
- React elements are immutable: 생성된 후에는 children이나 attributes를 바꿀 수 없다</code></pre><p>// Root DOM node</p>
<div id="root"></div>

<p>const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById(&#39;root&#39;));</p>
<pre><code>리액트는 바뀐 부분만 계산을 해서 해당 부분만 새롭게 랜더링함
#### Components and Props
Components
- 리액트는 component-based library
- react component는 props라는 입력값을 받아서 React element라는 출력값을 낸다
Props
- property를 줄여서 말함
- read-only(값을 변경할 수 없음): All React components must act like pure functions with respect to their props.</code></pre><p>// PURE - input을 변경하지 않으며, 같은 input에 대해서 항상 같은 output을 리턴
function sum(a, b) {
  return a+b;
}</p>
<p>// IMPURE - input을 변경함
function withdraw(account, amount) {
  account.total -= amount;
}</p>
<pre><code>Component
- 항상 대문자로 시작해야 함, 소문자로 시작하면 리액트에서는 DOM tag로 인식함
- 최대한 작게 만들어서 재사용성을 높이자
- component 합성: component안에 또 다른 component를 쓸 수 있음
- Function component</code></pre><p>function Welcome(props) {
  return <h1> Hello, {props.name}</h1>
}</p>
<pre><code>- Class component</code></pre><p>class Welcome extends React.Component {
  render() {
    return <h1> Hello, {props.name}</h1>
  }
}</p>
<pre><code>#### State and Lifecycle
State
- React component에 대한 변경 가능한 데이터
- 사용자가 정의함
- JavaScript의 객체임
- 직접 수정하면 안됨, setState 함수를 통해서만 수정하자</code></pre><p>class LikeButton extends React.Component {
  constructor(props) {
    super(props);</p>
<pre><code>this.state = {
  liked: false
};</code></pre><p>  }</p>
<p>  render() {
    if (this.state.liked) {
      return &#39;You liked this.&#39;;
    }</p>
<pre><code>return e(
  &#39;button&#39;,
  { onClick: () =&gt; this.setState({ liked: true }) },
  &#39;Like&#39;
);</code></pre><p>  }
}</p>
<pre><code>Lifecycle
![React component lifecycle](https://velog.velcdn.com/images/jay_jykim91/post/e3fc63eb-33ca-4bc2-b5b7-aedd21321d48/image.png)
Copyright@Soaple
#### Handling Events</code></pre><button onClick={activeLasers}>
  Activate Lasers
</button>
```
Event Handler: 이벤트를 처리하는 함수, Event Listener라고도 함
```
class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

<pre><code>// This binding is necessary to make &#39;this&#39; work in the callback
this.handleClick = this.handleClick.bind(this);</code></pre><p>  }</p>
<p>  handleClick() {
    this.setState(state =&gt; ({
      isToggleOn: !state.isToggleOn
    }));
  }</p>
<p>  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? &#39;ON&#39; : &#39;OFF&#39;}
      </button>
    )
  }
}</p>
<p>// 또는
class LoggingButton extends React.Component {
  // This syntax ensures &#39;this&#39; is bound within handleCllick.
  // Warning: this is <em>experimental</em> syntax.
  handleClick = () =&gt; {
    console.log(&#39;this is: &#39;, this);
  }</p>
<p>  render() {
    return (
      <button onClick={this.handleClick}>
        Click me
      </button>
    );
  }
}</p>
<pre><code>#### Conditional Rendering</code></pre><p>function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}</p>
<p>ReactDOM.render (
  <Greeting isLoggedIn={false} />, document.getElementById(&#39;root&#39;)
);</p>
<pre><code>Inline condition</code></pre><p>function MailBox(props) {
  const unreadMessages = props.unreadMessage;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length &gt; 0 &amp;&amp;
        <h2>
          You have {unreadMessages.length} unread messages.
        </h2>
      }
    </div>
  );
}</p>
<pre><code>If else condition</code></pre><p>render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      The user is <b>{isLoggedIn ? &#39;currently&#39; : &#39;not&#39;}</b> logged in.
    </div>
  );
}</p>
<pre><code>null을 리턴하면 렌더링 되지 않음</code></pre><p>function WarningBanner(props) {
  if(!props.warn) {
    return null;
  }</p>
<p>  return (
    <div className="warning">
      Warning!
    </div>
  );
}</p>
<pre><code>#### Lists and Keys
List
- JavaScript의 변수나 객체들을 하나의 변수로 묶어놓은 것</code></pre><p>function NumberList(props) {
  const numbers = props.numbers;
  const listItems = number.map((number) =&gt;
    <li>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}</p>
<p>const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />, documeng.getElementById(&#39;root&#39;)
);</p>
<pre><code>Keys
- 아이템들을 구분하기 위한 고유한 문자열
- key의 값은 해당 element사이에서만 고유한 값이면 된다
key로 값을 사용하는 경우</code></pre><p>const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =&gt;
  <li key={number.toString()}>
    {number}
  </li>
);</p>
<pre><code>key로 객체의 ID를 사용하는 경우</code></pre><p>const todoItems = todos.map((todo) =&gt;
  <li key={todo.id}>
    {todo.text}
  </li>
);</p>
<pre><code>key로 index를 사용하는 경우 -&gt; index는 고유한 key값은 아님</code></pre><p>const todoItems = todos.map((todo, index) =&gt;
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);</p>
<pre><code>key는 props로 전달되지 않음</code></pre><p>const content = posts.map((post) =&gt;
  &lt;Post
    // 아래에 있는 key는 Post에서 props.key 찍어봐도 안나옴
    key={post.id}
    // 그래서 id를 전달한다
    id={post.id} /&gt;
);</p>
<pre><code>#### Forms
Controlled Components는 값이 react의 통제를 받는 Input form element를 의미함</code></pre><p>handleChange(event) {
  this.setState({value: event.target.value});
}</p>
<p>handleSubmit(event) {
  alert(&#39;A name was submitted: &#39; + this.state.value);
  event.preventDefault();
}</p>
<p>render() {
  return (
    <form onSubmit={this.handleSubmit}>
      <label>
        Name:
        <input type='text' value={this.state.value} onChange={this.handleChange} />
      </label>
      <input type="submit" value="Submit" />
    </form>
  );
}</p>
<pre><code>File input tag는 값을 읽을 수만 있고 통제할 수 없기 때문에 Uncontrolled Components
#### Lifting State Up
Shared State
- state에 있는 데이터를 여러 개의 하위 컴포넌트에서 공통적으로 사용하는 경우
- 하위 컴포넌트들이 각자 state에 데이터를 가지고 있을 필요가 없음
Lifting State Up
- sharing state is accomplished by moving it up to the closest common ancestor of the components that need it
- 하위 컴포넌트의 state를 공통 상위 컴포넌트로 올림
#### Composition vs. Inheritance
Composition
- 여러개의 컴포넌트를 합쳐서 새로운 컴포넌트를 만드는 것
- Containment: children이라는 prop을 사용해서 조합</code></pre><p>function WelcomdDialog() {
  return (
    <FancyBorder color='blue'>
      // 여기서부터
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    // 여기까지 FancyBorder 컴포넌트의 children으로 전달이 됨
    </FancyBorder>
  );
}</p>
<pre><code>- Specialization: &#39;WelcomeDialog&#39;는 &#39;Dialog&#39;의 특별한 케이스</code></pre><Dialog
  title="Welcome"
  message="Thank you for visiting our spacecraft!"
</>
```
Inheritance
- 다른 컴포넌트로부터 상속을 받아서 새로운 컴포넌트를 만드는 것
- At Facebook, we use React in thousands of components, and we haven't found any use cases where we would recommend creating component inheritance hierarchies. -> inheritance는 react에서 사용할 필요가 없다
#### 참고자료
[처음 만난 리액트](https://edu.goorm.io/lecture/12976/%EC%B2%98%EC%9D%8C-%EB%A7%8C%EB%82%9C-react-%EB%A6%AC%EC%95%A1%ED%8A%B8) by goormedu]]></description>
        </item>
        <item>
            <title><![CDATA[React JS_코딩앙마]]></title>
            <link>https://velog.io/@jay_jykim91/React-JS%EC%BD%94%EB%94%A9%EC%95%99%EB%A7%88</link>
            <guid>https://velog.io/@jay_jykim91/React-JS%EC%BD%94%EB%94%A9%EC%95%99%EB%A7%88</guid>
            <pubDate>Sat, 28 May 2022 00:40:52 GMT</pubDate>
            <description><![CDATA[<h4 id="설치">설치</h4>
<pre><code>npx create-react-app 프로젝트 이름</code></pre><p>node_modules 폴더</p>
<ul>
<li>이 프로젝트를 실행할 때 필요한 dependency 모듈들이 모여 있음</li>
<li>package.json 파일의 &#39;dependencies&#39;에 기록되어 있음
package.json 파일 중 &#39;scripts&#39;</li>
<li>start: 개발 모드로 프로그램을 실행</li>
<li>build: 실제 배포 모드로 만들어 줌</li>
<li>test</li>
<li>eject: 내부 설정 파일을 꺼내는 역할, 웹페이지나 바벨 설정을 변경하고 싶을 떄 사용<h4 id="컴포넌트-jsx">컴포넌트, JSX</h4>
<pre><code>function App() {
const name = &quot;Tom&quot;;
const naver = {
  name: &quot;네이버&quot;,
  url: &quot;https://naver.com&quot;,
};
return (
  &lt;div className=&quot;App&quot;&gt;
    &lt;header className=&quot;App-header&quot;&gt;
      &lt;img src={logo} className=&quot;App-logo&quot; alt=&quot;logo&quot; /&gt;
      &lt;p&gt;Coding angma&lt;/p&gt;
      &lt;a
        className=&quot;App-link&quot;
        href=&quot;https://reactjs.org&quot;
        target=&quot;_blank&quot;
        rel=&quot;noopener noreferrer&quot;
      &gt;
        Learn React~~~~!!
      &lt;/a&gt;
    &lt;/header&gt;
    &lt;h1
      style={{
        color: &quot;#f0f&quot;,
        backgroundColor: &quot;green&quot;,
      }}
    &gt;
      Hello, {name}.&lt;p&gt;{2 + 3}&lt;/p&gt;
    &lt;/h1&gt;
    &lt;a href={naver.url}&gt;{naver.name}&lt;/a&gt;
  &lt;/div&gt;
);
}</code></pre><h4 id="css-작성법module-css">CSS 작성법(module css)</h4>
</li>
</ul>
<ol>
<li>inline style 사용<pre><code>&lt;h1
 style={{
 color: &quot;#f00&quot;,
 borderRight: &quot;12px solid #000&quot;,
 marginBottom: &quot;50px&quot;,
 opacity: 1,
 }}
&gt;
 Hello
&lt;/h1&gt;</code></pre></li>
<li>index.css, app.css 파일 사용
이때 단점은 css 파일들이 각 컴포넌트에 종속되는 것이 아니라 html의 header 부분에 들어가서 모든 페이지에 영향을 미치게 됨</li>
<li>css module 활용
보통 &#39;컴포넌트이름.module.css&#39;로 파일 생성
동일한 클래스 이름을 사용하더라도 각 컴포넌트 별로 다른 클래스 이름이 생성됨
글로벌 단위가 아닌 컴포넌트 단위로 관리할 수 있어서 편리함
<del>나는 요렇게만 해봤다...</del><pre><code>// jsx파일에는
import styles from &quot;./Hello.module.css&quot;;
</code></pre></li>
</ol>
<p>function Hello() {
  return (
    <div>
      <div className={styles.box}>Hello</div>
    </div>
  );
}</p>
<p>// module.css파일에는
.box {
  width: 200px;
  height: 50px;
  background-color: blue;
}</p>
<pre><code>
#### 이벤트 처리(Handling Events)</code></pre><p>export default function Hello() {
  function showName() {
    console.log(&quot;Mike&quot;);
  }
  function showAge(age) {
    console.log(age);
  }
  function showText(txt) {
    console.log(txt);
  }</p>
<p>  return (
    <div>
      &lt;h1
        style={{
          color: &quot;#f00&quot;,
          borderRight: &quot;12px solid #000&quot;,
          marginBottom: &quot;50px&quot;,
          opacity: 1,
      <h1>Hello</h1>
      <button onClick={showName}>Show name</button>
      &lt;button
        onClick={() =&gt; {
          showAge(10);
        }}
      &gt;
        Hello
      </h1>
      <div className={styles.box}>Hello</div>
        Show age
      </button>
      &lt;input
        type=&quot;text&quot;
        onChange={e =&gt; {
          const txt = e.target.value;
          showText(txt);
        }}
      /&gt;
    </div>
  );
}</p>
<pre><code>#### State, useState
state: 컴포넌트가 가지고 있는 속성값</code></pre><p>export default function Hello() {
  // let name = &quot;Mike&quot;;
  const [name, setName] = useState(&quot;Mike&quot;);</p>
<p>  return (
    <div>
      <h2 id="name">{name}</h2>
      &lt;button
        onClick={() =&gt; {
          setName(name === &quot;Mike&quot; ? &quot;Jane&quot; : &quot;Mike&quot;);
        }}
      &gt;
        Change
      </button>
    </div>
  );
}</p>
<pre><code>#### Props
props로 전달받은 값을 props.age = 100 과 같이 직접적으로 변경 불가능 -&gt; 변경 원한다면 useState 사용해야 함</code></pre><p>// App.js
function App() {
  return (
    <div className="App">
      <h3>props : properties</h3>
      <Hello age={10} />
      <Hello age={20} />
      <Hello age={30} />
    </div>
  );
}</p>
<p>// Hello.js
import { useState } from &quot;react&quot;;
import UserName from &quot;./UserName&quot;;</p>
<p>export default function Hello({ age }) {
  const [name, setName] = useState(&quot;Mike&quot;);
  const msg = age &gt; 19 ? &quot;성인 입니다.&quot; : &quot;미성년자 입니다.&quot;;</p>
<p>  return (
    <div>
      <h2 id="name">
        {name}({age}) : {msg}
      </h2>
      <UserName name={name} />
      &lt;button
        onClick={() =&gt; {
          setName(name === &quot;Mike&quot; ? &quot;Jane&quot; : &quot;Mike&quot;);
        }}
      &gt;
        Change
      </button>
    </div>
  );
}</p>
<p>// userName.js
export default function UserName({ name }) {
  return <p>Hello, {name}</p>;
}</p>
<pre><code>#### 라우터 구현 react-router-dom</code></pre><p>npm install react-router-dom</p>
<pre><code>강의는 v5로 만들어졌는데 현재는 v6가 나와있으니 아래 docs 참고
https://reactrouter.com/docs/en/v6
#### json-server, REST API
json-server: 빠르고 쉽게 rest api를 구축해 줌</code></pre><p>npm install -g json-server</p>
<p>json-server --watch 더미데이터 있는 곳 --port 지금 사용하고 있지 않은 포트
json-server --watch ./src/db/data.js --port 3001</p>
<pre><code>REST API
- uri 주소와 method로 CRUD(Create: POST, Read: GET, Update: PUT, Delete: DELETE) 요청을 하는 것
#### useEffect, fetch()로 API 호출
useEffect
- 상태 값이 변경되어 다시 랜더링 됐을 때 호출 됨
- 어떤 상태 값이 바뀌었을 때 동작하는 함수를 만들 수 있음
- 첫 번째 매개변수로 함수를 받음
- 두 번째 매개변수로는 의존성 배열
    - 배열 안에 어떤 것이 변경되었을 때 호출될 지 작성
    - 랜더링 된 후 최초 1번만 호출하고 싶으면 빈 배열 사용</code></pre><p>// DayList.js
useEffect(() =&gt; {
  fetch(&quot;<a href="http://localhost:3001/days&quot;">http://localhost:3001/days&quot;</a>)
    .then(res =&gt; {
      return res.json();
    })
    .then(data =&gt; {
      setDays(data);
    });
}, []);</p>
<p>// Day.js
useEffect(() =&gt; {
    fetch(<code>http://localhost:3001/words?day=${day}</code>)
      .then(res =&gt; {
        return res.json();
      })
      .then(data =&gt; {
        setWords(data);
      });
  }, [day]);</p>
<pre><code>#### Custom Hooks
hooks 폴더 만들어서 나만의 hooks를 정리해보면</code></pre><p>// useFetch.js
import { useEffect, useState } from &quot;react&quot;;</p>
<p>export default function useFetch(url) {
  const [data, setData] = useState([]);</p>
<p>  useEffect(() =&gt; {
    fetch(url)
      .then(res =&gt; {
        return res.json();
      })
      .then(data =&gt; {
        setData(data);
      });
  }, [url]);</p>
<p>  return data;
}</p>
<p>// Day.js
const words = useFetch(<code>http://localhost:3001/words?day=${day}</code>);</p>
<p>// DayList.js
const days = useFetch(&quot;<a href="http://localhost:3001/days&quot;">http://localhost:3001/days&quot;</a>);</p>
<pre><code>#### PUT(수정), DELETE(삭제)</code></pre><p>// Word.js
function toggleDone() {
  // isDone 수정
  fetch(<code>http://localhost:3001/words/${word.id}</code>, {
    method: &quot;PUT&quot;,
    headers: {
      &quot;Content-Type&quot;: &quot;application/json&quot;,
    },
    body: JSON.stringify({
      ...word,
      isDone: !isDone,
    }),
  }).then(res =&gt; {
    if (res.ok) {
      setIsDone(!isDone);
    }
  });
}</p>
<p>function del() {
  if (window.confirm(&quot;삭제 하시겠습니까?&quot;)) {
    fetch(<code>http://localhost:3001/words/${word.id}</code>, {
      method: &quot;DELETE&quot;,
    }).then(res =&gt; {
      if (res.ok) {
        setWord({ id: 0 });
      }
    });
  }
}</p>
<p>// 단어의 id가 0이면 보이지 않게
if (word.id === 0) {
  return null;
}</p>
<pre><code>#### POST(생성), useHistory()
Chrome 개발자 도구에서 Network를 &#39;Online&#39;에서 &#39;Slow 3G&#39;로 바꿔서 느린 환경을 가정하여 테스트 해볼 수 있음</code></pre><p>// Day.js
{words.length === 0 &amp;&amp; <span>Loading...</span>}</p>
<p>// CreateWord.js
if (!isLoading) {
  setIsLoading(true);
  fetch(<code>http://localhost:3001/words/</code>, {
    method: &quot;POST&quot;,
      headers: {
        &quot;Content-Type&quot;: &quot;application/json&quot;,
      },
    body: JSON.stringify({
      day: dayRef.current.value,
      eng: engRef.current.value,
      kor: korRef.current.value,
      isDone: false,
    }),
  }).then(res =&gt; {
    if (res.ok) {
      alert(&quot;생성이 완료 되었습니다&quot;);
      history.push(<code>/day/${dayRef.current.value}</code>);
      setIsLoading(false);
    }
  });</p>
<p>&lt;button
      style={{
        opacity: isLoading ? 0.3 : 1,
      }}</p>
<blockquote>
</blockquote>
<p>  {isLoading ? &quot;Saving...&quot; : &quot;저장&quot;}
</button></p>
<pre><code>#### 타입스크립트 적용
create-react-app으로 만든 프로젝트에 typescript를 추가하려면</code></pre><p>npm install typescript @types/node @types/react @types/react-dom @types/jest @types/react-router-dom</p>
<pre><code>.js 파일은 .ts로, .jsx 파일은 .tsx 파일로 변경</code></pre><p>// Word.tsx
interface IProps {
  word: IWord;
}</p>
<p>export interface IWord {
  day: string;
  eng: string;
  kor: string;
  isDone: boolean;
  id: number;
}</p>
<p>export default function Word({ word: w }: IProps) {}</p>
<p>```</p>
<h4 id="참고자료">참고자료</h4>
<p><a href="https://www.youtube.com/playlist?list=PLZKTXPmaJk8J_fHAzPLH8CJ_HO_M33e7-">Reactjs 강좌</a> by 코딩앙마</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript DOM & EVENT]]></title>
            <link>https://velog.io/@jay_jykim91/JavaScript-DOM-EVENT</link>
            <guid>https://velog.io/@jay_jykim91/JavaScript-DOM-EVENT</guid>
            <pubDate>Fri, 20 May 2022 12:01:26 GMT</pubDate>
            <description><![CDATA[<h4 id="노드에-접근하기">노드에 접근하기</h4>
<p>DOM(Document Object Model): HTML 문서의 각 요소들을 트리 형식으로 표현해 줌</p>
<pre><code>const pList = document.getElementsByTagName(&#39;p&#39;);
for(p of pList) {
  p.style.fontSize = &#39;20px&#39;
}
// 이때 pList는 배열은 아니고 iterable
// 그래서 for ... of ... 사용
document.querySelectorAll(&#39;.link&#39;);
document.querySelector(&#39;#first&#39;);
document.querySelector(&#39;h3:nth-of-type(2)&#39;).style.color = &#39;red&#39;;</code></pre><h4 id="부모-자식-형제-노드">부모, 자식, 형제 노드</h4>
<pre><code>document.querySelectorAll(&#39;p&#39;);
// 반환값이 NodeList

document.getElementsByTagName(&#39;p&#39;);
// 반환값이 HTMLCollection

// NodeList, HTMLCollection 둘다 유사배열 객체 이면서 iterable 임
// for ... of 로 순회함
// 이때 실시간으로 p태그를 하나 추가 해보면
// NodeList에는 반영이 안되지만 HTMLCollection에는 반영이 됨

const red = document.getElementById(&#39;red&#39;);
red.parentNode;
// 부모 노드를 반환함
red.parentElement;
// 부모 노드 중 요소 노드만 반환
// 요소 노드는 html 태그로 이루어진 요소

const ul = document.getElementById(&#39;color&#39;);
ul.childNodes;
// NodeList - li 말고도 주석을 포함한 모든 텍스트(줄바꿈 포함)를 반환
ul.children;
// HTMLCollection - li만 반환
ul.firstChild;
ul.lastChild;
// 위에 두개 보다는 아래 두개를 더 많이 사용함
ul.firstElementChild;
ul.lastElementChild;

const blue = document.getElementById(&#39;blue&#39;);
blue.previousSibling;
blue.nextSibling;
// 위가 아니라 아래를 사용한다
blue.previousElementSibling;
blue.nextElementSibling;</code></pre><p>보통 요소 노드만 뽑아서 사용한다
<img src="https://velog.velcdn.com/images/jay_jykim91/post/a81e573c-a830-4666-8ee7-cc97d36cd8d3/image.png" alt="부모, 자식, 형제 노드"></p>
<h4 id="노드-생성-추가-복제-삭제">노드 생성, 추가, 복제, 삭제</h4>
<pre><code>const blue = document.getElementById(&#39;blue&#39;);
const blueTextNoe = blue.firstChild;
blueTextNode.nodeName; // &#39;#text&#39;
blueTextNode.nodeType; // 3
blueTextNode.nodeValue; // &#39;Blue&#39;
// 텍스트 밸류를 가지고 있을 때만 nodeValue를 이용하여 수정 가능
blueTextNode.nodeValue = &#39;파랑&#39;;
// 또는 innerHTML로 수정

const newLi = document.createElement(&#39;li&#39;);
newLi.innerHTML = &#39;green&#39;;
const ul = document.getElementById(&#39;color&#39;);
ul.appendChild(newLi);

const newLi2 = document.createElement(&#39;li&#39;);
const newText = document.createTextNode(&#39;pink&#39;);
newLi2.appendChild(newText);
ul.appendChild(newLi2);

const newLi3 = document.createElement(&#39;li&#39;);
const newText3 = document.createTextNode(&#39;orange&#39;);
ul.inserBefore(newLi3, red);

// 기존 노드를 사용하면 노드가 이동함
ul.appendChild(red); // red가 맨 아래로 이동

// cloneNode
const newOrange = newLi3.cloneNode(); // li만 복사 됨
const newOrange2 = newLi2.cloneNode(true); // 안에 있는 요소(텍스트 등)까지 복사

// removeChild
ul.removeChild(red);
ul.removeChild(ul.firstElementChild);</code></pre><h4 id="css-style-class-제어">CSS style, class 제어</h4>
<pre><code>const box = document.getElementById(&#39;box&#39;);
box.style.backgroundColor = &#39;red&#39;;

box.className = &#39;bg-red&#39;;
box.className = &#39;bg-red txt-pink&#39;;

box.classList.add = &#39;txt-white&#39;;
box.classList.remove = &#39;txt-white&#39;);
box.classList.replace(&#39;bg-red&#39;, &#39;bg-blue&#39;);
box.classList.toggle(&#39;bg-blue&#39;);</code></pre><h4 id="이벤트-핸들러event-handler">이벤트 핸들러(Event Handler)</h4>
<pre><code>// 1
&lt;button onclick=&quot;alert(&#39;click&#39;)&quot;&gt; 클릭1 &lt;/button&gt;

// 2
&lt;button onclick=&#39;sayHello()&#39;&gt; 클릭2 &lt;/button&gt;
&lt;script&gt;
  function sayHello() {
    alert(&#39;hello&#39;);
  }
&lt;/script&gt;

// 3
&lt;button id=&#39;btn&#39;&gt; 클릭3 &lt;/button&gt;
&lt;script&gt;
  const btn = document.getElementById(&#39;btn&#39;);
  btn.onclick = sayHello;
&lt;/script&gt;

// 4
&lt;button id=&#39;btn2&#39;&gt; 클릭4 &lt;/button&gt;
&lt;script&gt;
  const btn = document.getElementById(&#39;btn2&#39;);
  btn.addEventListener(&#39;click&#39;, sayHello);
&lt;/script&gt;

// removeEventListener도 있음</code></pre><p>event 종류</p>
<ul>
<li>dbclick(더블 클릭), keydown, keyup</li>
<li>focus, focusin &lt;-&gt; blur</li>
<li>mousemove -&gt; clientX, clientY 이용가능</li>
<li>resize -&gt; window.innerHeight, innerWidth 이용가능</li>
</ul>
<h4 id="이벤트-버블링-이벤트-위임">이벤트 버블링, 이벤트 위임</h4>
<p>이벤트 버블링: 자식 요소에 발생한 이벤트는 부모 요소에 전파된다</p>
<pre><code>// 대부분의 이벤트는 버블링이 일어나나, 
// focus, blur, mouseenter, mouseleave는 그렇지 않음
// 인위적으로 막고 싶다면
event.stopPropagation();</code></pre><p>이벤트 위임: 자신에게 발생한 이벤트를 다른 요소에서 처리하는 것</p>
<pre><code>// li를 클릭할 때 효과를 주고싶으면 모든 li에게 addEventListener를 걸 것이 아니라
// li를 감싸고 있는 ol 또는 ul전체에 addEventListener를 걸어라
// 이벤트가 위임되기 때문에 똑같이 적용됨
event.target; // 이벤트를 발생시키는 요소
event.currentTarget; // 이벤트 헨들러가 등록된 요소</code></pre><h4 id="참고자료">참고자료</h4>
<p><a href="https://www.youtube.com/watch?v=uK6uExrg7Ww&amp;list=PLZKTXPmaJk8JVQv3XSNF8yJMdsxbFrO3S">JavaScript 활용편 DOM&amp;EVENT</a> by 코딩앙마
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType">mdn web docs_Node.nodeType</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript]]></title>
            <link>https://velog.io/@jay_jykim91/JavaScript</link>
            <guid>https://velog.io/@jay_jykim91/JavaScript</guid>
            <pubDate>Fri, 13 May 2022 12:06:40 GMT</pubDate>
            <description><![CDATA[<p>정리 기준</p>
<ol>
<li>평소에 사용하면서도 애매하게 알고 있었던 것</li>
<li>있다는 건 알고 있지만 사용하려고 하면 맨날 오류나서 결국 사용하지 못하는 개념들</li>
</ol>
<h4 id="how-to-use-script-tag">How to use script tag</h4>
<ol>
<li>head 태그 안에 그냥 script 넣기
parsing HTML -&gt; fetching JS, executing JS -&gt; parsing HTML</li>
</ol>
<ul>
<li>JS 파일이 클 경우 나머지 HTML을 parsing하기 까지 오래 걸림<pre><code>&lt;head&gt;
  &lt;script src=&quot;main.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;</code></pre></li>
</ul>
<ol start="2">
<li>body 태그 맨 끝에 그냥 script 넣기
parsing HTML(끝까지) -&gt; fetching JS, executing JS</li>
</ol>
<ul>
<li>웹사이트가 js파일에 많이 의존적이라면, 사용자가 의미있는 콘텐츠를 보기 위해 시간이 오래 걸림<pre><code>&lt;body&gt;
  ...
  &lt;script src=&quot;main.js&quot; async&gt;&lt;/script&gt;
&lt;/body&gt;</code></pre></li>
</ul>
<ol start="3">
<li>head 태그 안에 async로 script 넣기
parsing HTML 하면서 동시에 fetching JS, fetching JS가 끝나면 HTML 받아오던거 멈추고 -&gt; executing JS -&gt; parsing HTML</li>
</ol>
<ul>
<li>2번 방법 보다는 fetching JS가 병렬적으로 일어나기 때문에 fetching JS하는 시간을 절약할 수 있음</li>
<li>하지만 HTML을 전부 받아오기 전에 js가 실행되기 때문에 js가 실행되는데 필요한 요소들이 아직 준비가 안되어 있을 수 있음</li>
<li>여러 js파일을 모두 async로 받아올 경우, 다운로드가 완료된 js파일 순서에 따라 실행되기 때문에 js파일들 간의 의존적인 기능이 있다면 제대로 작동하지 않을 수 있음<pre><code>&lt;head&gt;
  &lt;script src=&quot;main.js&quot; async&gt;&lt;/script&gt;
&lt;/head&gt;</code></pre></li>
</ul>
<ol start="4">
<li>head 태그 안에 defer로 script 넣기
parsing HTML 하면서 동시에 fetching JS, parsing HTML이 모두 끝난 후 -&gt; executing JS</li>
</ol>
<ul>
<li>fetching JS와 parsing HTML이 병렬적으로 진행되어 시간도 아끼고, HTML이 모두 준비된 후에 js를 실행할 수 있음<pre><code>&lt;head&gt;
  &lt;script src=&quot;main.js&quot; defer&gt;&lt;/script&gt;
&lt;/head&gt;</code></pre></li>
</ul>
<h4 id="class">Class</h4>
<p>Getter and Setter</p>
<pre><code>class User {
  constructor(firstName, lastName, age) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
  }

  get age() {
    // 위에 있는 this.age;는 메모리를 읽어오는 것이 아니라
    // 이 getter를 호출하게 됨
    return this._age;
  }

  // setter를 정의하는 순간 위에서 = age;를 호출할 때(값을 할당할 때),
  // 메모리에 값을 할당하는 게 아니라 이 setter를 호출하게 됨
  // 이 말은, setter 안에서 전달된 value를 age에 할당 할 때,
  // 메모리에 값을 할당하는게 아니라 setter를 호출하게 됨. 그러면 무한 반복
  // 따라서 getter와 setter에 쓰여지는 변수는 이름을 다르게 쓴다
  set age(value) {
    // 
    this._age = value;
  }
}</code></pre><p>Public field and Private field</p>
<pre><code>class Experiment {
  publicField = 2;
  #privateField = 0;
}

const experiment = new Experiment();
console.log(experiment.publicField); // 2
console.log(experiment.privateField); // undefined</code></pre><p>Static properties and methods</p>
<pre><code>class Article {
  // object에 상관 없이 class 자체에 연결되어 있음
  static publisher = &#39;Dream Coding&#39;;
  constructor(articleNumber) {
    this.articleNumber = articleNumber;
  }

  static printPublisher() {
    console.log(Article.publisher);
  }
}

const article1 = new Article(1);
console.log(article1.publisher); // undefined
console.log(Article.publisher); // Dream Coding
Article.printPublisher(); // Dream Coding</code></pre><h4 id="object">Object</h4>
<p>for ... in vs. for ... of</p>
<pre><code>// for (key in obj)
for (key in ellie) {
  console.log(key); // ellie 안에 있는 모든 키 출력
}

// for (value of iterable)
const array = [1, 2, 3];
for (value of array) {
  console.log(value);
}</code></pre><p>Cloning</p>
<pre><code>const user = { name: &#39;ellie&#39;, age: 20 }
const user2 = user;
// user는 레퍼런스가 들어있는 메모리를 가리키고 있고, 그 레퍼런스는 데이터를 가지고 있는 오브젝트를 가리킨다
// user2의 변수는 user안에 있는 레퍼런트의 값이 동일한 레퍼런스가 들어있음, 따라서 똑같은 오브젝트를 가르킴

user2.name = &#39;coder&#39;;
console.log(user); // { name: &#39;coder&#39;, age: 20 }

// 위가 아니라 진짜 복사를 하고 싶다면
// old way
const user3 = {};
for (key in user) {
  user3[key] = user[key];
}
// new way
const user4 = {};
Object.assign(user4, user); // Object.assign(target, source);
// 위 두줄을 한줄로 하면
const user4 = Object.assign({}, user);
// 여러 오브젝트를 줄 수 있음
const mixed = Object.assign({}, fruit1, fruit2);
// 동일한 키가 있다면 뒤에 있는 값이 계속 덮어 씌움</code></pre><h4 id="json">JSON</h4>
<p>Object to JSON</p>
<pre><code>// stringify converts a JavaScript value to a JavaScript Object Notation(JSON) string.
let json = JSON.stringify(true);
console.log(json); // true

json = JSON.stringify([&#39;apple&#39;, &#39;banana&#39;]);
console.log(json); // [&quot;apple&quot;, &quot;banana&quot;] -&gt; &quot;&quot; 사용은 JSON의 규격 사항

const rabbit = {
  name: &#39;tori&#39;,
  color: &#39;white&#39;,
  size: null,
  birthDate: new Date(),
  jump: () =&gt; {
    console.log(`${this.name} can jump!`);
  }
};
json = JSON.stringify(rabbit);
console.log(json);
// {&quot;name&quot;:&quot;tori&quot;, &quot;color&quot;:&quot;white&quot;, &quot;size&quot;:null,&quot;birthDate&quot;:&quot;2022-01-10어쩌구&quot;}
// jump 함수는 제외됨, 데이터가 아니기 때문
// symbol같이 JS에만 있는 특별한 데이터도 포함되지 않음

json = JSON.stringify(rabbit, [&quot;name&quot;, &quot;color&quot;]);
console.log(json); // {&quot;name&quot;:&quot;tori&quot;, &quot;color&quot;:&quot;white&quot;}

json = JSON.stringify(rabbit, (key, value) =&gt; {
  console.log(`key: ${key}, value: ${value}`);
  return value;
  // 결과는 아래 이미지
});

json = JSON.stringify(rabbit, (key, value) =&gt; {
  console.log(`key: ${key}, value: ${value}`);
  return key === &#39;name&#39; ? &#39;ellie&#39;: value;
});
console.log(json); // {&quot;name&quot;:&quot;ellie&quot;, &quot;color&quot;:&quot;white&quot;, &quot;size&quot;:null,&quot;birthDate&quot;:&quot;2022-01-10어쩌구&quot;}</code></pre><p>JSON to Object</p>
<pre><code>// parse converts a JavaScript Object Notation(JSON) string into an object.
json = JSON.stringify(rabbit);
const obj = JSON.parse(json);
console.log(obj);
// {name: &quot;tori&quot;, color: &quot;white&quot;, size: null, birthDate: &quot;2022-01-10어쩌구&quot;}
// stringify를 할 때 함수는 변환되지 않기 때문에 parse한 결과에서도 함수가 없다
rabbit.jump(); // tori can jump!
obj.jump(); // jump is not a function

console.log(rabbit.birthDate.getData()); // 10
// 값이 그냥 string이기 때문.. rabbit에 있던 birthDate은 데이트라는 오브젝트 였었다
console.log(obj.birthDate.getData()); // getDate is not a function

// 세밀하게 parse 하고 싶을 때
const obj = JSON.parse(json, (key, value) =&gt; {
  return key === &#39;birthDate&#39; ? new Date(value) : value;
}
console.log(obj.birthDate.getDate); // 10</code></pre><h4 id="비동기-처리_promise-사용-예시">비동기 처리_Promise 사용 예시</h4>
<pre><code>class UserStorage {
  loginUser(id, password) {
      return new Promise((resolve, reject) =&gt; {
            setTimeout(() =&gt; {
            if (
              (id === &#39;ellie&#39; &amp;&amp; password === &#39;dream&#39;) ||
              (id === &#39;coder&#39; &amp;&amp; password === &#39;academy&#39;)
            ) {
              resolve(id);
            } else {
              reject(new Error(&#39;not found&#39;);
            }
            }, 2000);
      }
  });


  // 사용자의 데이터를 받아서 그 정보를 바탕으로 백엔드에 해당 사용자의 역할을 요청해서 받아오는 api
  getRoles(user) {
    return new Promise((resolve, reject) =&gt; {
            setTimeout(() =&gt; {
          if (user === &#39;ellie&#39;) {
            resolve({ name: &#39;ellie&#39;, role: &#39;admin&#39; });
          } else {
            reject(new Error(&#39;no access&#39;);
          };
          }, 1000);
    }); 
  } 
}

const userStorage = new UserStorage();
const id = prompt(&#39;enter your id&#39;);
const password = prompt(&#39;enter your password&#39;);

userStorage
// 로그인을 하고
.loginUser(id, password)
// 로그인에 성공하면 그 유저를 이용해서 역할을 받아오고
.then(user =&gt; userStorage.getRoles)
// 그것에 성공하면 alert를 띄운다
.then(user =&gt; alert(
  `Hello ${user.name}, you have a ${user.role} role`
))
.catch(console.log);</code></pre><h4 id="비동기-처리_async-await-사용-예시">비동기 처리_Async, await 사용 예시</h4>
<pre><code>function delay(ms) {
  return new Promise(resolve =&gt; setTimeout(resolve, ms));
}

async function getApple() {
  // await을 쓰면 delay가 진행되는 3초동안 기다려줌
  await delay(3000);
  // throw &#39;error&#39;;
  return &#39;🍎&#39;;
}

async function getBanana() {
  await delay(3000);
  return &#39;🍌&#39;;
}
// getBanana를 promise로 써보면 아래와 같이 쓸 수 있다
// 하지만 위와 같이 동기적인 코드를 쓰는 것처럼 하면 쉽게 이해할 수 있음
function getBanana() {
  return delay(3000);
  .then(() =&gt; &#39;🍌&#39;);
}

// 아래와 같이 하면 콜백 지옥 비슷해짐
function pickFruits() {
  return getApple()
  .then(apple =&gt; {
    return getBanana()
    .then(banana =&gt; `${apple} + ${banana}`)
  })
}

// 위 코드를 async를 써서 해보자
async function pickFruits() {
  // try, catch로 에러처리 해줄 수도 있음
  const apple = await getApple();
  const banana = await getBanana();
  return `${apple} + ${banana}`;
}
// 여기서 문제는 사과를 받는데 3초가 지나고 또 바나나를 받는데 3초가 지남
// apple과 banana 사이에는 서로 연관이 없기 때문에 서로를 기다릴 필요가 없다

// 따라서 아래와 같이 해볼 수 었음
// const를 만드는 순간 코드는 실행이 된다, 따라서 미리 만들어두고 await을 건다
// 병렬적으로 실행 가능, 하지만 코드가 정말 더러워짐
// 아래 promise api를 이용해봐
async function pickFruits() {
  const applePromise = getApple();
  const bananaPromise = getBanana();

  const apple = await applePromise();
  const banana = await bananaPromise();
  return `${apple} + ${banana}`;
}

pickFruits().then(console.log);

// Useful Promise APIs
function pickAllFruits() {
  // 프로미스 배열을 전달해주면 모든 프로미스들이 병렬적으로 받을 때까지 모아주는 아이
  return Promise.all([getApple(), getBanana()])
    // 이 경우 결과가 배열로 받아짐
  .then(fruits =&gt; fruits.join(&#39; + &#39;);
}
pickAllFruits().then(console.log); // 🍎 + 🍌

// 어떤 과일이던 먼저 따지는 과일 받아오기
function pickOnlyOne() {
  // 배열에 전달 된 프로미스 중에서 값을 가장 먼저 리턴하는 아이만 전달되어짐
  return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log);</code></pre><h4 id="nullish-coalescing-operator">Nullish Coalescing operator</h4>
<p>leftExpr ?? rightExpr
    - 왼쪽 코드가 null, undefined인 경우에만 오른쪽 코드가 실행된다
leftExpr || rightExpr
    - 왼쪽 코드가 falsy인 경우에만 오른쪽 코드가 실행된다</p>
<pre><code>// Bad
function printMessage(text) {
  let message = text;
  if (text == null || text == undefined) {
    message = &#39;Nothing to display&#39;;
  }
  console.log(message);
}

// Good
function printMessage(text) {
  // text가 있다면 그대로 쓰고 없으면 &#39;Nothing to display&#39;
  const message = text ?? &#39;Nothing to display&#39;;
  console.log(message);
}

printMessage(&#39;Hello&#39;); // Hello
printMessage(undefined); // Nothing to display
printMessage(null); // Nothing to display

// 위 함수를 default 값을 준다면?
// undefined인 경우에만 default값이 할당 됨
function printMessage(text = &#39;Nothing to display&#39;) {
  console.log(text);
}

printMessage(&#39;Hello&#39;); // Hello
printMessage(undefined); // Nothing to display
printMessage(null); // Null</code></pre><h4 id="optional-chaining">Optional Chaining</h4>
<pre><code>const bob = {
  name: &#39;Julia&#39;,
  age: 20
};
const anna = {
  name: &#39;Julia&#39;,
  age: 20,
  job: {
    title: &#39;Software Engineer&#39;,
  }
};

// Bad
function displayJobTitle(person) {
  if (person.job &amp;&amp; person.job.title) {
    console.log(person.job.title);
  }
}

// Good
function displayJobTitle(person) {
  // job이 있다면 그 job 안에 title이 있는지 아닌지 확인
  if (person.job?.title) {
    console.log(person.job.title);
  }
}

function displayJobTitle(person) {
  const title = person.job?.title ?? &#39;No Job Yet&#39;;
  console.log(title);
}</code></pre><h4 id="ajax_요즘-사용-방식">AJAX_요즘 사용 방식</h4>
<pre><code>fetch(&#39;https://codingapple1.github.io/price.json&#39;)
  .then((response) =&gt; {
    if (!response.ok) {
      throw new Error(&#39;Error 400 or Error 500&#39;)
    }
    return response.json()
  })
  .then((result) =&gt; {
    console.log(result);
  })
  .catch(() =&gt; {
    console.log(&#39;에러남&#39;);
  })

OR

async function fetchingData() {
  let response = await fetch(&#39;https://codingapple1.github.io/price.json&#39;);
  if (!response.ok) {
    throw new Error(&#39;Error 400 or Error 500&#39;);
  }
  let result = await response.json();
  console.log(result);
}
fetchingData().catch(() =&gt; {
  console.log(&#39;에러남&#39;);
})</code></pre><h4 id="참고자료">참고자료</h4>
<p><a href="https://www.youtube.com/playlist?list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2">Youtube 자바스크립트 기초 강의</a> by 드림코딩</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[05.13.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.13.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.13.22-Coding-test</guid>
            <pubDate>Fri, 13 May 2022 00:28:38 GMT</pubDate>
            <description><![CDATA[<h1 id="replace-with-alphabet-position">Replace With Alphabet Position</h1>
<h2 id="description">Description</h2>
<p>In this kata you are required to, given a string, replace every letter with its position in the alphabet.
If anything in the text isn&#39;t a letter, ignore it and don&#39;t return it.
&quot;a&quot; = 1, &quot;b&quot; = 2, etc.
Example
alphabetPosition(&quot;The sunset sets at twelve o&#39; clock.&quot;)
Should return &quot;20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11&quot; ( as a string )</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function alphabetPosition(text) {
  let alphabets = &#39;abcdefghijklmnopqrstuvwxyz&#39;.split(&#39;&#39;);

  let result = text.toLowerCase().split(&#39;&#39;).map(function(letter) {
    return alphabets.includes(letter) ? alphabets.indexOf(letter) + 1 : &#39; &#39;
  })

  return result.filter(a =&gt; a != &#39; &#39;).join(&#39; &#39;);
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>function alphabetPosition(text) {
  var result = &quot;&quot;;
  for (var i = 0; i &lt; text.length; i++){
    var code = text.toUpperCase().charCodeAt(i)
    if (code &gt; 64 &amp;&amp; code &lt; 91) result += (code - 64) + &quot; &quot;;
  }

  return result.slice(0, result.length-1);
}</code></pre><h2 id="wrap-up">Wrap up</h2>
<h3 id="charcodeat-method">charCodeAt method</h3>
<p>The charCodeAt() method returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.</p>
<pre><code>String.charCodeAt(index)</code></pre><h4 id="parameters">Parameters</h4>
<h5 id="index">index</h5>
<p>An integer greater than or equal to 0 and less than the length of the string. If index is not a number, it defaults to 0</p>
<h4 id="return-value">Return value</h4>
<p>A number representing the UTF-16 code unit value of the character at the given index. If index is out of range, charCodeAt() returns NaN.</p>
<h4 id="examples">Examples</h4>
<pre><code>// The following example returns 65, the Unicode value for A.

&#39;ABC&#39;.charCodeAt(0)  // returns 65</code></pre><p>source: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt">mdn web docs</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[05.12.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.12.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.12.22-Coding-test</guid>
            <pubDate>Thu, 12 May 2022 01:00:02 GMT</pubDate>
            <description><![CDATA[<h1 id="number-of-trailing-zeros-of-n">Number of trailing zeros of N!</h1>
<h2 id="description">Description</h2>
<p>Write a program that will calculate the number of trailing zeros in a factorial of a given number.
N! = 1 * 2 * 3 * ... * N
Be careful 1000! has 2568 digits...
For more info, see: <a href="http://mathworld.wolfram.com/Factorial.html">http://mathworld.wolfram.com/Factorial.html</a>
Examples
zeros(6) = 1
// 6! = 1 * 2 * 3 * 4 * 5 * 6 = 720 --&gt; 1 trailing zero
zeros(12) = 2
// 12! = 479001600 --&gt; 2 trailing zeros
Hint: You&#39;re not meant to calculate the factorial. Find another way to find the number of zeros.</p>
<h2 id="other-solution">Other Solution</h2>
<pre><code>function zeros (n) {
  let result = 0;

  while(n &gt; 0){
    n = Math.floor(n/5);
    result += n
  }

  return result;
}</code></pre><h2 id="comments">Comments</h2>
<p>5 comes from the prime dividers To have a trailing zero, the number have to be divided by 10. Same as divided by 2 and 5.
In a factorial computation, there will be a lot more of *2 that *5, so we count how many times the final number can be divided by 5 and we have the number of times it&#39;s dividable by 10.</p>
<p>source: <a href="https://en.wikipedia.org/wiki/Trailing_zero">wikipedia_Trailing zero</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[05.11.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.11.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.11.22-Coding-test</guid>
            <pubDate>Wed, 11 May 2022 02:00:12 GMT</pubDate>
            <description><![CDATA[<h1 id="counting-duplicates">Counting Duplicates</h1>
<h2 id="description">Description</h2>
<p>Count the number of Duplicates
Write a function that will return the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string. The input string can be assumed to contain only alphabets (both uppercase and lowercase) and numeric digits.
Example
&quot;abcde&quot; -&gt; 0 # no characters repeats more than once
&quot;aabbcde&quot; -&gt; 2 # &#39;a&#39; and &#39;b&#39;
&quot;aabBcde&quot; -&gt; 2 # &#39;a&#39; occurs twice and &#39;b&#39; twice (<code>b</code> and <code>B</code>)
&quot;indivisibility&quot; -&gt; 1 # &#39;i&#39; occurs six times
&quot;Indivisibilities&quot; -&gt; 2 # &#39;i&#39; occurs seven times and &#39;s&#39; occurs twice
&quot;aA11&quot; -&gt; 2 # &#39;a&#39; and &#39;1&#39;
&quot;ABBA&quot; -&gt; 2 # &#39;A&#39; and &#39;B&#39; each occur twice</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function duplicateCount(text){
  let inputArr = text.toLowerCase().split(&#39;&#39;);
  let resultObj = {};

  for(let i = 0; i &lt; inputArr.length; i++) {
    (resultObj.hasOwnProperty(inputArr[i])) ? 
      resultObj[inputArr[i]].count += 1 : resultObj[inputArr[i]] = { count: 1 }
  }

  let result = 0;

  for(let key in resultObj) {
    if (resultObj[key].count &gt; 1) {
      result += 1;
    }
  }

  return result
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>function duplicateCount(text){
  return text.toLowerCase().split(&#39;&#39;).filter(function(val, i, arr){
    return arr.indexOf(val) !== i &amp;&amp; arr.lastIndexOf(val) === i;
  }).length;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[05.10.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.10.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.10.22-Coding-test</guid>
            <pubDate>Tue, 10 May 2022 01:34:07 GMT</pubDate>
            <description><![CDATA[<h1 id="which-are-in">Which are in?</h1>
<h2 id="description">Description</h2>
<p>Given two arrays of strings a1 and a2 return a sorted array r in lexicographical order of the strings of a1 which are substrings of strings of a2.
Example 1:
a1 = [&quot;arp&quot;, &quot;live&quot;, &quot;strong&quot;]
a2 = [&quot;lively&quot;, &quot;alive&quot;, &quot;harp&quot;, &quot;sharp&quot;, &quot;armstrong&quot;]
returns [&quot;arp&quot;, &quot;live&quot;, &quot;strong&quot;]
Example 2:
a1 = [&quot;tarp&quot;, &quot;mice&quot;, &quot;bull&quot;]
a2 = [&quot;lively&quot;, &quot;alive&quot;, &quot;harp&quot;, &quot;sharp&quot;, &quot;armstrong&quot;]
returns []
Notes:
Arrays are written in &quot;general&quot; notation. See &quot;Your Test Cases&quot; for examples in your language.
In Shell bash a1 and a2 are strings. The return is a string where words are separated by commas.
Beware: r must be without duplicates.</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function inArray(array1,array2){
  let result = [];

  for(let i = 0; i &lt; array1.length; i++) {
    for(let j = 0; j &lt; array2.length; j++) {
      if (array2[j].includes(array1[i])) {
        result.push(array1[i])
      }
    }
  }

  return [...new Set(result)].sort()
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>function inArray(arr1, arr2) {
  return arr1.filter(function(needle) {
    return arr2.some(function(haystack) {
      return haystack.indexOf(needle) &gt; -1;
    });
  }).sort();
}</code></pre><pre><code>function inArray(array1,array2){
  return array1
    .filter(a1 =&gt; array2.find(a2 =&gt; a2.match(a1)))
    .sort()
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[05.09.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.09.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.09.22-Coding-test</guid>
            <pubDate>Mon, 09 May 2022 01:10:02 GMT</pubDate>
            <description><![CDATA[<h1 id="multiplication-table">Multiplication table</h1>
<h2 id="description">Description</h2>
<p>Your task, is to create NxN multiplication table, of size provided in parameter.
for example, when given size is 3:
1 2 3
2 4 6
3 6 9
for given example, the return value should be: [[1,2,3],[2,4,6],[3,6,9]]</p>
<h2 id="my-answer">My answer</h2>
<pre><code>multiplicationTable = function(size) {
  let result = [];

  for (let i = 1; i &lt;= size; i++) {
    let pushedArr = [];
    for (let m = 1; m &lt;= size; m++) {
      pushedArr.push(m * i);
    }
    result.push(pushedArr);
  }
  return result;
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>multiplicationTable = function(size) {
  var result = [];

  for (var i = 0; i &lt; size; i++) {
    result[i] = [];
    for(var j = 0; j &lt; size; j++) {
      result[i][j] = (i + 1) * (j + 1);
    }
  }

  return result
}</code></pre><pre><code>multiplicationTable = function(size) {

  return Array.apply(null, new Array(size)).map(function(val, i) {
    return Array.apply(null, new Array(size)).map(function(val, j) {
      return (i+1) * (j+1);
    });
  });
}</code></pre><h2 id="wrap-up">Wrap up</h2>
<h3 id="apply-function">apply function</h3>
<pre><code>func.apply(thisArg, [argsArray])</code></pre><h4 id="parameters">Parameters</h4>
<h5 id="thisarg">thisArg</h5>
<p>The value of this provided for the call to func.</p>
<h5 id="argsarrayoptional">argsArray(optional)</h5>
<p>An array-like object, specifying the arguments with which func should be called, or null or undefined if no arguments should be provided to the function.</p>
<h4 id="return-value">Return value</h4>
<p>The result of calling the function with the specified this value and arguments.</p>
<h4 id="examples">Examples</h4>
<pre><code>const array = [&#39;a&#39;, &#39;b&#39;];
const elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // [&quot;a&quot;, &quot;b&quot;, 0, 1, 2]</code></pre><pre><code>// min/max number in an array
const numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
let max = Math.max.apply(null, numbers);
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

let min = Math.min.apply(null, numbers);</code></pre><p>source: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">mdn web docs</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[05.08.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.08.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.08.22-Coding-test</guid>
            <pubDate>Sun, 08 May 2022 02:40:53 GMT</pubDate>
            <description><![CDATA[<h1 id="isbn-10-validation">ISBN-10 Validation</h1>
<h2 id="description">Description</h2>
<p>ISBN-10 identifiers are ten digits long. The first nine characters are digits 0-9. The last digit can be 0-9 or X, to indicate a value of 10.
An ISBN-10 number is valid if the sum of the digits multiplied by their position modulo 11 equals zero.
For example:
ISBN     : 1 1 1 2 2 2 3 3 3  9
position : 1 2 3 4 5 6 7 8 9 10
This is a valid ISBN, because:
(1<em>1 + 1</em>2 + 1<em>3 + 2</em>4 + 2<em>5 + 2</em>6 + 3<em>7 + 3</em>8 + 3<em>9 + 9</em>10) % 11 = 0
Examples
1112223339   --&gt;  true
111222333    --&gt;  false</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function validISBN10(isbn) {
  if (!(/^\d{9}[\d|X]$/.test(isbn))) { return false }

  let sum = 0;
  let arr = [...isbn];
  for (let i = 0; i &lt; arr.length; i++) {
    sum += (arr[i] === &#39;X&#39;) ? (10 * (i+1)) : (arr[i] * (i+1))
  }
  return (sum % 11 === 0) ? true : false;
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>function validISBN10(isbn) {
  var len = isbn.length;

  if (len !== 10) {
      return false;
  }

  return isbn.split(&#39;&#39;)
      .map(function (num, index) {
         return (num === &#39;X&#39; &amp;&amp; index === len - 1 ? 10 : parseInt(num, 10)) * (index + 1); 
      })
      .reduceRight(function (a, b) {
          return a + b;
      }, 0) % 11 === 0;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[05.17.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.07.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.07.22-Coding-test</guid>
            <pubDate>Sat, 07 May 2022 02:28:16 GMT</pubDate>
            <description><![CDATA[<h1 id="convert-a-hex-string-to-rgb">Convert A Hex String To RGB</h1>
<h2 id="description">Description</h2>
<p>When working with color values it can sometimes be useful to extract the individual red, green, and blue (RGB) component values for a color. Implement a function that meets these requirements:
Accepts a case-insensitive hexadecimal color string as its parameter (ex. &quot;#FF9933&quot; or &quot;#ff9933&quot;)
Returns a Map&lt;String, int&gt; with the structure {r: 255, g: 153, b: 51} where r, g, and b range from 0 through 255
Note: your implementation does not need to support the shorthand form of hexadecimal notation (ie &quot;#FFF&quot;)
Example
&quot;#FF9933&quot; --&gt; {r: 255, g: 153, b: 51}</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function hexStringToRGB(hexString) {
  let array = [hexString.slice(1,3), hexString.slice(3,5), hexString.slice(5,7)];
  let result = {}

  result.r = parseInt(array[0], 16);
  result.g = parseInt(array[1], 16);
  result.b = parseInt(array[2], 16);

  return result;
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>const hexStringToRGB = str =&gt; {
  const [r, g, b] = str.match(/\w{2}/g).map(x =&gt; parseInt(x, 16));
  return { r, g, b };
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[CSS]]></title>
            <link>https://velog.io/@jay_jykim91/CSS</link>
            <guid>https://velog.io/@jay_jykim91/CSS</guid>
            <pubDate>Fri, 06 May 2022 12:31:13 GMT</pubDate>
            <description><![CDATA[<p>정리 기준</p>
<ol>
<li>평소에 사용하면서도 애매하게 알고 있었던 것</li>
<li>있다는 건 알고 있지만 평소에 잘 사용하지 않아 이번 기회에 다시 한번 짚고 가는 것</li>
</ol>
<h4 id="css-구문">CSS 구문</h4>
<p>selector { property: value }</p>
<pre><code>h1 { 
  color: yellow 
}</code></pre><h4 id="css-적용">CSS 적용</h4>
<ol>
<li>Inline
html 파일 안에서 해당 요소에 직접 스타일 적용<pre><code>&lt;div style=&quot;color:red;&quot;&gt; 내용 &lt;/div&gt;</code></pre></li>
<li>Internal
html 파일 안에서 head 태그 안에 style 태그를 활용하여 스타일 적용<pre><code>&lt;style&gt; div {color: red;} &lt;/style&gt;</code></pre></li>
<li>External
외부 css 파일에 스타일을 작성하고 html에서 아래와 같이 연결하여 스타일 적용<pre><code>&lt;link rel=&quot;stylesheet&quot; href=&quot;css/style.css&quot;&gt;</code></pre></li>
<li>Import
css 파일 내에서 다른 css 파일을 불러와서 적용하는 방식<pre><code>@import url(&quot;css/style2.css&quot;);</code></pre></li>
</ol>
<h4 id="선택자">선택자</h4>
<ol>
<li>요소 선택자(태그 선택자)<pre><code>h1 { color: yellow; }</code></pre></li>
<li>class 선택자<pre><code>css 파일
.foo { font-size: 30px; }
</code></pre></li>
</ol>
<p>html 파일</p>
<p class="foo"> ... </p>
```
3. id 선택자
```
css 파일
#bar { background-color: yellow; }

<p>html 파일</p>
<p id="bar"> ... </p>
```
4. 선택자 조합
```
/* 요소와 class의 조합 */
p.bar { ... }

<p>/* 다중 class */
.foo.bar { ... }</p>
<p>/* id와 class의 조합 */
#foo.bar { ... }</p>
<pre><code>5. 속성 선택자</code></pre><p>css 파일
p 태그 중 class나 Id속성을 가지고 있는 요소
p[class] { color: silver; }
p[class][id] { text-decoration: underline; }</p>
<p>p 태그 중 class가 &#39;foo&#39;인 요소, Id가 &#39;title&#39;인 요소
p[class=&quot;foo&quot;] { color: silver; }
p[id=&quot;title&quot;] { text-decoration: underline; }</p>
<p>html 파일</p>
<p class="foo">Hello</p>
<p class="bar">CSS</p>
<p class="baz" id="title">HTML</p>
```
```
[class~="bar"] : class 속성의 값이 공백으로 구분한 "bar" 단어가 포함되는 요소 선택
[class^="bar"] : class 속성의 값이 "bar"로 시작하는 요소 선택
[class$="bar"] : class 속성의 값이 "bar"로 끝나는 요소 선택
[class*="bar"] : class 속성의 값이 "bar" 문자가 포함되는 요소 선택

<p>css 파일
p[class~=&quot;color&quot;] { font-style: italic; } /* 1, 2번째 요소 <em>/
p[class^=&quot;color&quot;] { font-style: italic; } /</em> 1, 3번째 요소 <em>/
p[class$=&quot;color&quot;] { font-style: italic; } /</em> 2번째 요소 <em>/
p[class</em>=&quot;color&quot;] { font-style: italic; } /* 1, 2, 3번째 요소 */</p>
<p>html 파일</p>
<p class="color hot">red</p>
<p class="cool color">blue</p>
<p class="colorful nature">rainbow</p>
```
6. 문서 구조 관련 선택자
자손 선택자: 선택자 사이에 아무 기호 없이 공백으로 구분함
```
/* <div>의 자손 요소인 <span>를 선택하는 선택자 */
div span { color: red; }
```
자식 선택자: 선택자 사이에 꺽쇠 기호(>)로 구분함
```
/* <div>의 자식 요소인 <span>를 선택하는 선택자 */
div > h1 { color: red; }
```
인접 형제 선택자: 선택자 사이에 + 기호로 구분함
```
div + p { color: red; }

<p>/* body 요소의 자식인 div 요소의 자손인 table 요소 바로 뒤에 인접한 ul 요소 선택 */
body &gt; div table + ul { ... }</p>
<pre><code>#### 가상 클래스(pseudo class)
미리 정의해놓은 상황에 적용되도록 약속된 보이지 않는 클래스
:first-child : 첫 번째 자식 요소 선택
:last-child : 마지막 자식 요소 선택
:link : 하이퍼 링크이면서 아직 방문하지 않은 앵커
:visited : 이미 방문한 하이퍼링크를 의미
:focus: 현재 입력 초점을 가진 요소에 적용
:hover: 마우스 포인터가 있는 요소에 적용
:before : 가장 앞에 요소를 삽입
:after : 가장 뒤에 요소를 삽입
:first-line : 요소의 첫 번째 줄에 있는 텍스트
:first-letter : 블록 레벨 요소의 첫 번째 문자
#### 속성 - 단위 - 상대 길이
%: 부모의 값에 대해서 백분율로 환산한 크기
em: font-size를 기준으로 값을 환산, 소수점 3자리까지 표현 가능
rem: root의 font-size를 기준으로 값을 환산
vw: viewport의 width값을 기준으로 1%의 값으로 계산
#### 속성 - 색상
컬러 키워드: ex) yellow, red
16 진법 
- 6자리의 16진수(0-9, A-F)는 각각 두 자리씩 세 가지 색상을 나타내며, 첫 번째 두 자리는 적색(RR), 가운데 두 자리는 녹색(GG), 마지막 두 자리는 청색(BB)을 의미함 ex) #RRGGBB
- 6자리의 16진수에서 각각의 두 자리가 같은 값을 가지면 3자리로 축약하여 사용할 수 있음 ex) #aa11cc 는 #a1c로 축약
RGB( ): RGB 값은 rgb(R, G, B)의 형태로 각 변수 값(R 적색, G 녹색, B 청색)의 강도를 정의하며, 0~255의 정수로 된 값을 지정. 0 → 255는 검정 → 흰색으로 값의 변화를 나타냄
RGBA( ): 기존 RGB에서 A값이 추가된 형태. rgb(R, G, B, A)의 형태로 각 변수는(R 적색, G 녹색, B 청색, A 투명도)의 강도를 나타냄. A 값은 0 ~ 1 사이의 값을 지정할 수 있으며, 0.5와 같이 소수점으로 표기하며, 0 → 1은 투명 → 불투명으로 값의 변화를 나타냄 ex) rgba( 0, 0, 0, 0)는 투명한 색상
#### background 속성</code></pre><p>background: [-color] [-image] [-repeat] [-attachment] [-position];</p>
<pre><code>#### 타이포그래피의 구조
em: 폰트의 전체 높이
ex(=x-height): 해당 폰트의 영문 소문자 x의 높이
Baseline: 소문자 x를 기준으로 하단의 라인
Descender: 소문자에서 baseline 아래로 쳐지는 영역, 서체에 따라 descender의 길이가 다름(g,j,p,q,y)
Ascender: 소문자 x의 상단 라인 위로 넘어가는 영역(b,d,h,l)
![structure of typography](https://velog.velcdn.com/images/jay_jykim91/post/f10d7838-efe6-42b6-9766-49e57481d65c/image.png)
#### webfont 속성
@font-face: 웹에 있는 글꼴을 사용자의 로컬 환경(컴퓨터)으로 다운로드하여 적용하는 속성</code></pre><p>@font-face {
    font-family: webNanumGothic; /* 사용자 지정 웹 폰트명 <em>/
    src: url(NanumGothic.eot); /</em> 적용 될 웹 폰트의 경로 <em>/
    font-weight: bold; /</em> 필요에 따라 지정 <em>/
    font-style: italic; /</em> 필요에 따라 지정 */
}</p>
<pre><code>#### 단어 관련 속성
white-space: 요소 안에 공백을 어떻게 처리할지 지정하는 속성
- normal: 공백과 개행을 무시, 필요한 경우에 자동 줄바꿈 O, 기본 값
- nowrap: 공백과 개행을 무시, 자동 줄바꿈 X
- pre: 공백과 개행을 표현, 자동 줄바꿈 X
- pre-line: 공백은 무시, 개행만 표현. 필요한 경우에 자동 줄바꿈 O
- pre-wrap: 개행은 무시, 공백만 표현. 필요한 경우 자동 줄바꿈 O
#### clear 속성_레이아웃
요소를 floating 된 요소의 영향에서 벗어나게 하는 속성
- none: 양쪽으로 floating 요소를 허용(기본값)
- left: 왼쪽으로 floating 요소를 허용하지 않음
- right: 오른쪽으로 floating 요소를 허용하지 않음
- both: 양쪽으로 floating 요소를 허용하지 않음
#### HTML/CSS 유효성 검사 테스트
[The W3C Markup Validation Service](https://validator.w3.org/)
#### Media query
미디어 타입
- all, braille, embossed, handheld, print, projection, screen, speech, tty, tv
미디어 타입
- width, height, device-width, device-height, orientation(세로/가로 모드), aspect-ratio, device-aspect-ratio, color, color-index, monochrome, resolution, scan, grid</code></pre><p>@media screen { ... }
@media screen and (min-width: 768px) { ... }
@media (min-width: 768px) and (max-width: 1024px) { ... }
@media (color-index)
    : 미디어 장치가 color-index를 지원하면 적용
@media screen and (min-width: 768px), screen and (orientation: portrait), ...
    : 쉼표로 연결된 미디어 쿼리 중 하나라도 참이면 적용(and 키워드와 반대)</p>
<pre><code>#### Viewport
설정 시, head 태그 안에 meta 태그 사용
- width(height) : 뷰포트의 가로(세로) 크기를 지정. px단위의 수치가 들어갈 수 있지만, 대부분 특수 키워드인 &quot;device-width(height)&quot;를 사용(뷰포트의 크기를 기기의 스크린 width(height) 크기로 설정)
- initial-scale : 페이지가 처음 나타날 때 초기 줌 레벨 값을 설정(소수값)
- user-scalable : 사용자의 확대/축소 기능을 설정</code></pre><meta name="viewport" content="width=device-width, initial-scale=1.0">
```
#### 참고자료
[boostcourse 비전공자를 위한 HTML/CSS](https://www.boostcourse.org/cs120)]]></description>
        </item>
        <item>
            <title><![CDATA[HTML]]></title>
            <link>https://velog.io/@jay_jykim91/HTML</link>
            <guid>https://velog.io/@jay_jykim91/HTML</guid>
            <pubDate>Fri, 06 May 2022 12:30:52 GMT</pubDate>
            <description><![CDATA[<p>정리 기준</p>
<ol>
<li>평소에 사용하면서도 애매하게 알고 있었던 것</li>
<li>있다는 건 알고 있지만 평소에 잘 사용하지 않아 이번 기회에 다시 한번 짚고 가는 것</li>
</ol>
<h4 id="empty-tag빈-태그">Empty tag(빈 태그)</h4>
<p>종료 태그 없이 사용하는 태그
Empty tags contain only the opening tag but they perform some action in the webpage</p>
<pre><code>&lt;br&gt;, &lt;img src=&#39;&#39;&gt;, &lt;input type=&#39;&#39;&gt;</code></pre><h4 id="공백-무시">공백 무시</h4>
<p>기본적으로 HTML은 두 칸 이상의 공백을 모두 무시</p>
<h4 id="텍스트-표현-태그">텍스트 표현 태그</h4>
<pre><code>&lt;b&gt; : bold 태그는 글자를 굵게 표현하는 태그
&lt;i&gt; : italic 태그는 글자를 기울여서 표현하는 태그 
      특정 이유(기술적인 용어, 외국어 문구, 소설속 인물의 생각 등)로 다른 글자와 구분하기 위해 사용
&lt;u&gt; : underline 태그는 글자의 밑줄을 표현하는 태그
&lt;s&gt; : strike 태그는 글자의 중간선을 표현하는 태그</code></pre><h4 id="dl-태그">dl 태그</h4>
<p>dl(definition/description list) 태그는 용어와 그에 대한 정의를 표현할 때 사용
dl은 용어와 설명이 하나의 세트로 항목을 이루고 하나 이상의 항목으로 리스트가 이루어지는 구조</p>
<pre><code>&lt;dt&gt; : 용어를 나타내는 태그
&lt;dd&gt; : 용어에 대한 정의 또는 설명을 나타내는 태그</code></pre><p><img src="https://velog.velcdn.com/images/jay_jykim91/post/84cc67c7-b3a9-43f6-8c94-70ccc28d2d57/image.png" alt="dl 태그 예시 이미지"></p>
<h4 id="상대경로와-절대경로">상대경로와 절대경로</h4>
<p>상대경로는 현재 웹 페이지를 기준으로 상대적으로 이미지의 위치를 나타내는 경로를 뜻하며, &#39;./&#39;는 페이지가 있는 현재 폴더를 나타냄
절대경로는 실제 그 이미지가 위치한 곳의 전체 경로</p>
<pre><code>&lt;!-- 상대경로 --&gt;
&lt;img src=&quot;./images/pizza.png&quot; alt=&quot;피자&quot;&gt;

&lt;!-- 절대경로 --&gt;
&lt;img src=&quot;C:/users/document/images/pizza.png&quot; alt=&quot;피자&quot;&gt;
&lt;img src=&quot;http://www.naver.com/pizza.png&quot; alt=&quot;피자&quot;&gt;</code></pre><h4 id="이미지-파일-형식">이미지 파일 형식</h4>
<p>gif : 제한적인 색을 사용하고 용량이 적으며 투명 이미지와 애니메이션 이미지를 지원하는 형식
jpg : 사진이나 일반적인 그림에 쓰이며 높은 압축률과 자연스러운 색상 표현을 지원하는 형식(투명을 지원하지 않음)
png : 이미지 손실이 적으며 투명과 반투명을 모두 지원하는 형식</p>
<h4 id="input-태그">input 태그</h4>
<p>type=&quot;submit&quot;: form의 값을 전송하는 버튼
type=&quot;reset&quot;: form의 값을 초기화하는 버튼
type=&quot;image&quot;: 이미지를 삽입할 수 있는 버튼 (submit과 동작이 동일함)
type=&quot;button&quot;: 아무 기능이 없는 버튼</p>
<h4 id="button-태그">button 태그</h4>
<pre><code>&lt;button type=&quot;submit|reset|button&quot;&gt;버튼 안에 들어갈 텍스트&lt;/button&gt;</code></pre><h4 id="label-태그">label 태그</h4>
<p>label은 form 요소의 이름과 form 요소를 명시적으로 연결시켜주기 위해 사용하며, 모든 form 요소에 사용할 수 있음
form 요소의 id 속성값과 label의 for 속성값을 같게 적어주어야 함
또한, 스크린 리더기를 통해 듣게 되면 해당 form 요소에 접근 시 label을 함께 읽어줌
label은 사용성, 접근성적인 측면으로 중요한 역할을 하므로 반드시 써주는 것이 좋음 <del>-&gt; 잘 안썼던 거 같은데 반성....</del></p>
<pre><code>&lt;label for=&quot;name&quot;&gt;이름&lt;/label&gt;: &lt;input type=&quot;text&quot; id=&quot;name&quot;&gt;&lt;br&gt;
&lt;label for=&quot;nickname&quot;&gt;이름&lt;/label&gt;: &lt;input type=&quot;text&quot; id=&quot;nickname&quot;&gt;&lt;br&gt;
&lt;label for=&quot;address&quot;&gt;이름&lt;/label&gt;: &lt;input type=&quot;text&quot; id=&quot;address&quot;&gt;&lt;br&gt;</code></pre><h4 id="fieldset-legend">fieldset, legend</h4>
<p>form 요소를 구조화 하기 위해 필요한 태그
fieldset: 여러 개의 폼 요소를 그룹화하여 구조적으로 만들기 위해 사용
legend: 폼 요소의 제목으로 fieldset 내부에서 반드시 최상단에 위치해야 함</p>
<pre><code>&lt;fieldset&gt;
    &lt;legend&gt;기본 정보&lt;/legend&gt;
    ... 폼 요소들 ...
&lt;/fieldset&gt;</code></pre><h4 id="form">form</h4>
<p>form 요소들을 감싸는 태그로 데이터를 묶어서 실제 서버로 전송해주는 역할을 하는 태그
대표적인 속성 2가지</p>
<ul>
<li>action: 데이터를 처리하기 위한 서버의 주소</li>
<li>method: 데이터를 전송하는 방식을 지정
  get: 데이터가 전송될 때 주소창에 파라미터 형태로 붙어 데이터가 노출됨
  post: 데이터가 전송될 때 데이터가 노출되지 않음<pre><code>&lt;form action=&quot;&quot; method=&quot;&quot;&gt;
  &lt;fieldset&gt;
      &lt;legend&gt;기본 정보&lt;/legend&gt;
      ... 폼 요소들 ...
  &lt;/fieldset&gt;
&lt;/form&gt;</code></pre></li>
</ul>
<h4 id="content-models">Content Models</h4>
<h5 id="metadata">Metadata</h5>
<p>콘텐츠의 스타일, 동작을 설정하거나 다른 문서와의 관계 등 정보를 포함하는 요소들
ex) link, meta, script, style, title</p>
<h5 id="flow">Flow</h5>
<p>문서의 자연스러운 흐름에 의해 배치되는 요소들
ex) a, button, canvas, details, form, p, section 등 대부분</p>
<h5 id="sectioning">Sectioning</h5>
<p>문서의 구조와 관련된 요소들
ex) article, aside, nav, section</p>
<h5 id="heading">Heading</h5>
<p>각 section의 header를 정의하는 heading 태그
ex) h1~h6</p>
<h5 id="phrasing">Phrasing</h5>
<p>문서의 텍스트 또는 텍스트를 꾸며주는 문단 내부 레벨로 사용되는 요소들
ex) abbr, code, embed, iinput, ruby, ...</p>
<h5 id="embedded">Embedded</h5>
<p>외부 콘텐츠를 표현하는 요소들이 포함되며 오디오나 비디오, 이미지 등 멀티미디어 관련 요소들
ex) audio, canvas, embed, math, object, svg</p>
<h5 id="interactive">Interactive</h5>
<p>사용자와 상호작용을 하는 요소들
ex) audio, form, menu, select, ...</p>
<h4 id="html5-시멘틱-요소">HTML5 시멘틱 요소</h4>
<p>article, aside, figcaption, figure, footer, header, main, mark, nav, section, time</p>
<h4 id="참고자료">참고자료</h4>
<p><a href="https://www.boostcourse.org/cs120">boostcourse 비전공자를 위한 HTML/CSS</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[05.06.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.06.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.06.22-Coding-test</guid>
            <pubDate>Fri, 06 May 2022 05:06:26 GMT</pubDate>
            <description><![CDATA[<h1 id="credit-card-mask">Credit Card Mask</h1>
<h2 id="description">Description</h2>
<p>Usually when you buy something, you&#39;re asked whether your credit card number, phone number or answer to your most secret question is still correct. However, since someone could look over your shoulder, you don&#39;t want that shown on your screen. Instead, we mask it.
Your task is to write a function maskify, which changes all but the last four characters into &#39;#&#39;.
Examples
&quot;4556364607935616&quot; --&gt; &quot;############5616&quot;
     &quot;64607935616&quot; --&gt;      &quot;#######5616&quot;
               &quot;1&quot; --&gt;                &quot;1&quot;
                &quot;&quot; --&gt;                 &quot;&quot;</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function maskify(cc) {
  if (cc.length &lt; 5) { return cc };
  return &#39;#&#39;.repeat(cc.slice(0, -4).length) + cc.slice(-4);
}
</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>function maskify(cc) {
  return cc.slice(0, -4).replace(/./g, &#39;#&#39;) + cc.slice(-4);
}</code></pre><pre><code>function maskify(cc) {
  return cc.replace(/.(?=....)/g, &#39;#&#39;);
}</code></pre><pre><code>function maskify(cc) {
  return cc.replace(/.(?=.{4})/g, &quot;#&quot;);
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[05.05.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.05.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.05.22-Coding-test</guid>
            <pubDate>Wed, 04 May 2022 23:55:44 GMT</pubDate>
            <description><![CDATA[<h1 id="camelcase-method">CamelCase Method</h1>
<h2 id="description">Description</h2>
<p>Write simple .camelCase method (camel_case function in PHP, CamelCase in C# or camelCase in Java) for strings. All words must have their first letter capitalized without spaces.
For instance:
&quot;hello case&quot;.camelCase() =&gt; HelloCase
&quot;camel case word&quot;.camelCase() =&gt; CamelCaseWord</p>
<h2 id="my-answer">My answer</h2>
<pre><code>String.prototype.camelCase=function(){
  return this.split(&#39; &#39;).map(function(word) {
    return word.charAt(0).toUpperCase() + word.slice(1)
  }).join(&#39;&#39;)
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[05.04.22] Coding test]]></title>
            <link>https://velog.io/@jay_jykim91/05.04.22-Coding-test</link>
            <guid>https://velog.io/@jay_jykim91/05.04.22-Coding-test</guid>
            <pubDate>Tue, 03 May 2022 22:50:52 GMT</pubDate>
            <description><![CDATA[<h1 id="weird-string-case">WeIrD StRiNg CaSe</h1>
<h2 id="description">Description</h2>
<p>Write a function toWeirdCase (weirdcase in Ruby) that accepts a string, and returns the same string with all even indexed characters in each word upper cased, and all odd indexed characters in each word lower cased. The indexing just explained is zero based, so the zero-ith index is even, therefore that character should be upper cased and you need to start over for each word.
The passed in string will only consist of alphabetical characters and spaces(&#39; &#39;). Spaces will only be present if there are multiple words. Words will be separated by a single space(&#39; &#39;).
Examples:
toWeirdCase( &quot;String&quot; );//=&gt; returns &quot;StRiNg&quot;
toWeirdCase( &quot;Weird string case&quot; );//=&gt; returns &quot;WeIrD StRiNg CaSe&quot;</p>
<h2 id="my-answer">My answer</h2>
<pre><code>function toWeirdCase(string){
  let result = string.split(&#39; &#39;).map(function(word) {
    let arr = word.split(&#39;&#39;);
    for(let i = 0; i &lt; arr.length; i++) {
      i % 2 === 0 ? arr[i] = arr[i].toUpperCase() : arr[i] = arr[i].toLowerCase();
    }
    return arr.join(&#39;&#39;);
  })

  return result.join(&#39; &#39;);
}</code></pre><h2 id="other-solutions">Other solutions</h2>
<pre><code>function toWeirdCase(string){
  return string.split(&#39; &#39;).map(function(word){
    return word.split(&#39;&#39;).map(function(letter, index){
      return index % 2 == 0 ? letter.toUpperCase() : letter.toLowerCase()
    }).join(&#39;&#39;);
  }).join(&#39; &#39;);
}</code></pre>]]></description>
        </item>
    </channel>
</rss>