<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Xxxyoonx</title>
        <link>https://velog.io/</link>
        <description>UX에 관심많은 프론트 엔드 개발자입니다:)</description>
        <lastBuildDate>Sun, 26 Feb 2023 14:32:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Xxxyoonx</title>
            <url>https://media.vlpt.us/images/jiynn_12/profile/cd0fa4fc-1393-4276-a938-39e9654a143b/ETlDdQ8WAAcPzbl.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Xxxyoonx. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jiynn_12" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[docker + ec2 로 react 프로젝트 배포하기 ]]></title>
            <link>https://velog.io/@jiynn_12/docker-ec2-%EB%A1%9C-react-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jiynn_12/docker-ec2-%EB%A1%9C-react-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 26 Feb 2023 14:32:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🚀 배포할 프로젝트의 기술스택
🏁 <code>react</code>  + <code>node.js</code> (express) + <code>mongoDB</code> 풀스택 프로젝트 </p>
<blockquote>
<p>🤔  <strong>EC2 + docker 로 배포 선정이유</strong>
      ⇒ ec2 터미널에서 프로젝트 환경을 설치-세팅해서 배포하기보단 
          docker 로 모든 환경을 구축해서 ec2 에서 가져오기만 하는 방식이 테스트하기도 좋고 
          AWS 과 docker 공식 문서에서 설명하는 비용절감과 편리한 코드전달 등의 이유로 docker를 사용해보기로 결정!</p>
</blockquote>
</blockquote>
<blockquote>
<p>개발친구 구글링과 유투브 선생님들, 공식문서 참고해서 나름의 순서를 정리하고 시작했다.
docker + ec2 배포하기 단계</p>
<ul>
<li>dockerfile 로 이미지파일 생성 ⇒ 컨테이너로 실행해보고 테스트하기</li>
<li>docker hub 에 이미지 올리기</li>
<li>ec2 에 docker 설치 및 로그인</li>
<li>ec2 에서 docker hub 에 있는 이미지를 pull 하여 컨테이너 실행하기
<del>정리하면 쉽지만 과정은 순탄지 않았다ㅎㅎ…ㅎㅎ</del></li>
</ul>
</blockquote>
<h1 id="1️⃣-docker-이미지-생성-컨테이너-실행">1️⃣ docker 이미지 생성, 컨테이너 실행</h1>
<blockquote>
<p>빌드에 앞서 docker 설치
<a href="https://goddaehee.tistory.com/312">https://goddaehee.tistory.com/312</a> ⇒ 참고하여 설치, 터미널에 sudo -v 했을때 버전 정보가 뜬다면 잘 설치되어있는 것</p>
</blockquote>
<h3 id="dockerfile-만들기">dockerfile 만들기</h3>
<ul>
<li><p>내 프로젝트는 client/server 나뉘어져 있었고 각각의 폴더의 최상단 디렉토리에 dockerfile 을 만들어줬다</p>
</li>
<li><p>client 디렉토리에서는 추가적으로 nginx 설정 파일을 추가했다.</p>
</li>
<li><p>nginx 로 React 이미지 생성</p>
<ul>
<li><p>client:  <code>dockerfile</code>, <code>nginx.conf</code> 파일 추가하기</p>
<pre><code class="language-bash">  FROM nginx

  # root 에 app 폴더를 생성
  RUN mkdir /app

  # work dir 고정
  WORKDIR /app

  # work dir 에 build 폴더 생성 /app/build
  RUN mkdir ./build

  # host pc의 현재경로의 build 폴더를 workdir 의 build 폴더로 복사
  ADD ./build ./build

  # nginx 의 default.conf 를 삭제
  RUN rm /etc/nginx/conf.d/default.conf

  # host pc 의 nginx.conf 를 아래 경로에 복사
  COPY ./nginx.conf /etc/nginx/conf.d

  # 80 포트 오픈
  EXPOSE 80

  # container 실행 시 자동으로 실행할 command. nginx 시작함
  CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]
</code></pre>
<pre><code class="language-bash">  server {
      listen 80;
      location / {
          root    /app/build;
          index   index.html;
          try_files $uri $uri/ /index.html;
      }
  }</code></pre>
</li>
<li><p>server : <code>dockerfile</code> 파일 추가하기</p>
<pre><code class="language-bash">  # 가져올 이미지를 정의
  FROM node:16
  # 경로 설정하기
  WORKDIR /app
  # package.json 워킹 디렉토리에 복사 (.은 설정한 워킹 디렉토리를 뜻함)
  COPY package.json .
  # 명령어 실행 (의존성 설치)
  RUN npm install
  # 현재 디렉토리의 모든 파일을 도커 컨테이너의 워킹 디렉토리에 복사한다.
  COPY . .

  # 각각의 명령어들은 한줄 한줄씩 캐싱되어 실행된다.
  # package.json의 내용은 자주 바뀌진 않을 거지만
  # 소스 코드는 자주 바뀌는데
  # npm install과 COPY . . 를 동시에 수행하면
  # 소스 코드가 조금 달라질때도 항상 npm install을 수행해서 리소스가 낭비된다.

  # 3030번 포트 노출
  EXPOSE 3030:3306

  # npm start 스크립트 실행
  CMD [&quot;npm&quot;, &quot;start&quot;]
</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="docker-이미지-빌드하기-컨테이너-실행하기">Docker 이미지 빌드하기 ,컨테이너 실행하기</h3>
<ul>
<li>docker build 전 빌드하려는 디렉토리에 있는지 확인하는 것 필수</li>
</ul>
<pre><code class="language-bash"># 클라이언트단 빌드
sudo docker build -t 이미지이름 .
sudo docker run -d --name 컨테이너이름 -p 8300:80 이미지이름
# run : 실행
# -d : 백그라운드 모드
# -p 8300:80 : 포트 연결 외부노출포트:내부포트
# 컨테이너에서 사용할 이미지 이름은 위의 명령어에서 만들어준 이미지 이름과 동일해야한다. </code></pre>
<ul>
<li>빌드한 이미지로 컨테이너 실행을 했다면 docker 창에서 생성된 컨테이너를 확인할 수 있음<ul>
<li><code>sudo docker ps</code> 명령어로 현재 실행중인 컨테이너 목록을 확인할 수 있음</li>
<li><code>localhost://8300</code> 으로 들어가서 잘뜬다면 성공</li>
<li>동일하게 server 단 코드도 이미지 빌드해주고 컨테이너 실행후 테스트 해본다!
<img src="https://velog.velcdn.com/images/jiynn_12/post/863207f7-80f7-43cd-bce1-d306ff8205d4/image.png" alt=""><img style="width:500px" src="https://velog.velcdn.com/images/jiynn_12/post/2aea89bd-869d-48e6-aece-3d5717f2654c/image.png" />



</li>
</ul>
</li>
</ul>
<h3 id="docker-hub-에-push">Docker hub 에 push</h3>
<ul>
<li>생성한 이미지로 실행한 컨테이너가 잘 작동한다면 이제 docker hub에 만든 이미지를 공유해보기</li>
</ul>
<pre><code class="language-bash">sudo docker tag nginx-react zeeyoon/nginx-react:latest
# 연결하기! 생성해둔이미지이름 레파지토리에올릴이름:버전
sudo docker push zeeyoon/nginx-react:latest
# push 하기 </code></pre>
<p><img src="https://velog.velcdn.com/images/jiynn_12/post/00837930-b730-4980-889d-85fa22ba6fc2/image.png" alt=""></p>
<p>docker hub 에 올라와있는 것을 확인할 수 있음 </p>
<h1 id="2️⃣-aws-ec2-인스턴스-생성하기">2️⃣ AWS ec2 인스턴스 생성하기!</h1>
<ul>
<li><p>프리티어로 인스턴스를 생성해준다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/0e42bab3-4e84-4cd6-b4b7-90b714657c9a/image.png" alt=""></p>
</li>
<li><p>키 페어를 생성해주고 권한 설정 해주기
<img src="https://velog.velcdn.com/images/jiynn_12/post/3e0d2733-0c66-447e-a2e0-fbd318de7cfe/image.png" alt=""></p>
</li>
</ul>
<ol>
<li>프라이빗 키(.pem)를 보안된 위치인 .ssh 하위 디렉터리에 저장<pre><code>mv ~/Downloads/키페어파일 ~/.ssh/키페어파일</code></pre></li>
<li>프라이빗 키(.pem)의 권한 설정</li>
</ol>
<pre><code>chmod 400 ~/.ssh/키페어파일</code></pre><ul>
<li>인스턴스 연결하기<ul>
<li>나는 추가적으로 탄련적 IP 를 만들어서 고정 ip 를 생성했다.</li>
<li>탄련적 IP 발급받고 연결을 안하면 요금이 부과될수 있다고 하니 주의하자!
<img src="https://velog.velcdn.com/images/jiynn_12/post/e709801e-3b4c-441a-ad92-16da92b9d50d/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="인바운드-규칙-추가해주기">인바운드 규칙 추가해주기</h3>
<ul>
<li><p>EC2 &gt; 보안그룹 &gt; 인바운드편집 에서 규칙 추가해주기</p>
</li>
<li><p>클라이언트 포트는 8300 , 서버포트는 3030을 사용하도록 나누었고 인바운드 규칙에 추가해줬다.</p>
<ul>
<li>ec2 에서 pull 받은 이미지로 컨테이너를 실행할때 해당 포트로 연결해줘야한다!</li>
<li>nginx 는 8300 으로, server 는 3030 으로 연결
<img src="https://velog.velcdn.com/images/jiynn_12/post/b0e9f6e6-3ba2-4727-b95e-34e6d94c6346/image.png" alt=""></li>
</ul>
</li>
<li><p>터미널에서 ec2 접속해주기 </p>
</li>
</ul>
<pre><code class="language-bash">  ssh -i 생선한키파일.pem 사용자이름@발급받은퍼블릭ip주소</code></pre>
<ul>
<li>아래처럼 뜨면 접속성공!
<img src="https://velog.velcdn.com/images/jiynn_12/post/0a64a803-d45b-4740-abbb-c7a89555d874/image.png" alt=""></li>
</ul>
<h2 id="docker-가져오기">docker 가져오기</h2>
<ul>
<li>docker 를 사용하지 않았을때, node 설치, git 설치 및 가져올 코드 클론, nginx 설정 등등 을 여기서 해야하지만 나는 모든 환경세팅과 코드가 있는 도커 이미지가 있기 때문에 docker 를 설치해주고 docker hub 에 있는 이미지를 가져오면 된다.</li>
</ul>
<h3 id="ec2-에서-docker-설치하기">EC2 에서 docker 설치하기</h3>
<pre><code class="language-bash">sudo yum install docker -y
# 설치해주기
sudo docker login
# 로그인해주기 
sudo service docker start
# docker 시작하기</code></pre>
<h3 id="docker-이미지-pull-하고-컨테이너-실행하기">docker 이미지 pull 하고 컨테이너 실행하기</h3>
<ul>
<li>client, server 단 이미지 2개 모두 pull 하고 컨테이너를 실행해준다.<pre><code class="language-bash">sudo docker pull zeeyoon/nginx-react:latest
# 도커가 로그인 되어있다는 가정하에!
# 내가 만든 레파지토리를 Pull 해오기
sudo docker run -d --name my-react-app -p 8300:80 zeeyoon/nginx-react:latest
# 가져온 이미지를 컨테이너를 만들면서 실행시킨다. 
</code></pre>
</li>
</ul>
<h1 id="서버단-이미지도-똑같이-pull-받고-실행해준다">서버단 이미지도 똑같이 pull 받고 실행해준다.</h1>
<p>sudo docker run -t -i -p 3040:3307 zeeyoon/tdz-node</p>
<pre><code>
- 퍼블릭 주소로 접속해보니 api 연결도 잘되고 배포도 잘되었다…😭😭😭😭
![](https://velog.velcdn.com/images/jiynn_12/post/9beec1e0-56c3-4644-9189-d48f3d18338f/image.png)






&gt; 프론트엔드 개발자 취업을 하는데 내 프로젝트를 눈으로 확인할 배포사이트 하나 없는게 계속 마음에 걸려 그냥 내가 배포해버리자..^^..! 라는 가벼운 마음으로 시작했지만 역시 어려웠다.
(AWS 도 제대로 모르는데 docker 까지 하려니 ~~중간에 다놔버리고 싶었지만ㅎㅎ~~ 어찌저찌 배포했다.)

다하고 보니 사람들이 왜 배포자동화 ci/cd 에 대해 이야기하는지 필요성을 알게되었다.
코드 바뀔때마다 이 과정들을 다시 반복하는것은 너무 비효율적인것 같고 추가적으로 공부해서 적용해봐야겠다🤔


🚩참고한 자료
- https://kanlanc.com/dockerizing-react-node-app-deploying-to-ec2/
- https://docs.docker.com/build/
- https://ooeunz.tistory.com/70
- https://velog.io/@nellholic108/Docker-EC2-%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Debounce 와 throttle 은 뭐고 각각 언제 사용할까? ]]></title>
            <link>https://velog.io/@jiynn_12/Debounce-%EC%99%80-throttle-%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B3%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@jiynn_12/Debounce-%EC%99%80-throttle-%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B3%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 10 Jan 2023 13:29:42 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Debounce와 throttle은 시간이 지남에 따라 함수 실행을 허용하는 횟수를 제어하는 유사하지만 다른 기술이다.
각각의 기술에 대해 알아보고 언제 사용하는지 고찰해보자.</p>
</blockquote>
<h1 id="1-디바운싱-debounce">1) 디바운싱, Debounce</h1>
<ul>
<li>연속적으로 발생한 이벤트를 하나로 처리하는 방식이다.</li>
<li>주로 <b><u>처음</u></b>이나 <b><u>마지막</u></b>으로 실행된 함수만을 실행한다.</li>
<li>성능상의 문제를 위해 사용한다.<ul>
<li>(모든 함수를 실행하면 성능적으로 문제가 생길 수 있다!)</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jiynn_12/post/7a5cc23c-4fce-4249-88c7-a4d05e773291/image.webp" alt=""></p>
<h3 id="📂-디바운스-구현-코드">📂 디바운스 구현 코드</h3>
<blockquote>
<ul>
<li>디바운스를 어떻게 구현하는지 정말 간단한 예시로 살펴보자! </li>
</ul>
</blockquote>
<ul>
<li>타이핑이 될때마다 이벤트가 발생하는 코드에 디바운스를 적용하여 코드를 수정해보면서 이해해하고자 한다. </li>
</ul>
<pre><code class="language-jsx">function typingInput() {
    const name = nameElem.value;
    console.log(`입력된 이름: ${name}`)
}

const nameElem = document.getElementById(&#39;inputName&#39;)

nameElem.addEventListener(&quot;input&quot;, typingInput)</code></pre>
<blockquote>
<p>위의 코드는 input 태그에 타이핑 될때마다 console 이 찍히는 것을 확인할 수 있다.  </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jiynn_12/post/cef1ac2c-6c0f-48d4-8b86-8398a6a9f024/image.png" alt=""></p>
<blockquote>
<ul>
<li>타이핑할때마다 console이 찍히는 것이 아니라 1초마다 타이핑이 찍히도록 디바운싱을 적용해보았다.</li>
<li>setTimeout으로 특정 시간동안 딱한번만 함수가 실행되도록 코드를 작성한다. <ul>
<li>마지막 함수 실행후 1초후 console 이 찍힌다. </li>
</ul>
</li>
</ul>
</blockquote>
<pre><code class="language-jsx">let alertTimer
function alertWhenTypingStops() {
  // 앞선 타이머를 리셋
  // 따라서 마지막 함수가 실행 (타이핑을 멈추고선 함수실행) 
  if (alertTimer) {
    clearTimeout(alertTimer)
  }

  const name = nameElem.value
  // 타이머 시작
  alertTimer = setTimeout(() =&gt; console.log(`입력된 이름: ${name}`), 1000)
}

const nameElem = document.getElementById(&#39;inputName&#39;)

nameElem.addEventListener(&quot;input&quot;, alertWhenTypingStops)</code></pre>
<p><img src="https://velog.velcdn.com/images/jiynn_12/post/101093d7-8cf4-4454-ade1-924021fafb8a/image.png" alt=""></p>
<h3 id="🤔-대표적-사용예시">🤔 대표적 사용예시</h3>
<ul>
<li>키워드 검색 혹은 자동완성 기능에서 api 함수 호출 횟수를 최대한 줄이고 싶을때</li>
<li>사용자가 창크기 조정을 멈출때까지 기다렸다가 resizing Event 를 반영하고 싶을때</li>
</ul>
<h1 id="2-쓰로틀링-throttling">2) <strong>쓰로틀링, Throttling</strong></h1>
<ul>
<li>스로틀링은 출력을 조절한다는 의미로 이벤트를 일정주기마다 발생하도록 하는 기술</li>
<li>100ms 를 준다면 이벤트는 100ms 동안 최대 한번만 발생하게 됨</li>
<li>즉 마지막 함수가 호출된 후 일정시간이 지나기전에 다시 호출되지 않도록함<ul>
<li>일정 시간동안 딱한번만 이벤트를 발생시킴!!</li>
</ul>
</li>
<li>연이어 발생한 이벤트에 대해, 일정한 delay를 포함시켜 연속적으로 발생한 이벤트는 무시하는 방식을 뜻한다. 즉, delay 시간동안 호출된 함수는 무시한다.</li>
</ul>
<pre><code class="language-jsx">let isInThrottle
function increaseScoreDuringTyping() {
  if (isInThrottle) {
    return
  }

  isInThrottle = true

  // 타이머 세팅
  setTimeout(() =&gt; {
    const score = document.querySelector(&#39;#score&#39;)
    const newScore = parseInt(score.innerText) + 1
    score.innerText = newScore

    isInThrottle = false
  }, 500)
}

const nameElem = document.querySelector(&#39;#inputName&#39;)

nameElem.addEventListener(&quot;input&quot;, increaseScoreDuringTyping)</code></pre>
<ul>
<li>쓰로틀러를 500ms동안 작동시키고, 만약 쓰로틀러가 이벤트를 조이고 있는 경우, 해당 이벤트는 무시된다. 결과적으로 500ms 동안 최대 1번의 이벤트만이 발생!</li>
</ul>
<h3 id="🤔-대표적-사용예시-1">🤔 대표적 사용예시</h3>
<ul>
<li>스크롤에 많이 사용한다. (모든 스크롤을 기록하는것...또한 성능문제가 있음 따라서 특정 시간마다의 스크롤의 위치를 찍어주는것이 좋다)<ul>
<li>Lodash 라는 라이브러리로 이미 구현되어있는 쓰로틀링을 사용해본 경험이 있었다. 이제야 그때 그 라이브러리 왜쓰는지 제대로 알게되었다는..ㅎㅎ</li>
</ul>
</li>
</ul>
<p>참고:
<a href="https://programming119.tistory.com/241">개발자 아저씨들 힘을모아</a>
<a href="https://codefrontend.com/debounce-throttle-js-react/">https://codefrontend.com/debounce-throttle-js-react/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[개발자로 협업하기] husky 로 git hook 적용하기]]></title>
            <link>https://velog.io/@jiynn_12/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-husky</link>
            <guid>https://velog.io/@jiynn_12/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-husky</guid>
            <pubDate>Thu, 29 Dec 2022 04:32:16 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-husky-를-쓰면-뭐가-좋을까">🤔 Husky 를 쓰면 뭐가 좋을까?</h2>
<p>이전 글에서 작성한 <a href="https://velog.io/@jiynn_12/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-Eslint-prettier-husy-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0">prettier 와 ESLint 설정을 세팅</a>하고 팀별로 개발 정책을 아무리 열심히 논의해도 
실수로 팀원 한명이라도 그것을 적용하지 않는다면? 또 다시 왜 팀 규칙을 지키지 않았는지에 대한 코드리뷰를 해야하는 일이 생긴다.  </p>
<p>따라서 열심히 정한 정책들을 강제적으로 지키도록 하고 그렇지 않을 경우 merge, push 와 같은 과정에서 작업을 중단하도록 하는 <code>git hook</code> 을 활용하는 것은 좋은 방법으로 보인다. (팀이 git 으로 협업한다는 가정하에)</p>
<h3 id="git-hook-이란">git hook 이란?</h3>
<ul>
<li><p>husky에 대해 알아보기전에 <code>git hook</code> 이 무엇인지 먼저 짚고 넘어가보자 </p>
<blockquote>
<ul>
<li>Git Hooks 는 Git 과 관련한 어떤 이벤트가 발생했을 때 특정 스크립트를 실행할 수 있도록 하는 기능을 말한다. (ex. commit, push)</li>
<li>git hook 설정은 까다롭고, 모든 팀원들이 사전에 repo를 클론받고 메뉴얼하게 사전 과정을 수행해야지만 hook이 실행됨을 보장할 수 있는데 실수로라도 사전 과정을 시행하지 않는다면 hook이 실행되지 않는다.</li>
</ul>
</blockquote>
</li>
<li><p>그렇다면 여기서 또 Git Hooks 을 반드시 적용하게끔 강제할 수는 없을까? 만약 프로젝트가 모듈 의존성을 관리하기 위해 npm 을 사용하고 있다면 husky 는 모든 팀원과 공유할 수 있는 좋은 방법이다.</p>
</li>
</ul>
<h3 id="husky-란">Husky 란?</h3>
<blockquote>
<ul>
<li>git hook 설정을 도와주는 npm package</li>
</ul>
</blockquote>
<ul>
<li>번거로운 git hook 설정이 편함</li>
<li><code>npm install</code> 과정에서 사전에 세팅해둔 git hook을 다 적용시킬 수 있어서 모든 팀원이 git hook 실행이 되도록 하기가 편함</li>
</ul>
<h2 id="🛠-설치-및-적용해보기">🛠 설치 및 적용해보기</h2>
<ol>
<li><code>npm i husky --save-dev</code></li>
<li>(처음 husky 세팅하는 사람만 실행 필요) <code>npx husky install</code><ul>
<li>husky에 등록된 hook을 실제 .git에 적용시키기 위한 스크립트</li>
<li><code>.husky</code> 디렉토리가 생성되는것을 확인
<img src="https://velog.velcdn.com/images/jiynn_12/post/8d2e999a-aa73-427e-a232-ed34ec3fad44/image.png" alt=""></li>
</ul>
</li>
<li><code>package.json</code> 에 script 문 추가하기<ul>
<li>이후에 clone 받아서 사용하는 사람들은 npm install후에 자동으로 husky install 이 될 수 있도록 하는 설정</li>
</ul>
</li>
</ol>
<blockquote>
<h3 id="prettiereslint---cache">prettier/eslint --cache</h3>
<ul>
<li><code>prettier --cache --write .</code> , <code>eslint --cache .</code> <ul>
<li>모든 파일을 검사하지만 이미 검사한 파일이나 항목을 cache 에 저장하고 변경사항이 없으면
해당 파일은 검사하지 않기 때문에 실행 속도도 빠르다. </li>
</ul>
</li>
<li><code>npm run format</code>, <code>npm run lint</code> 명령어를 통해 좀더 쉽게 사용하도록 pacakge.json 스크립트 문에 추가해줍니다. </li>
</ul>
</blockquote>
<pre><code class="language-json">// package.json

    {
      &quot;scripts&quot;: {
        &quot;postinstall&quot;: &quot;husky install&quot;,
        &quot;format&quot;: &quot;prettier --cache --write .&quot;,
        &quot;lint&quot;: &quot;eslint --cache .&quot;,
      },
    }</code></pre>
<ol start="4">
<li>pre-commit, pre-push hook 추가하기 <ol>
<li><code>npx husky add .husky/pre-commit &quot;npm run format&quot;</code></li>
<li><code>npx husky add .husky/pre-push &quot;npm run lint&quot;</code></li>
</ol>
<ul>
<li>위의 명령어를 차례로 입력하면 아래와 같이 git hook 관련 파일이 생겨난것을 확인 할 수 있다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/9d68b8bb-f8bf-40dd-81bf-c0098e9aff51/image.png" alt=""></li>
</ul>
</li>
</ol>
<h3 id="git-hook이-잘되고-있는지-확인해보기">git hook이 잘되고 있는지 확인해보기</h3>
<blockquote>
<p>이제 commit을 하기전에 prettier가 코드를 설정한 포맷에 맞게 수정해주고 push 하기전 ESLint 문법을 확인해준다.</p>
</blockquote>
<blockquote>
<ul>
<li>테스트를 위해서 아래와같이 설정해주었다. </li>
</ul>
</blockquote>
<ul>
<li>ESLint 로는 console.log 는 무조건 error 로 설정</li>
<li>prettier 로는 홑따옴표를 사용하도록 설정 <ul>
<li>원하는 결과는 쌍따옴표로 작성한 코드는 홑따옴표로 바뀐채 commit 되며, push 에 실패해야한다. </li>
</ul>
</li>
</ul>
<p>commit을 하고 나서 prettier 가 잘 적용된 모습을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/c540ead6-60ac-49e5-aa0c-de3a896bd0b9/image.png" alt=""></p>
<p><code>console.log</code> 코드가 포함된 커밋
을 push 하려고 하니 ESLint 문법에 걸려 push 작업이 중단된 모습을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/46d95f57-01a3-4c90-b714-38a38db0fd39/image.png" alt=""></p>
<hr>
<p>husky 으로 git hook 을 적용하여 특정 규칙을 강제하는 방법에대해 알아보았다. 
eslint 에러 발생시에는 실행중인 script 문이 아예 종료되기 때문에 규칙을 엄격하게 error 로 한것인지 warn 으로 할것인지 고려할 필요가 있다. </p>
<ul>
<li>참고문서
<a href="https://typicode.github.io/husky/#/?id=install">husky 공식문서</a>
<a href="https://library.gabia.com/contents/8492/">가비아 라이브러리_husky로 git hook 하자</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[개발자로 협업하기] Eslint, prettier 설정하기]]></title>
            <link>https://velog.io/@jiynn_12/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-Eslint-prettier-husy-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jiynn_12/%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-Eslint-prettier-husy-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 26 Dec 2022 04:59:29 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-lintter-와-code-formatter-왜-필요할까">🤔 Lintter 와 Code Formatter 왜 필요할까?</h2>
<blockquote>
<ul>
<li>하나의 프로젝트에서 다른 개발자들이 각자 다른 코딩 스타일로 작성한다면, 제 3자 뿐만아니라 팀원끼리도 코드를 이해하는데 피로도가 생기게 됩니다.</li>
<li>따라서 어떤 형태의 문법을 지향/지양 할지, 포맷팅시 쌍따옴표를 사용할지, 몇자마다 줄바꿈 할지... 등의 여부를 고민하지 않고 코드 작성 그자체에 집중하도록 하기 위해 사용하기 위해 필요합니다.</li>
<li>이를 개인이 의식적으로 지키기 보다는 강제성을 주어 팀끼리 정한 코드 스타일을 자동화 하기 위해서 자동화 툴인 <code>ESLint</code>, <code>prettier</code> 를 사용합니다.  </li>
</ul>
</blockquote>
<p>📄 정말 간단하게 말하자면, 코딩 스타일 관련 논쟁과 리뷰 등 불필요한 에너지 소모를 줄이고자 코딩 스타일 자동화 툴을 사용하고 이를 통해 개발자들은 코드 작성 그자체에 집중하도록 해준다! </p>
<blockquote>
<ul>
<li>일반적으로 Lintting 기능은 <code>ESLint</code>에, Code Formatting은 <code>Prettier</code>에 일임하는 방식으로 사용</li>
</ul>
</blockquote>
<ul>
<li><code>ESLint</code>는 코드 자체의 문법 교정과 더불어 코드 스타일링 기능도 포함</li>
<li><code>Prettier</code>는 자동으로 코드의 스타일을 맞춰주는 보다 강력한 기능을 지원</li>
</ul>
<h2 id="1-eslint">1. ESLint</h2>
<ul>
<li>일관되고 버그를 피할수 있는 코드를 짜기위해서 만들어진 코드 분석 툴</li>
<li>작성된 코드의 구문을 분석하여 버그가 발생할 여지가 있거나, 불필요한 코드, 혹은 보안상 위험한 코드 등에 대한 경고를 띄워준다.</li>
</ul>
<h3 id="🛠-설치-및-설정">🛠 설치 및 설정</h3>
<ul>
<li><code>npm install eslint --save-dev</code><ul>
<li>CRA의 경우 내장되어 있기 때문에 따로 설치하지 않아도 됨</li>
</ul>
</li>
<li><code>npm install eslint-config-prettier --save-dev</code><blockquote>
<p><code>eslint-config-prettier</code> 설치 하는 이유! 
eslint에서 formatting 관련 rule들을 모두 해제해주는 eslint plugin 으로 prettier 와 포맷팅 설정 관련 충돌 시 이를 해결해준다.</p>
</blockquote>
</li>
<li>프로젝트의 루트 디렉토리에 <code>.eslintrc.*</code> 파일로 커스터마이징할 수 있다. <ul>
<li>package.json의 eslintConfig 필드에서도 작성 가능</li>
</ul>
</li>
</ul>
<pre><code class="language-js">{
  &quot;extends&quot;: [&quot;react-app&quot;, &quot;eslint:recommended&quot;], 
  &quot;rules&quot;: {
    &quot;no-var&quot;: &quot;error&quot;,
    &quot;no-multiple-empty-lines&quot;: &quot;error&quot;,
    &quot;no-console&quot;: [&quot;error&quot;, { &quot;allow&quot;: [&quot;warn&quot;, &quot;error&quot;, &quot;info&quot;] }],
      // 콘솔 코드 에러 (warn, error, info 는 허용)
    &quot;eqeqeq&quot;: &quot;error&quot;,
    &quot;no-unused-vars&quot;: &quot;warn&quot;,
    &quot;no-undef&quot;: &quot;warn&quot;
  }
}</code></pre>
<ul>
<li>console 관련 코드로 esLint 가 잘 적용되었는지 확인가능하다.<ul>
<li>console.log 코드에는 error 를 표시해주고, console.error 는 허용하고 있다. 
<img src="https://velog.velcdn.com/images/jiynn_12/post/3da405dd-003a-4f3f-bf38-9f1973046f33/image.png" alt=""></li>
</ul>
</li>
</ul>
<ul>
<li>위의 코드에서 extends(확장자)는 공식문서에서 eslint-all 보다는 eslint-recommended 를 권장하고 있다.<ul>
<li>node_modules 폴더의 eslint 부분에 가면 recommended와 all 파일 확인 가능하다. </li>
<li>해당 파일을 상속받아 확장하여 사용하는 방식이라고 이해하면 된다. 
<img src="https://velog.velcdn.com/images/jiynn_12/post/faaa02da-1295-4c9d-a1f8-323c9f10f52a/image.png" width="1000px"></img></li>
</ul>
</li>
</ul>
<h2 id="2-prettier">2. Prettier</h2>
<ul>
<li>코드 포맷팅 툴</li>
<li>포맷팅 룰을 커스터마이징할 수 있다.</li>
<li>코드의 포맷팅을 툴을 사용함으로서 팀원 모두가 같은 포맷팅스타일을 공유 가능</li>
</ul>
<h3 id="🛠-설치-및-설정-1">🛠 설치 및 설정</h3>
<ul>
<li><code>npm install prettier --save-dev</code></li>
<li>프로젝트의 루트 디렉토리에 <code>.prettierrc.확장자</code> 파일을 통해 설정<ul>
<li>확장자는 다양하게 지원 (JSON.YAML, JS, TOML)</li>
</ul>
</li>
</ul>
<pre><code class="language-js">module.exports = {
  printWidth: 100, // printWidth default 80 =&gt; 100 으로 변경
  singleQuote: true, // &quot;&quot; =&gt; &#39;&#39;
  arrowParens: &quot;avoid&quot;, // arrow function parameter가 하나일 경우 괄호 생략
  semi: true, //  세미콜론 사용 여부
  useTabs: false, // 탭 사용 여부
  tabWidth: 2, // // 탭 너비 
};</code></pre>
<ul>
<li>설정한 prettier 가 파일을 저장할때마다 적용하고 싶다면 VSCode 의 formatting Setting 을 바꿔줘야한다.<ul>
<li>Default Formatter를 Prettier 로 지정 (VSCode Prettier 확장 설치해야 보임)</li>
<li>Format On Save 에 체크하기
<img src="https://velog.velcdn.com/images/jiynn_12/post/d8e86cc2-8d18-45a5-9b45-d8f4204cd5c5/image.png" alt=""><img src="https://velog.velcdn.com/images/jiynn_12/post/3a314276-aac6-47f4-ad75-cc7889826f51/image.png" alt=""></li>
</ul>
</li>
</ul>
<hr>
<p>초기 세팅이 다소 번거로울수는 있지만 딱 한번만 세팅한다면 이후 적용하기 쉽고 
개발 생산성 향상에 도움이 된다는 측면에서 Linter 와 formatter 를 적용하는게 좋다. </p>
<ul>
<li>참고자료
<a href="https://prettier.io/docs/en/options.html">prettier 공식 문서</a>
<a href="https://eslint.org/docs/latest/use/getting-started">EsLint 공식 문서</a>
원티드 개발자로 일하기 강의자료 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Heroku] react+express 배포하기 (온갖 에러 해결하기)]]></title>
            <link>https://velog.io/@jiynn_12/Heroku-reactexpress-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0-%EC%98%A8%EA%B0%96-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jiynn_12/Heroku-reactexpress-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0-%EC%98%A8%EA%B0%96-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 01 Dec 2022 16:11:11 GMT</pubDate>
            <description><![CDATA[<h2 id="1-빌드하기">1. 빌드하기</h2>
<h3 id="✔️-npm-run-build">✔️ npm run build</h3>
<p>→ 작성한 react 코드를 js, html ,css 변환하는 작업을 우선 해준다. </p>
<ul>
<li>빌드된 해당 파일은 <code>server</code> 폴더로 이동시켜준다.
<img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/d8f279be-2d5a-46c6-9d6d-94524b44c32d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2022-09-25_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9.04.43.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230208%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230208T054617Z&X-Amz-Expires=86400&X-Amz-Signature=81e03e993c1237cd3726069194082df837442c2ea24e9cbd6f35ebe6b8d10e40&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA%25202022-09-25%2520%25E1%2584%258B%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25AE%25209.04.43.png%22&x-id=GetObject" alt=""></li>
</ul>
<h3 id="✔️-appjs-server-파일-코드-수정하기">✔️ app.js (server) 파일 코드 수정하기</h3>
<p>🔗 참고 : <a href="https://yohanpro.com/posts/js/node-path">NodeJS에서 Path 사용방법</a></p>
<pre><code class="language-jsx">import path from &quot;path&quot;;

app.use(express.static(path.join(__dirname, &quot;../build&quot;)));
app.get(&quot;/*&quot;, (req, res) =&gt; {
  res.sendFile(path.join(__dirname, &quot;../build/index.html&quot;));
});</code></pre>
<ul>
<li>빌드된 build 폴더로 접근 가능한 코드를 작성한 후 root 경로에 보여줄 html 파일을 연결해준다.</li>
</ul>
<hr>
<p>위의 작업을 모두 완료한 후 <code>server</code> 에서 <code>npm start</code> 실행하면
서버 실행 포트인 <a href="http://localhost:5000">localhost:5000</a> 에 들어가도 클라이언트 화면이 잘 나오는 것을 확인할 수 있음! </p>
<h1 id="2-packagejson-작성하기">2. package.json 작성하기</h1>
<ul>
<li><code>heroku</code> 는 단순히 <code>package.json</code> 파일을 참조하여 <code>npm run start</code> 를 한다고 생각하기.</li>
<li>아래의 배포 과정이 자동으로 이뤄질수 있도록 프로젝트 루트경로에 <code>package.json</code> 파일 생성후 script 코드를 작성해 줘야한다.</li>
</ul>
<blockquote>
<p> <strong>🚀 배포 과정</strong>
client 폴더로 이동 ⇒ npm ci ⇒ npm run build ⇒ 서버에 빌드폴더로 이동
server 폴더로 이동⇒ npm ci ⇒ npm start</p>
</blockquote>
<ul>
<li><p><code>npm ci</code> ⇒ 패키지들을 설치해준다.</p>
<ul>
<li>⛔️ <code>npm ci --dev</code>  라고 명시해주면 devDependencies 에 있는 의존성들도 추가로 설치해준다!</li>
</ul>
</li>
<li><p>단, <code>heroku</code> 에서는 60초 이내에 빌드를 다 끝내고 서버 코드를 실행해야함</p>
<ul>
<li><p>따라서 <code>npm start</code> 전에 미리 해당 작업을 완료시켜주는 코드를 작성한다.</p>
<pre><code class="language-json">&quot;client-build&quot;: &quot;cd client &amp;&amp; npm ci &amp;&amp; npm run build &amp;&amp; cd ../&quot;,
&quot;server-build&quot;: &quot;cd server &amp;&amp; npm ci --dev &amp;&amp; cd ../ &quot;,
&quot;heroku-prebuild&quot;: &quot;npm run client-build &amp;&amp; npm run server-build &amp;&amp; mv ./client/build ./server/build&quot;,
</code></pre>
</li>
</ul>
</li>
<li><p>잘 되었는지 테스트를 위해 실행해보기</p>
<pre><code class="language-bash">  npm run heroku-prebuild &amp;&amp; npm run start</code></pre>
<ul>
<li><p>마주친 에러 ⇒ 아마 node 로 실행하는 import문을 못읽는 것 같다,</p>
</li>
<li><p><code>package.json</code> 파일에서 <code>start</code> 스크립트문을 수정했다</p>
<pre><code>// 에러메세지
&gt; node server.js --exec babel-node
(node:62597) Warning: To load an ES module, set &quot;type&quot;: &quot;module&quot;
in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/Users/gyeongjiyun/Desktop/DevProject/seoul-cyber-punk/server/server.js:1
import &quot;dotenv/config&quot;;
^^^^^^

&quot;start&quot; : &quot;node --exec server.js babel-node&quot; // ES 오류</code></pre></li>
<li><p>만약 babel 설정을 해두었다면 start 스크립트가 <code>babel-node</code> 로 되어있는지 살펴보기</p>
<pre><code class="language-json">&quot;start&quot;: &quot;babel-node server.js&quot; // 제대로 작동
&quot;start&quot; : &quot;nodemon --exec babel-node server.js&quot; // 제대로 작동</code></pre>
</li>
<li><p>⛔️ <code>nodemon</code> 으로 빌드하여 서버에서 실행했을때 잘 작동하지만, 배포할때 <code>nodemon</code> 을 계속 사용하면 에러가 발생한다.</p>
</li>
<li><p>따라서,  <code>nodemon</code>은 개발 종속성으로 따로 스크립트문을 작성하고 배포를 위해서는 <code>babel-node</code>를 사용하기</p>
<ul>
<li><code>“start:dev&quot; : “nodemon --exec babel-node server.js”</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>  🔗 [구글링해서 찾은 stack overflow에서 참고한 답변](https://stackoverflow.com/questions/56047981/node-js-heroku-deployment-on-mac-sh-1-nodemon-not-found-npm-err-nodemon)</code></pre><h1 id="3-heroku-에-배포하기">3. heroku 에 배포하기</h1>
<ul>
<li>회원가입 및 로그인 후 <code>create a new app</code> 클릭!</li>
</ul>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/df061be3-602b-483c-9b6a-2cd568e1c303/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2022-09-25_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10.59.30.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230208%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230208T054738Z&X-Amz-Expires=86400&X-Amz-Signature=88d5fb0801965c578af18676b4cfe306582ee65847ae2452f12da7f2c7bde4a1&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA%25202022-09-25%2520%25E1%2584%258B%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25AE%252010.59.30.png%22&x-id=GetObject" alt="스크린샷 2022-09-25 오후 10.59.30.png"></p>
<p><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F315579a8-e6d1-4fce-a77f-ce089365aaf3%2F%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA_2022-09-25_%25E1%2584%258B%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25AE_11.01.04.png?table=block&id=dc06629b-ec3b-4fba-98a5-bd6f88800aee&spaceId=57e694cf-0dd1-4c7f-a515-126a6ed81298&width=2000&userId=66251f75-5997-4f2e-aa20-11861ec300d4&cache=v2" alt="스크린샷 2022-09-25 오후 11.01.04.png"></p>
<ul>
<li>github에 연결하여 배포하기<ul>
<li>빌드하는 모든 코드들은 연결된 github의 레포지토리에 모두 push 해준다.</li>
</ul>
</li>
</ul>
<p><img src="https://www.notion.so/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Ff4642698-8f95-44de-8752-da4146b8c6e3%2F%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA_2022-09-25_%25E1%2584%258B%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25AE_11.01.30.png?table=block&id=920add83-1c11-4b62-b0f1-8012a0355503&spaceId=57e694cf-0dd1-4c7f-a515-126a6ed81298&width=2000&userId=66251f75-5997-4f2e-aa20-11861ec300d4&cache=v2!%5B%5D(https://velog.velcdn.com/images/jiynn_12/post/3a8b369e-e01f-4ba2-b45d-b472a0bcbdeb/image.png)" alt="스크린샷 2022-09-25 오후 11.01.30.png"></p>
<h3 id="✔️procfile-파일-만들기">✔️<code>Procfile</code> 파일 만들기</h3>
<p>⇒ 애플리케이션 실행시 실행할 커맨드를 정의할 수 있는 파일
⇒ 프로젝트 root 디렉토리에 파일을 생성하고 <code>&lt;process&gt;: &lt;command&gt;</code>의 형태로 내용을 추가하면 <code>Heroku</code>는 이 파일을 기준으로 커맨드를 실행하게 된다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/52807d33-b076-48d5-b1c4-ea1d98ed8aea/image.png" alt=""></p>
<h1 id="4-마주친-에러-해결하기">4. 마주친 에러 해결하기</h1>
<ul>
<li>아래 블로그를 많이 참고하였다.</li>
</ul>
<p><a href="https://meirener.tistory.com/m/299">[Node.js] Heroku에서 배포하기+H10(App crashed) 에러 해결방법</a></p>
<h2 id="1️⃣-app-crashed-에러-해결하기">1️⃣ App crashed 에러 해결하기</h2>
<pre><code class="language-bash">2022-02-06T20:56:10.128489+00:00 heroku[web.1]: State changed from starting to crashed
2022-02-06T20:56:11.918417+00:00 heroku[router]: at=error code=H10 desc=&quot;App crashed&quot; method=GET path=&quot;/&quot; ...
2022-02-06T20:56:12.986375+00:00 heroku[router]: at=error code=H10 desc=&quot;App crashed&quot; method=GET path=&quot;/...</code></pre>
<ul>
<li><code>nodemon</code> 을 사용하고있는지 <code>package.json</code>파일 살펴보기</li>
<li><code>package.json</code> 에 <code>node</code> 와 <code>npm</code> 버전 명시해주기</li>
<li>최상위 경로에 <code>Procfile</code> 파일 만들어주기<ul>
<li>⛔️여기서 주의점은 콜론 앞뒤로 공백이 없어야한다!!</li>
</ul>
</li>
</ul>
<pre><code class="language-json">&quot;engines&quot;: {
    &quot;node&quot;: &quot;16.16.0&quot;,
    &quot;npm&quot;: &quot;8.11.0&quot;
  },</code></pre>
<pre><code class="language-json">web:npm start</code></pre>
<h2 id="2️⃣-mongodb-연결-실패-해결하기">2️⃣ MongoDB 연결 실패 해결하기</h2>
<ul>
<li>altas 에서 해당 db가 모든 곳에서 접근가능하지 체크하기</li>
<li>heroku 에서 Config Vars 에 해당 mongodb 주소 추가하기<ul>
<li>여기서 key 값은 코드 작성시 사용한 변수명과 동일해야한다!</li>
</ul>
</li>
</ul>
<h2 id="3️⃣-api-호출관련-에러해결하기">3️⃣ api 호출관련 에러해결하기</h2>
<ul>
<li>배포는 잘 되었으나 api 호출하는 페이지는 모두 안뜨거나 아예 하얀창이 뜬다.</li>
<li>application log 를 살펴보니 호출하는 path 에 포트 번호가 undefined 라고 뜨고있었다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/c1cf39b5-a6f4-4b87-826b-c1c1d9cb3974/image.png" alt=""></li>
</ul>
<ul>
<li>클라이언트에서 <code>api.js</code>의코드를 다시 살펴보기<ul>
<li><code>.env</code> 파일에 있는 <code>url</code> 주소를 가져다 사용하고 있었고 heroku 는 당연히 <code>.env</code> 파일을 읽지 못한다. (gitignore 에 .env 파일이 있기때문에)</li>
<li>api 호출 주소를 명시적으로 표시하는 코드로 수정하였다.</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">async function get(apiUrl) {
  const result = await axios.get(
    `${process.env.REACT_APP_BASE_URL}${apiUrl}`,
    {
      withCredentials: true,
    }
  );
.....중략
</code></pre>
<pre><code class="language-jsx">const result = await axios.get(
    `${process.env.REACT_APP_BASE_URL || &quot;https://seoul-cyber-punk.herokuapp.com&quot;}${apiUrl}`,
    {
      withCredentials: true,
    }
  );</code></pre>
<ul>
<li>코드를 수정하고 나니 모두 제대로 뜬다.</li>
</ul>
<h3 id="⛔️503-에러-해결하기">⛔️503 에러 해결하기</h3>
<ul>
<li><strong>review 페이지</strong> youtube API 호출 에러가 뜬다.</li>
<li>at=error code=H12 : Request timeout 이라는 로그가 찍혀있다.
<img src="https://velog.velcdn.com/images/jiynn_12/post/15c0aedd-987d-47b2-9748-542f96d1c40e/image.png" alt=""></li>
</ul>
<ul>
<li>Heroku는 모든 웹 요청에 대해 30초 제한 시간이 있고 새 요청이 애플리케이션 dyno로 라우팅되고 이 30초 제한 시간 내에 응답이 없으면 Heroku는 연결을 끊고 H12 오류를 보고한다는 사실을 알게되었음.</li>
<li>해결법1<ul>
<li>백그라운드 작업을 하라고 나와있다. ⇒ node.js 같은 경우는 redis 를 사용하라는 문서가 heroku 에 있다.</li>
<li><a href="https://devcenter.heroku.com/articles/background-jobs-queueing">https://devcenter.heroku.com/articles/background-jobs-queueing</a></li>
<li><a href="https://devcenter.heroku.com/articles/node-redis-workers">https://devcenter.heroku.com/articles/node-redis-workers</a></li>
<li><a href="https://stackoverflow.com/questions/69120076/fix-for-heroku-503-timeout">https://stackoverflow.com/questions/69120076/fix-for-heroku-503-timeout</a></li>
<li><a href="https://velog.io/@di-uni/Heroku-Redis-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-feat.-Nodejs">https://velog.io/@di-uni/Heroku-Redis-사용하기-feat.-Nodejs</a></li>
</ul>
</li>
<li>해결법2<ul>
<li>주기적으로 서버에 ping을 보내 처리 요청이 완료되었는지 확인</li>
</ul>
</li>
</ul>
<h1 id="배포">배포</h1>
<p><a href="https://seoul-cyber-punk.herokuapp.com/">https://seoul-cyber-punk.herokuapp.com/</a></p>
<ul>
<li>에러 하나 해결하면 다음 에러가 기다리고 있는 배포과정...정말 울고싶었지만 배포완료한 페이지를 보고나니 너무 뿌듯하다😭 할 수 있는 구글링이라는 구글링은 다해보고 온갖 유투브 영상 다 찾아봤다. 결론은 포기만 안하면 어찌되었든 다 해결된다.</li>
</ul>
<hr>
<p>📍 참고자료</p>
<p><a href="https://www.youtube.com/watch?v=ntFeJ30GE40">Heroku에 React + Express 서비스 자동 배포하기 (HM #1)</a></p>
<p><a href="https://velog.io/@kskim625/React-Express-Heroku-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0">React + Express &gt;&gt; Heroku 배포하기</a></p>
<p><a href="https://www.daleseo.com/js-babel-node/">Node.js로 ES6 코드 실행하기 (Babel)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Pug Temaplate Engine 기본문법]]></title>
            <link>https://velog.io/@jiynn_12/TIL31-Pug-Temaplate-Engine-%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@jiynn_12/TIL31-Pug-Temaplate-Engine-%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Tue, 17 May 2022 14:16:01 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📍 오늘 배운내용
SSR을 구현하는 방법으로 HTML을 미리 템플릿을 저장하는 엔진 =&gt; <code>Pug</code>, <code>ejs</code> 등 </p>
</blockquote>
<h1 id="1️⃣-템플릿-엔진이란">1️⃣ 템플릿 엔진이란?</h1>
<ul>
<li>SSR을 구현하는 방법</li>
<li>서버에서 클라이언트로 보낼 <strong>HTML의 형태</strong>를 <strong>미리 템플릿으로</strong> 저장</li>
<li>동작 시에 미리 작성된 <strong>템플릿에 데이터를 넣어서 완성된 HTML 생성</strong></li>
<li>템플릿 엔진 ⇒ 템플릿 작성 문법 , 템플릿을 HTML로 변환하는 기능 제공</li>
</ul>
<h2 id="템플릿-엔진의-종류">템플릿 엔진의 종류</h2>
<p><code>EJS</code> ⇒ HTML 과 유사한 문법의 템플릿엔진 
<code>Mustache</code> ⇒ 간단한 데이터 치환정도 제공하는 경량화 템플릿 엔진
<code>Pug</code> ⇒ 들여쓰기 표현식 이용한 간략한 표기와 레이아웃등 강력한 기능 제공</p>
<h1 id="2️⃣-pug">2️⃣ Pug</h1>
<blockquote>
</blockquote>
<p>📚  들여쓰기 표현식을 이용해 가독성이 좋고 개발 생산성 높음
HTML 잘 몰라도 문법적 실수 줄일 수 있음
<code>layout</code>, <code>include</code>, <code>mixin</code> 등 기능 제공</p>
<h2 id="1-pug-문법">1. Pug 문법</h2>
<ul>
<li>HTML 닫기 태그 없이 <code>들여쓰기</code>로 블록 구분</li>
<li><code>=</code> 을 이용해서 전달받은 <code>변수</code> 사용</li>
<li><code>id</code> 나 <code>class</code> 는 태그뒤에 이어서 바로 사용</li>
<li><code>()</code>을 이용해서 <code>attribute</code> 사용</li>
</ul>
<pre><code class="language-jade">html
    head
        title= title
    body
        h1#welcome 반갑습니다!
        a.link(href=&quot;[링크]&quot;) 링크입니다.</code></pre>
<ul>
<li><code>each~in</code> 표현식으로 주어진 배열의 값 순환하며 HTML 태그 만듦</li>
<li><code>if</code>, <code>else if</code> , <code>else</code> ⇒ 주어진 값의 조건을 확인하여 HTML 태그 만듦</li>
</ul>
<pre><code class="language-jade">each item in items
    if item.name == &#39;apple&#39;
        h1 This is Aplle
    else 
        h2= `${item.name}`</code></pre>
<h3 id="✔️-layout-기능">✔️ layout 기능</h3>
<ul>
<li><code>layout 템플릿</code>으로 사용할 파일(<code>layout.pug</code>) : <code>block</code> 을 포함한 <strong>템플릿 작성</strong> <ul>
<li>주로 html, head (폰트, css참조, title,등..) 등과같이 자주 쓰이는 태그 작성</li>
</ul>
</li>
<li>작성한<code>layout.pug</code>파일을 사용하려면 <code>extends</code> 키워드 사용<ul>
<li><code>block</code> 부분에 새로 작성한 HTML 태그가 포함된다.</li>
</ul>
</li>
</ul>
<pre><code class="language-pug">--- layout.pug ---
html
    head
        title= title
    body
        block content


--- main.pug ---
extends layout
block content
    h1 Hello World!~
    p 안녕하세요.

--- 하위에 있는 h1 태그가 레이아웃 content 부분에 들어간다...---</code></pre>
<h3 id="✔️-include-기능">✔️ include 기능</h3>
<ul>
<li>자주 반복되는 구문 미리 작성 ⇒ <code>include</code> 하여 사용</li>
<li>일반적인 텍스트 파일도 <code>include</code> 하여 템플릿에 포함 가능</li>
</ul>
<pre><code class="language-pug">
--- title.pug ---
h1= title


--- main.pug ---
extend layout
block content
    include title    --- 위에서 선언된것이 그대로 들어감 ---
    div.content
        안녕하세요
    pre
        include article.txt </code></pre>
<h3 id="✔️-mixin-기능">✔️ mixin 기능</h3>
<ul>
<li><code>mixin</code> 을 사용 ⇒ 템플릿을 함수처럼 사용할 수 있게 선언</li>
<li><code>include</code>는 값을 지정 못하지만 <code>mixin</code>은 파라미터를 지정하여 값을 넘겨받아 템플릿에 사용!</li>
</ul>
<pre><code class="language-pug">--- listItem.pug---
minxin listItem(title, name)
    tr
        td title
        td name
--- main.pug ---
include listItem
table
    tbody
        listItem(&#39;제목&#39;, &#39;이름&#39;)</code></pre>
<h2 id="2-expressjs--pug-연동하기">2. Express.js + pug 연동하기</h2>
<ul>
<li><code>app.set</code><ul>
<li>템플릿 저장되는 디렉터리 지정</li>
<li>어떤 템플릿 엔진을 사용할지 지정</li>
</ul>
</li>
<li><code>res.render</code><ul>
<li><code>app.set</code> 에 지정된 값을 이용해 화면을 그리는 기능 수행</li>
<li>첫번째 인자는 템플릿의 이름, 두번째 이름은 템플릿에 전달되는 값</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">// app.js
app.set(&#39;views&#39;, path.join(__dirname,&#39;views&#39;)); //views에 views 라는 폴더 경로설정
app.set(&#39;view engine&#39;, &#39;pug&#39;); //view engine 으로 pug를 사용하겠다.

// requist handler
//.. 생략
res.render(&#39;main&#39;, { //main =&gt; main.pug 파일을 지정
    title: &#39;Hello Express&#39;, //main.pug 파일에 전달하는 값
});</code></pre>
<h2 id="3-expressjs-의-applocals">3. Express.js 의 app.locals</h2>
<ul>
<li>express.js 의 <code>app.locals</code><ul>
<li><code>render</code> 함수에 전달되지 않은 값이나 함수 사용 가능</li>
<li>템플릿에 전역으로 사용될 값을 지정하는 역할</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">app.locals.appName = &quot;Express&quot;;</code></pre>
<pre><code class="language-jsx">h1 = appName
// &lt;h1&gt;Express&lt;/h1&gt; </code></pre>
<h1 id="3️⃣-express-generator-사용시-템플릿-엔진-지정">3️⃣ express-generator 사용시 템플릿 엔진 지정</h1>
<pre><code class="language-bash">express --view=pug [프로젝트명] 

// ejs 로 하고싶다면
// express --view=ejs [프로젝트명]</code></pre>
<ul>
<li><code>express-generator</code> 는 기본적으로 <code>jade</code> 라는 템플릿 엔진 사용</li>
<li><code>jade</code> 는 <code>pug</code> 의 이전 이름 , 최신 지원을 받기위해선 템플릿 엔진을 <code>pug</code>로 지정 해야 함</li>
<li><code>--view</code> 옵션 사용 ⇒ 템플릿 엔진을 지정</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[CORS 에러 ]]></title>
            <link>https://velog.io/@jiynn_12/TIL31-CORS-%EC%97%90%EB%9F%AC</link>
            <guid>https://velog.io/@jiynn_12/TIL31-CORS-%EC%97%90%EB%9F%AC</guid>
            <pubDate>Mon, 16 May 2022 15:17:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>오늘 배운 내용
📍 프로젝트를 진행하다보면 CORS 라는 에러를 자주 맞닥뜨린다고한다. (당황하지말고 잘 처리하자)
📍 아직 프로젝트 시작 전이라 잘 와닿지 않지만 알아만 두자! </p>
</blockquote>
<h1 id="cors-cross-origin-resource-sharing">CORS, Cross-Origin Resource Sharing</h1>
<blockquote>
<p>📚 <code>CORS</code> 는 한 도메인 또는 Origin의 웹 페이지가 다른 도메인 (도메인 간 요청)을 가진 리소스에 액세스 할 수 있게하는 보안 메커니즘
<code>CORS</code> 는 서버와 클라이언트가 정해진 헤더를 통해 서로 요청이나 응답에 반응할지 결정하는 방식으로 <strong>CORS</strong> 라는 이름으로 표준화 되었다. <code>CORS</code> 는 최신 브라우저에서 구현된 동일 출처 정책(<code>SOP</code> same-origin policy) 때문에 등장했다.</p>
<blockquote>
<p>정확하게 말하자면 요청을 <code>CORS</code>가 보내고 있는데 <code>SOP</code>가 이걸 막아서 나는 오류⛔️
(우리의 브라우저에 저장된 쿠키(인증관련)를 악용할 수도 있기 때문에)
아래의 영상은 <code>SOP</code> 가 그 요청을 왜 막고 있는지 <code>CORS</code> 가 무엇인지 자세히 설명해주신다.
<a href="https://www.youtube.com/watch?v=bW31xiNB8Nc">🔥 얄팍한 코딩사전님의 CORS관련 유투브</a></p>
</blockquote>
</blockquote>
<h3 id="어떤-요청이-cors-를-사용하는가">어떤 요청이 CORS 를 사용하는가?</h3>
<ul>
<li>XMLThhpRequest, Fetch API 호출</li>
<li>웹 폰트 (@font-face에서 교차 도메인 폰트 사용 시)</li>
<li>WebGL 텍스쳐 등...</li>
</ul>
<h2 id="간단하게-확인해보기">간단하게 확인해보기</h2>
<ul>
<li><p>codepen 웹사이트에서 내가 사용하는 코드(fetch)를 사용하면 <code>CORS</code> 에러가 난다.</p>
<ul>
<li>codepen (외부의 사이트) ⇒ ip와 local 모두 다름</li>
<li><a href="http://localhost:3000">localhost:3000</a> ⇒ 웹사이트 서버. 우리는 3000번 포트</li>
<li>우리의 클라이언트 역시. (localhost:3000)이 요청하고 응답해야함</li>
</ul>
<blockquote>
<p><strong>포트는 데이터의 통로라고 할 수 있다.</strong></p>
</blockquote>
</li>
</ul>
<h2 id="해결방법">해결방법</h2>
<blockquote>
<p>접근제어 시나리오 예제가 상세히 설명되어 있다.
<a href="https://developer.mozilla.org/ko/docs/Web/HTTP/CORS">https://developer.mozilla.org/ko/docs/Web/HTTP/CORS</a>
시나리오 예제중 단순 요청 부분을 참고하기 </p>
</blockquote>
<h3 id="에러-메세지-살펴보기">에러 메세지 살펴보기</h3>
<blockquote>
<p>codepen의 웹사이트가 나의로컬의 컨텐츠를 호출하려고 하는 과정에서 난 오류</p>
<blockquote>
<pre><code>Access to fetch at &#39;http://127.0.0.1:3000/expost/getlist&#39; 
from origin &#39;https://cdpn.io&#39; has been blocked by CORS policy: 
No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource.</code></pre></blockquote>
</blockquote>
<pre><code>- 에러 메세지에 의하면 `origin` 으로부터 접근제한이 되었다



- HEAD 의 `origin` 부분을 바꿔주면 된다.
  - 방법1. `res.setHeader()` 으로 header정보를 응답해주기
  - 방법2. `cors` 라는 모듈을 사용하기 (`npm i cors`)

```jsx
const cors = require(&#39;cors&#39;);
app.use(cors({
  origin: &#39;*&#39;,
  methods: [&#39;GET&#39;, &#39;POST&#39;, &#39;DELETE&#39;, &#39;UPDATE&#39;, &#39;PUT&#39;, &#39;PATCH&#39;]
  // 보통은 골라서 허용함
}))</code></pre><ul>
<li><p><strong>codePen</strong> 에서도 잘 뜨는것을 확인할 수 있다.
<img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/34df2d39-ee97-4ea3-81db-024551bc03b7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2022-05-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1.25.28.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220516%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220516T143713Z&X-Amz-Expires=86400&X-Amz-Signature=af11d6b3a9d456d9893d584ac8b7327bec0362106cb055460b02b78dae85ebcf&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA%25202022-05-16%2520%25E1%2584%258B%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25AE%25201.25.28.png%22&x-id=GetObject" alt=""></p>
<hr>
<p>MDN 문서가 정말 친절하게 설명해준다. <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/CORS">CORS MDN 문서</a>
CORS 에러를 만난다면 필요한 부분을 찾아서 정독하자 </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node] node 실행시 import 문 에러 해결하기 (babel)]]></title>
            <link>https://velog.io/@jiynn_12/TIL30</link>
            <guid>https://velog.io/@jiynn_12/TIL30</guid>
            <pubDate>Sun, 15 May 2022 15:02:15 GMT</pubDate>
            <description><![CDATA[<p>⛔️ 백엔드 부분 코드를 작성하려고 보니 <code>import</code>문, <code>process.env</code> 문 등 esm 문법을 사용할 수 없다는 에러가 계속 발생
찾아보니 바벨설정을 해줘야한다고한다.</p>
<pre><code># 에러메세지
Uncaught : Error : require() of ES Module
# 혹은
SyntaxError: Cannot use import statement outside a module</code></pre><h2 id="1-bable-이란">1. bable 이란?</h2>
<ul>
<li><p>우선 babel 이 무엇인지 이 설정을 왜 해줘야하는지 의문이 생김</p>
<blockquote>
<p> 아주 간단하게 <code>Bablel</code> 은 <code>JSX</code> 코드를 브라우저가 알아보도록 변환시켜 주는 역할을 한다! 
<img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f01493cf-eafd-4e09-a53c-2ee152f53bdf/_2022-08-01__3.34.01.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20221201%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20221201T154431Z&X-Amz-Expires=86400&X-Amz-Signature=e89290481d9e4e0c08fa9e591f14cacd30f0ada4a57e7f6655526d0f88395e28&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA%25202022-08-01%2520%25E1%2584%258B%25E1%2585%25A9%25E1%2584%2592%25E1%2585%25AE%25203.34.01.png%22&x-id=GetObject" alt="스크린샷 2022-08-01 오후 3.34.01.png"></p>
<ul>
<li>위의 JSX 코드를 아래의 코드로 변환해주기 위해 Babel을 사용한다!</li>
</ul>
</blockquote>
<ul>
<li>Babel 은 JSX로 적은 코드를 브라우저가 이해할 수 있는 형태로 바꿔준다.</li>
<li>브라우저는 JSX를 모르기때문에 invalid 하다고 생각한다.</li>
</ul>
</li>
<li><p>바벨 설정을 통해 코드를 common JS로 변환해주고 확장자(.js, .ts, ... )를 작성해주지 않아도 된다. 하지만 생긴것만 import, export 문이지 사실은 common JS를 사용하고 있는셈</p>
</li>
</ul>
<h2 id="2-바벨-설정해주기">2. 바벨 설정해주기</h2>
<ul>
<li>아래의 패키지들을 설치해준다. <pre><code>npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime    #종속X
npm install --save-dev babel-plugin-transform-remove-console # build 할 때 console.log 제거
</code></pre></li>
</ul>
<pre><code>
- `babel.config.json` 파일 생성하기
</code></pre><p>{
  &quot;presets&quot;: [
    [
      &quot;@babel/preset-env&quot;,
      {
        &quot;targets&quot;: {
          &quot;node&quot;: &quot;current&quot;
        }
      }
    ]
  ],
  &quot;plugins&quot;: [&quot;@babel/plugin-transform-runtime&quot;]
}</p>
<p>```</p>
<ul>
<li>에러없이 잘 작동하는 것을 확인! </li>
</ul>
<h2 id="🏁-결론">🏁 결론</h2>
<p>바벨 설정을 해줘야 import 문 같은 ESM 문법을 사용할 수 있다.
CommonJS 의 문제점이 무엇인지 왜 ESM 모듈 시스템을 써야하는지 아래 동영상에서 자세히 설명해준다!
🚀 근본적인 이야기 : <a href="https://www.youtube.com/watch?v=mee1QbvaO10">https://www.youtube.com/watch?v=mee1QbvaO10</a></p>
<p>CRA 로 프론트단 react 프로젝트를 했을때는 CRA가 알아서 바벨설정을 해주기때문에 마주치지 못했던 에러였지만 이 기회에 바벨이 무엇인지 이러한 설정이 왜 필요한지 공부하는 계기가 되었음! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JS의 truty와 falsy ]]></title>
            <link>https://velog.io/@jiynn_12/JavaScript-JS%EC%9D%98-truty%EC%99%80-falsy</link>
            <guid>https://velog.io/@jiynn_12/JavaScript-JS%EC%9D%98-truty%EC%99%80-falsy</guid>
            <pubDate>Mon, 09 May 2022 01:05:19 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>JS에서 참같은 값과 거짓같은 값에대해 알고있자</p>
</blockquote>
<h1 id="1️⃣-js는-자동-형변환한다-type-conversion">1️⃣ JS는 자동 형변환한다. (Type conversion)</h1>
<ul>
<li><strong><code>===</code></strong>, 일치연산자</li>
<li><strong><code>==</code></strong> , <strong>동등연산자</strong> =&gt; <strong><em>되도록이면 사용하지 말기</em></strong>, <del>의도치않게 일치한다고 여길수도 있기때문에</del></li>
</ul>
<pre><code class="language-jsx">const a = 1
const b = &#39;1&#39;

console.log(a === b) //false
console.log(a == b) //true , 형변환이 생겼기 때문에 
console.log(typeof a.toString())</code></pre>
<h2 id="📚-truty-참-같은-값-">📚 Truty (참 같은 값 )</h2>
<ul>
<li>비어있는 객체데이터 포함 모든객체데이터, 문자열 ,숫자,...<ul>
<li><code>true</code></li>
<li><code>{}</code> , <code>[]</code> : 빈배열, 빈객체도 Truty</li>
<li><code>숫자</code> : 1, 2, -12, &#39;3.14&#39;, 양수,음수,실수 모두 Truty</li>
<li><code>문자열</code>: <code>&#39;false&#39;</code> , 빈문자열을 제외한 모든 문자열</li>
</ul>
</li>
</ul>
<h2 id="📚-falsy거짓-같은-값">📚 Falsy(거짓 같은 값)</h2>
<ul>
<li>빈 문자열, 의도적으로 비어있는 ,의도하지않은 빈 데이터, 0, Not a Number데이터<ul>
<li><code>false</code></li>
<li><code>&#39;&#39;</code></li>
<li><code>null</code></li>
<li><code>undefined</code></li>
<li><code>0</code>, <code>-0</code></li>
<li><code>NaN</code></li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">if(&#39;false&#39;) { //true값으로 여긴다 문자데이터로 여기기때문에
  console.log(123)
}

//NaN , 숫자데이터이지만 not a number인
console.log(1 + undefined)// NaN</code></pre>
<hr>
<h2 id="2️⃣-truty-값과-falsy-값을-이용해-반복문의-조건식-조건문에-사용">2️⃣ truty 값과 falsy 값을 이용해 반복문의 조건식, 조건문에 사용</h2>
<ul>
<li>0은 false이기 때문에 queue의 배열의 길이가 0이 되는 순간 while문을 탈출한다.</li>
</ul>
<pre><code class="language-jsx">let queue = [1,2,3,4,5,6,7]
let K = 3;

while(queue.length) {
  cnt++;
  if(cnt === K) {
    answer += queue.shift();
    if(queue.length) {
      answer += &quot;, &quot;;
      cnt = 0;
    } else {
      answer += &quot;&gt;&quot;;
    }
  } else {
    queue.push(queue.shift());
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JavaScript의 내장객체]]></title>
            <link>https://velog.io/@jiynn_12/TIL15</link>
            <guid>https://velog.io/@jiynn_12/TIL15</guid>
            <pubDate>Mon, 25 Apr 2022 01:04:58 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>JavaScript </p>
</blockquote>
<h1 id="1️⃣-자바스크립트-내장객체">1️⃣ 자바스크립트 내장객체</h1>
<ul>
<li>여러 용도에 활용하는 객체를 내장하고 있다.</li>
<li>숫자 다루기, 문자 다루기, 날짜 다루기, JSON 객체 다루기 등에 유용한 객체를 제공한다.</li>
</ul>
<h2 id="1-globalthis">1. globalThis</h2>
<ul>
<li>전역 객체를 지칭하는 변수</li>
<li>전역 객체는 환경에 따라 다르다</li>
<li>환경별 차이를 통일하여 하나의 변수로 서로 다른 전역 객체를 가르키게 한다.</li>
<li><strong>브라우저 환경에서 window 객체와 같음</strong></li>
</ul>
<h2 id="2-window">2. Window</h2>
<ul>
<li><strong>전역스코프에 선언된 <code>변수</code></strong>는 모두 <code>window</code>의 <code>property</code>가 된다.</li>
<li>DOM document 를 포함하는 창을 나타내는 객체</li>
<li>현재 창의 정보를 얻거나 창을 조작한다.</li>
</ul>
<h2 id="3-document">3. document</h2>
<ul>
<li>브라우저에 로드된 웹페이지</li>
<li>문서의 title, URL등의 정보를 얻어옴</li>
<li><code>element</code> <strong>생성, 검색 등의 기능</strong> 제공</li>
<li><code>createElement</code>, <code>createTextNode</code>는 동적으로 원소를 생성하고 이를 이용해 자바스크립트만으로 원소를 구성할 수 있음</li>
</ul>
<h2 id="4-number-nan">4. Number, NaN</h2>
<ul>
<li>자바스크립트의 number 원시타입(primitive type, 기본형)을 감싸는 객체</li>
<li>유의미한 상수값, 숫자를 변환하는 메서드 등을 제공</li>
<li>NaN (=Not a Number) 를 나타내는 객체 (할당할 수 있음)</li>
<li>isNaN() ⇒ NaN이 되는지를 검사</li>
</ul>
<pre><code class="language-jsx">Number(&#39;123&#39;) //=&gt; 숫자 123
let str = &#39;abc&#39;
function checkNumber (x) {
    if(isNaN(x)) return 0 //x가 not a number 즉 숫자가 아니라면 return 0
    else return x * 2;
}</code></pre>
<h2 id="5-math">5. Math</h2>
<ul>
<li>기본적인 수학 연산 메서드, 상수를 다루는 객체</li>
<li>BigInt 타입과 호환되지 않고, Number 타입만을 인자로 다룬다.</li>
</ul>
<h2 id="6-date">6. Date</h2>
<ul>
<li>특정 시점의 날짜를 표시하기 위한 객체.</li>
<li>날짜와 관련된 작업을 하기위한 여러 메서드를 포함</li>
</ul>
<pre><code>    Date.prototype.getFullYear - 년도
    Date.prototype.getMonth - 월 - 1 (1월은 0, 2월은 1, ...)
    Date.prototype.getDate - 일
    Date.prototype.getHours - 시
    Date.prototype.getMinutes - 분
    Date.prototype.getSeconds - 초</code></pre><pre><code class="language-jsx">Date.getDay();
// 일요일(0) - 토요일(6)
// Date는 형태는 2021/4/12
Date.getMonth()
Date.getDate()
Date.gethour()

date.setDate();  //시간설정, 설정시 월 변경 등의 시간 변환은 Date객체가 처리
date.toDateString(); // 메서드는 특정 포맷의 문자열을 반환한다. 

Date.getTime() // 시간을 밀리초 단위로 반환(1970.1.1시점 이후부터)
Date.fromNow() // 주어진 시간이 현재로부터 며칠이나 흘렀는지 계산</code></pre>
<blockquote>
<p>new Date()로 Date 객체를 생성하면, 객체를 생성한 시점의 시간 정보만을 얻을 수 있음
실시간으로 현재 시간의 밀리초를 얻기 위해선 정적 메서드인 Date.now()를 활용!</p>
</blockquote>
<blockquote>
<p>Date 객체는 기본적으로 현재 컴퓨터의 시간대(타임존) 정보를 기반으로 생성
따라서 Date 객체를 생성하면, 현재 시간대가 기준 UTC 시간대에서 얼마나 벗어나 있는지를 알 수 있음</p>
</blockquote>
<h2 id="7-string-json">7. String, JSON</h2>
<ul>
<li><p>자바스크립트의 문자열 원시타입(기본형)의 래퍼객체</p>
</li>
<li><p>문자열을 조작하기 위한 여러 메서드를 포함</p>
</li>
<li><p>JSON - JSON 객체와 관련된 메서드를 담은 객체</p>
<ul>
<li>String</li>
<li>trim(), toUpperCase(), includes() ⇒ true,false반환</li>
<li>split(), replace(), indexOf()⇒ 찾을 요소 인덱스를 반환, 없을시 -1반환</li>
</ul>
</li>
<li><p>JSON</p>
<ul>
<li><p>JSON.stringfy() : 주어진 객체를 JSON 문자열로 만든다.</p>
</li>
<li><p>JSON.parse(): 주어진 JSON문자열을 자바스크립트에 맞는 결과 객체로 만든다.</p>
<pre><code class="language-jsx">  JSON.stringify({name : &quot;Daniel&quot;, age: 12 })
  // &#39;{&quot;name&quot; : &quot;Daniel&quot;, &quot;age&quot; : 12 }&#39;

  JSON.parse(&#39;{&quot;name&quot; : &quot;Daniel&quot;, &quot;age&quot; : 12 }&#39;)
  // {name : &quot;Daniel&quot;, age: 12}
</code></pre>
</li>
</ul>
</li>
</ul>
<h1 id="그외">그외</h1>
<p><code>instanceof</code></p>
<pre><code class="language-jsx">//x는 와 z 사이 
x &gt;= &quot;a&quot; &amp;&amp; x &lt;= &quot;z&quot;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JS심화-실행컨텍스트, this, 클로저]]></title>
            <link>https://velog.io/@jiynn_12/TIL14</link>
            <guid>https://velog.io/@jiynn_12/TIL14</guid>
            <pubDate>Mon, 25 Apr 2022 01:04:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📍 오늘배운내용</p>
</blockquote>
<ul>
<li>실행컨텍스트 (및 JS의 코드실행순서)와 this 에대해 알아보자</li>
<li>클로저라는 개념 모를때는 우리가 사용하고 있었지만 개념으로 공부하니까 어려웠다! 
=&gt; 정말 간단하게 말하자면 함수가 종료되면 함수내부의 변수는 사라지지만 외부로 전달하여 사용가능한것을 클로저라고 하자</li>
<li>일반함수와 화살표함수가 가르키는 <code>this</code>를 알아두기! </li>
</ul>
<h1 id="1️⃣-실행컨텍스트--execution-context">1️⃣ 실행컨텍스트 , Execution Context</h1>
<h2 id="1-자바스크립트-함수가-실행되는-과정">1. 자바스크립트 함수가 실행되는 과정</h2>
<blockquote>
<p>자바스크립트 엔진은 코드가 없어도 3가지 변수를 포함해서 실행환경(실행컨텍스트)를 초기화한다.</p>
</blockquote>
<ol>
<li><code>this</code><ul>
<li>this 포인터의 경우, 글로벌 스코프에서는 window(global)를 가르킨다.</li>
</ul>
</li>
<li>변수들 (<code>Variable Object</code>)</li>
<li><code>Scope chain</code><ul>
<li>scope는 코드가 현재 실행되는 환경, 맥락을 의미한다.<blockquote>
<blockquote>
<p>📍 자바스크립트가 실행되면 <code>전역 실행 컨텍스트</code>(Global Exeuction Context)가 만들어지고 함수가 실행될때는 <code>함수 실행 컨텍스트</code> (Function Execution Context)가 만들어진다.
📍 함수가 실행되면 함수 스코프에 따라 환경이 만들어지고 this, 변수, 스코프체인이 형성된다. 함수 실행이 끝나면 스코프 체인을 따라 글로벌 환경에 도달한다. </p>
</blockquote>
</blockquote>
</li>
</ul>
</li>
</ol>
<ul>
<li><p>어떤 코드도 없는경우(실행하는 함수)  : 예를들어 html/css로만 구성된 웹을 브라우저에 실행할때</p>
<pre><code class="language-jsx">  console.log(this); //window </code></pre>
<ul>
<li><code>this</code> : window</li>
<li>변수들 (<code>Variable Object</code>) : {}</li>
<li><code>Scope chain</code> : []</li>
</ul>
</li>
<li><p>특정 함수가 존재하고 실행되는 경우</p>
<pre><code class="language-jsx">  function fac() {
      let a = 100;
      let b = 200;

      function mul (first, second) {
          return first * second;
      }
      return mul(a,b)
  }

  //fac 함수 실행
  fac();</code></pre>
<table>
<thead>
<tr>
<th>Executive Context</th>
<th>fac()</th>
<th>mul()</th>
</tr>
</thead>
<tbody><tr>
<td>this</td>
<td>undefined (strict mode - js 실행될때 정해진 mode..)</td>
<td>undefined</td>
</tr>
<tr>
<td>Variable Object</td>
<td>{ a:100, b:200, mul:function{..} }</td>
<td>{ first : 100, second : 200}</td>
</tr>
<tr>
<td>Scope chain</td>
<td>global</td>
<td>fac, global</td>
</tr>
</tbody></table>
</li>
<li><p><code>mul()</code>은 실행이 끝나면 해당 실행컨텍스트는 모두 삭제되고 <code>fac</code> 스코프로 돌아간다.</p>
</li>
<li><p><code>fac</code> 실행이 끝나면 원래 모두 삭제되고 실행되는 코드가 없던 상태로 돌아감(<code>global</code> 스코프로 돌아감!)</p>
</li>
</ul>
<h2 id="2-실행-컨텍스트">2. 실행 컨텍스트</h2>
<ul>
<li><p>실행 컨텍스트 혹은 실행맥락은 자바스크립트 코드가 실행되는 환경</p>
</li>
<li><p>코드에서 참조하는 변수, 객체(함수포함),this 에 대한 레퍼런스가 있다.</p>
</li>
<li><p>실행 컨텍스트는 전역에서 시작해서 함수가 호출될때 <code>스택</code>에 쌓이게 된다.</p>
</li>
<li><p>실행 컨텍스트 스택(<code>call stack</code>)</p>
<ul>
<li><p>스택의 자료구조 처럼 <strong>가장 나중에 실행된 함수</strong>의 실행컨텍스트가 <strong>가장 먼저 제거</strong>된다!</p>
<pre><code class="language-jsx">let a =20;
function func() {
  let b= 30;
  function check(v) {console.log(v)}
  function func2() {
      let c = 40;
      check(a+b+c)//=========== 4
  }
  func2()       //=========== 3
}
func()       //============== 2

      //====================1</code></pre>
</li>
<li><p><code>Global</code> : <code>a</code> , <code>console</code>(전역객체이기 때문에), <code>func함수</code></p>
</li>
<li><p><code>func 함수</code> : <code>b</code>, <code>check함수</code>, <code>func2함수</code> (전역에서 <code>func()</code> 에 의해 실행)</p>
</li>
<li><p><code>func2 함수</code> : <code>c</code>  (전역 &gt; <code>func()</code> 내에서 <code>func2()</code> 에의해 실행)</p>
  <div style="color:blue">
  - check(a+b+c) 호출 <br>
  - 스코프체인을 따라서 해당 변수를 찾아나섬 (스코프 체이닝!) <br>
  - ⇒ `a`는 `전역`에서 `b`는 `func`함수스코프에서 `c`는 `현재 스코프안` 에서 찾음
    </div></li>
<li><p><code>check 함수</code> : <code>v</code> (전역 &gt; func() &gt; func2내에서 <code>check(a+b+c)</code> 에 의해 실행)</p>
</li>
</ul>
</li>
</ul>
<hr>
<h1 id="2️⃣-this-가-가르키는것">2️⃣ this 가 가르키는것</h1>
<h2 id="1-dynamic-binding">1. dynamic binding</h2>
<ul>
<li><p>함수 호출되는 상황은 4가지 상황</p>
<ul>
<li><p>함수 호출, 메서드 호출(객체의 메서드), 생성자 함수 호출(new 키워드), 간접호출(call, apply 등)</p>
</li>
<li><p><code>call</code> 과 <code>apply</code> 는 기본적인 <code>function</code> 의 객체</p>
</li>
<li><p>그외 콜백함수의 호출이 있음 (특정 동작이후로 불려지는 함수, 다른 함수의 인자로 보내지는 함수)</p>
<p>  <img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f6916b8d-a072-4e82-a594-6958fe42c374/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2022-04-21_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11.16.17.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220504%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220504T030450Z&X-Amz-Expires=86400&X-Amz-Signature=24c25ba4117725bef9d7e82aea349c71614235a3dce39ed68dfab75ec94b8983&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22%25E1%2584%2589%25E1%2585%25B3%25E1%2584%258F%25E1%2585%25B3%25E1%2584%2585%25E1%2585%25B5%25E1%2586%25AB%25E1%2584%2589%25E1%2585%25A3%25E1%2586%25BA%25202022-04-21%2520%25E1%2584%258B%25E1%2585%25A9%25E1%2584%258C%25E1%2585%25A5%25E1%2586%25AB%252011.16.17.png%22&x-id=GetObject" alt="스크린샷 2022-04-21 오전 11.16.17.png"></p>
</li>
</ul>
</li>
<li><p><code>bind</code>, <code>apply</code>, <code>call</code> 등으로 <code>this</code> 가 가르키는 것을 조작할 수 있다!</p>
<ul>
<li><code>bind(p)</code> : <code>this</code>가 <code>p</code> 객체를 가리키도록</li>
</ul>
</li>
</ul>
<h2 id="2-화살표-함수의-this-🆚-일반함수의-this-🆚-콜백함수-this">2. 화살표 함수의 this 🆚 일반함수의 this 🆚 콜백함수 this</h2>
<pre><code class="language-jsx">let o = {
  name: &quot;zeeyoon&quot;,
  f1: () =&gt; {
    console.log(&quot;[f1] this :&quot;,  this);
  },
  f2: function () {
    console.log(&quot;[f2] this :&quot;,  this);
  },
};

o.f1(); // 화살표함수 global
o.f2(); // 일반함수  a

setTimeout(o.f1, 10); //콜백함수 global
setTimeout(o.f2, 20); //콜백함수 global</code></pre>
<p>화살표 함수와 콜백함수로 함수를 실행할때는 기존의 맥락(this)를 전역 컨텍스트의 맥락으로 바꾼다.</p>
<h3 id="📍-화살표-함수와-일반함수의-this">📍 화살표 함수와 일반함수의 this</h3>
<blockquote>
<ul>
<li>화살표 함수의 this<ul>
<li>항상 상위 스코프의 this를 가르킨다.</li>
<li>화살표 함수의 this는  정해지면 apply, bind, call 로도 조작할 수 없음</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li>일반함수의 this ⇒ 새롭게 생성된 실행 컨텍스트를 가르킴 (함수가 만들어진 환경의 스코프)<ul>
<li>메소드와 함수는 다르다! (간단하게 점 혹은 대괄호의 여부로 구분하기 &gt; 있다면 메소드) <pre><code>1. **함수 실행 시에는, 전역(window)객체**를 가리킨다.
2. **메소드 실행** 시에는 **메소드를 소유하고 있는 객체**를 가리킨다.
3. **생성자 실행 시**에는 **새롭게 만들어진 객체**를 가리킨다.</code></pre></li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">    const fac = {
      method() {
        console.log(&quot;context : &quot;, this); //fac
        let func1 = function () {
          console.log(&quot;[일반함수 func2] this : &quot; , this); 
        }
        let func2 = () =&gt; 
          console.log(&quot;[화살표함수 func2] this : &quot; , this);

        func1(); // global
        func2(); // fac 화살표 함수이기때문에 호출된 위치인 method
      },
    };

    fac.method();</code></pre>
<ul>
<li><code>func1</code> 이 <code>global을</code> 가르키는 이유는?(⭐️⭐️⭐️⭐️)<ul>
<li><code>func1</code> 함수가 실행되면서 <strong>새로운 컨텍스트를 생성</strong>하는데 바인딩된 컨텍스트가 없으므로 <code>this</code>는 <code>gobal</code>을 가르킨다.</li>
</ul>
</li>
<li><code>method</code> 내의 <code>context: this</code> 가 <code>fac</code> 인 이유는 <code>global</code> 에서 호출했을때 <code>fac.method()</code> 에 의해 <code>global</code> &gt; <code>fac()</code> &gt; <code>method()</code> 의 순서로 새로운 컨텍스트를 생성했기 때문임. </li>
</ul>
<h2 id="3-this를-조작하는-경우">3. this를 조작하는 경우</h2>
<pre><code class="language-jsx">let bio = {
  name: &quot;zeeyoon&quot;,
  hello : function() {
    console.log(&quot;안녕 내이름은 &quot;, this.name);
  },
};

bio.hello();    
//안녕 내이름은  zeeyoon (hello 의 this는 bio)

//콜백함수 &gt; 전역객체를 바인딩한다
setTimeout(bio.hello, 10);   
//안녕 내이름은  undefined (hello의 this는 global)
setTimeout(bio.hello.bind(bio), 20);  //안녕 내이름은  zeeyoon  
// (hello의this를 global에서 bio 로 바인딩)</code></pre>
<h1 id="3️⃣-클로저--closure">3️⃣ 클로저 , Closure</h1>
<p>외부로 전달하는 방법</p>
<ul>
<li>전역 변수에 할당하기</li>
<li>return 값으로 외부로 전달하기</li>
<li>자바스크립트에서 함수는 일급 객체 (first-class object)<ul>
<li><code>일급객체</code>란, 다른 <strong><code>변수</code>처럼</strong> 대상을 다룰 수 있는것</li>
<li>즉 JavaScript 에서 <strong><u>함수는 변수처럼 다룰 수 있다.</u></strong></li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">    var f = function() {}
    // f 는 함수객체 -&gt; 변수처럼 다룰 수 있음 

    const Bio = (name) =&gt; {
        const hello = () =&gt; console.log(&quot;안녕 내이름은 &quot;, name);

      return { hello } //객체처럼 
        //return hello
        //return hello()
    }

    const person = Bio(&#39;zeeyoon&#39;) //person 이라는 객체에 Hello 라는 함수 프로퍼티를 넣은것 
    person.hello();
    //bio(&#39;zeeyoon&#39;)();
    //bio(&#39;zeeyoon&#39;);
</code></pre>
<h3 id="closure-는-함수의-일급객체-성질을-이용한다-js">Closure 는 함수의 일급객체 성질을 이용한다 (JS)</h3>
<ul>
<li>함수가 생성될 때, <strong>함수 내부에서 사용되는 변수들이 외부에 존재하는 경우</strong> 그변수들은 함수의 스코프에 저장된다. (⇒ 원래는 실행이 끝나면 실행 컨텍스트가 삭제되기 때문에 변수도 존재하지 않는데 존재하는 경우)</li>
<li>함수를 통해 외부로 그 값(변수)를 전달했을때 클로저가 가능하다!</li>
<li>함수와 함수가 사용하는 변수들을 저장한 공간을 클로저(Closure) 라고 한다.</li>
</ul>
<pre><code class="language-jsx">function createCV() {
  let name = &quot;&quot;;
  let about = &quot;&quot;;
  function changeName(txt) {
    name = txt;
  }
  function changeAbout(txt) {
    about = txt;
  }
  function print() {
    console.log(&quot;NAME : &quot;, name);
    console.log(&quot;ABOUT : &quot;, about);
  }

  return { changeName, changeAbout, print };
}

// 클로저 만들기 (외부에서 createCV함수 내부의 변수를  저장하는 공간 클로저를 만든다)
// 이력서 1
const cv1 = createCV();
cv1.changeName(&#39;zeeyoon&#39;);
cv1.changeAbout(&#39;개발 경력 6개월&#39;);
cv1.print(); //NAME :  zeeyoon ABOUT :  개발 경력 6개월

// 이력서 2
const cv2 = createCV();
cv1.changeName(&#39;june&#39;);
cv1.changeAbout(&#39;개발 경력 1년 이상&#39;);
cv1.print(); //NAME :  june ABOUT :  개발 경력 1년 이상</code></pre>
<hr>
<p>📍 <strong>코드 및 이미지 출처</strong> : 엘리스 아카데미 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Rest,spread(ES6),구조분해할당]]></title>
            <link>https://velog.io/@jiynn_12/TIL13</link>
            <guid>https://velog.io/@jiynn_12/TIL13</guid>
            <pubDate>Wed, 20 Apr 2022 05:54:37 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📍<strong>오늘 배운 내용</strong></p>
</blockquote>
<ul>
<li>ES6문법 =&gt; rest,spread 연산자 사용법</li>
<li>객체나 배열 필드는 단순히 reference만 복사한다. 따라서, deep copy (깊은복사) 를 위한 별도의 작업을 해주한다.</li>
</ul>
<h1 id="1️⃣-es6-rest-spread-operator">1️⃣ ES6 Rest, Spread Operator</h1>
<h2 id="1-rest-operator">1. Rest Operator</h2>
<ul>
<li>함수의 인자, 배열, 객체 중 <strong>나머지 값을 묶어 사용</strong>하도록 한다.</li>
<li><strong>함수의 인자 중 나머지</strong>를 가르킨다.</li>
<li><strong>배열의 나머지 인자</strong>를 가르킨다.</li>
<li><strong>객체의 나머지 필드</strong>를 가르킨다.</li>
</ul>
<pre><code class="language-jsx">function checkMin(...rest) {
    // ... (rest연산자) 를 이용해서 배열을 만든다.
    // [7, 3, 5, 2, 4, 1] 따라서 배열메소드 reduce() 사용
  return rest.reduce((a,b) =&gt; a&lt;b ? a : b)
}
console.log(checkMin(7, 3, 5, 2, 4, 1)); //1</code></pre>
<blockquote>
<p><strong>배열의 경우, 인자가 하나도 없다면 rest operator로 묶을 수 없다.</strong></p>
</blockquote>
<h2 id="2-spread-operator">2. Spread Operator</h2>
<ul>
<li>묶인 배열 혹은 객체를 각각의 필드로 변환</li>
<li>객체는 또다른 객체로의 spread 를 지원한다.</li>
<li>배열은 또다른 배열의 인자, 함수의 인자로의 spread 를 지원한다.</li>
</ul>
<pre><code class="language-jsx">const bio = {
  name: &#39;zeeyoon&#39;,
  age : 27,
  address : &#39;Seoul&#39;,
  job : &#39;FrontEnd Engineer&#39;,
};

//============= rest 연산 ==============
const {age, name, ...rest} = bio;
// 여기서 rest 는 객체 
// const age = bio.age
// const name = bio.name
// const rest = biot.나머지필드    와 동일한 코드라고 생각하기
console.log(age, name, rest);
// 27 zeeyoon { address: &#39;Seoul&#39;, job: &#39;FrontEnd Engineer&#39; }

// ============ spread 연산 ==================
let bio2 = {...bio, name: &quot;june&quot;, age : 26 }
// bio객체를 가져오고 이름과 나이는 덮어씌우기 (...bio가 뒤에오면 바꾼내용은 의미X)</code></pre>
<h1 id="2️⃣-구조-분해할당">2️⃣ 구조 분해할당</h1>
<ul>
<li>인덱스 순서대로 그대로 할당된다. (arr 에 2번째 인덱스에 데이터가 추가해도 추가한 데이터는 할당되지 않는다.)</li>
</ul>
<pre><code class="language-jsx">let arr = [&quot;Zeeyoon&quot;, &quot;Kyeong&quot;];

let[firstName, lastName] = arr;
console.log(firstName);
console.log(lastName);</code></pre>
<ul>
<li><strong>객체의 구조분해할당</strong><ul>
<li>프로퍼티(필드)를 사용하면 순서상관없다 </li>
<li>프로퍼티명을 바꿔 줄 수 있다.</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">let user = {
  name: &#39;zeeyoon&#39;, 
  age: 25,
  location: &#39;seoul&#39;,
  edu : &#39;STNU&#39;
}
let {edu, age, location} = user;
console.log(edu);        //STNU
console.log(age);        //25
console.log(location);    //seoul

let {name : lastname} = user;
console.log(lastname);    //zeeyoon</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] IndexedDB (트랜잭션으로 CRUD작업)]]></title>
            <link>https://velog.io/@jiynn_12/TIL12-IndexedDB%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%84%9C-%EA%B8%B0%EB%8A%A5%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jiynn_12/TIL12-IndexedDB%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%84%9C-%EA%B8%B0%EB%8A%A5%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 20 Apr 2022 01:00:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📍 <strong>오늘배운내용</strong></p>
</blockquote>
<ul>
<li>다양한 웹브라우저의 DB와 그중에서 IndexedDB에 대해서 배웠다.</li>
<li>수업 알아듣는게 너무 힘들었지만 나만 그런거 아니었다,, 다른분들의 질문을 보고 어느정도 해결되었다</li>
</ul>
<h1 id="indexeddb-로컬-데이터베이스">IndexedDB (로컬 데이터베이스)</h1>
<ul>
<li>브라우저에 데이터를 저장하는 로컬DB,  장점 &gt; 빠르다...</li>
<li>브라우저의 객체 저장 가능, 자바스크립트 객체, 파일, blobs등을 저장, <code>Transaction</code>을 지원<ul>
<li><u><strong>관계형데이터베이스, sql</strong> 이 아니다!</u></li>
</ul>
</li>
<li>결론! 자바스크립트 기반의 객체 지향 데이터 베이스 &gt; 자료형과 객체 저장 가능</li>
</ul>
<hr>
<blockquote>
<h3 id="클라이언트-측-브라우저에-저장하기-위한-api">클라이언트 측 브라우저에 저장하기 위한 API</h3>
<pre><code>1. 쿠키 (cookies) : 문 서내부에 간단 문자열 데이터를 저장 (적은양의 데이터)
2. 로컬 저장소(Local Storage) : Json 데이터를 문자열로 변환하여 저장 (사용자가 지우지않는이상 지속)
3. 세션 저장소 (Sesscion Storage) : Json 데이터를 오직 탭 세션에 저장 (탭을 닫으면 제거됨)
4. IndexedDB : key를 이용해 Index되는 구조화된 데이터를 쉽게 저장
    1. JSON 형태 즉, Key-Value 형태의 데이터베이스
    2. transaction 기능 지원
    3. Key 범위의 쿼리와 Index를 지원
    4. localStorage에 비해 훨씬 많은 데이터 저장 가능
    5. 즉 Index를 지원하기 때문에 많은 양의 구조화된 데이터를 다룰때 적합하다</code></pre></blockquote>
<h2 id="indexeddb-작업순서">IndexedDB 작업순서</h2>
<h3 id="1️⃣-데이터베이스-열기">1️⃣ 데이터베이스 열기</h3>
<pre><code class="language-javascript">let onRequest = indexedDB.open(&#39;myDB&#39;,1);</code></pre>
<ul>
<li><code>let request = indexedDB.open(name, version);</code><ul>
<li>name : 문자열, 데이터베이스 이름 / version - 기본적으로 양의 정수 버전 1</li>
<li><code>let request = indexedDB.open(&#39;myDB&#39;, 1);</code></li>
<li>IndexedDB 데이터베이스 수정시 Version을 같이 수정해줘야함</li>
</ul>
</li>
</ul>
<h3 id="2️⃣-데이터베이스에-objectstore객체저장소-테이블-생성">2️⃣ 데이터베이스에 ObjectStore(객체저장소, 테이블) 생성</h3>
<ol>
<li><p><code>createObjectStore()</code> 메소드 사용해주기!</p>
<ul>
<li><code>database.createObjectStore(’store name’, {keyPath: ‘id’})</code></li>
<li><code>database.createObjectStore(’store name’, {autoIncrement: true})</code> </li>
<li><code>database.createObjectStore(’store name’, {autoIncrement: ‘id’, autoIncrement: true})</code><ul>
<li>AutoIncrement : 데이터 고유번호를 자동으로 갱신</li>
</ul>
</li>
</ul>
</li>
<li><p><code>onpugradeneeded()</code> 으로 DB가 업그레이드 될때 <code>ObjectStore</code> 생성 또는 수정 가능</p>
<pre><code class="language-javascript"> request.onsuccess = e =&gt; {
     alert(&quot;upgraed is called&quot;);}
 }

 request.onupgradeneeded = e =&gt; {
     //2. 1단계에서 연결한 DB onRequset 객체를 사용해서
     const database = onRequest.result;
     database.createObjectStore(&#39;users&#39;, {autoIncrement: true})
     database.createObjectStore(&#39;items&#39;, {autoIncrement: true})
  }

 request.error = e =&gt; {
     alert(&quot;Error creating or accessing db&quot;);}
 }
</code></pre>
</li>
</ol>
<pre><code>- **`onupgradeneeded`**
  - 데이터 베이스를 여는 코드를 작성했을때 사용한 `name(&#39;myDB&#39;)` 또는 `version(1)`과 일치하는 데이터베이스가 없는 경우 호출 -&gt; 데이터베이스를 생성. 
이 이벤트 안에서 `objectStore`를 **만들거나 삭제하고, 인덱스를 만들거나 지울 수 있음**
- **`onsuccess`**
  - `Name`과 `Version` 모두 일치하는 데이터베이스가 있는 경우 호출
- **`error`**
  - DB 호출에 실패했을 때 error를 발생 또는 `Name`이 일치하지만 존재하는 DB의 `Version` 보다 &lt;u&gt;낮은 Version을 호출&lt;/u&gt;하면 error를 발생


### 3️⃣ Transaction 시작 - 데이터 추가, 검색 작업 요청

💬 **Transaction 시작하기**

```jsx
  //1.                    database.transaction(객체저장소이름, transaction mode)
  const transaction = database.transaction(&quot;users&quot;, &#39;readwrite&#39;)

 //2. store에 값을 삽입하기 위해 objectStore() 함수로 테이블 선택
  const store = transaction.objectStore(storeName);
//이후 CRUD 작업시 store에 add, get, clear...메소드를 ㅅ용
</code></pre><ol>
<li><p>모든 데이터 읽기 및 쓰기는 Transacrtion 내에서 수행된다.</p>
<ul>
<li><code>users</code> : 객체 저장소 이름(2단계 객체저장소 생성시 입력한 이름)</li>
<li>Transaction Mode : <code>readonly</code>, <code>readwrite</code>, <code>versionchange</code></li>
</ul>
</li>
<li><p>트랜잭션은 데이터베이스 객체 단위로 작동하므로 트랜잭션을 사용할 객체 저장소를 지정해줘야함</p>
<ul>
<li><code>store</code> 객체로 트랙잭션 사용</li>
</ul>
</li>
</ol>
<hr>
<p>💬 <strong>ObjectStore에 데이터 추가하기 - CRUD</strong></p>
<pre><code class="language-jsx">//&#39;users(1)&#39;라는 이름의 ObjectStore를 생성
database.createObjectStore(&#39;users&#39;, {autoIncrement: true})
function addUsers() {

        const user = {
          name: &quot;Zeeyoon&quot;,
          about: &quot;fontend Engineer&quot;
        }
        //&#39;users(1)&#39; ObjectStore 에 readwrite(읽기,쓰기)권한으로 Transaction 시작하기
        // transaction을 시작한 객체를 transaction 이라는 변수에 저장 
        const transaction = database.transaction(&quot;users&quot;, &#39;readwrite&#39;)

        //objectStore() 함수로 users 테이블 선택
        // 여기서의 &quot;usersOb&quot;는 users라는 오브젝트스토어 객체!를 넣을 변수
        // *** 번거롭지만 또 users라는 오브젝트스토어를 찾아줘야한다. (그렇게 만들어졌음) ***
        const usersOb = transaction.objectStore(&quot;users&quot;)

        //원하는 객체 (user) 를 테이블에 추가
        // 테이블 객체를 저장한 usersOb에 add 메소드적용
        usersOb.add(user)
}
</code></pre>
<ul>
<li><code>ObjectStore.add()</code><ul>
<li>transaction 을 complete 해줘야한다.</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">dbPromise.then(function(db){
    const transaction = db.transaction(&#39;users&#39;, &#39;readwrite&#39;)
  // 키값을 id라는 프로퍼티로 하겠다!
    const store = transaction.objectStore(&#39;users&#39;, {keyPath:&#39;id&#39;})
    store.add({id:3, name: &#39;Zeeyoon&#39;;, age: 27})

    return transaction.complete
}</code></pre>
<hr>
<ul>
<li><code>ObjectStore.get(key)</code> , <code>ObjectStore.getAll()</code> </li>
</ul>
<pre><code class="language-jsx">dbPromise.then (function(db) {
    const transaction = db.transaction([&#39;users&#39;], &#39;readwrite&#39;)
    const store = transaction.objectStore(&#39;users&#39;)
    return store.get(&#39;Zeeyoon&#39;) //{id:3, name: &#39;Zeeyoon&#39;;, age: 27}
    //=============
    return store.getAll(); //모든 데이터가 다 나옴 
}</code></pre>
<hr>
<ul>
<li><code>ObjectStore.put()</code></li>
</ul>
<pre><code class="language-jsx">dbPromise.then (function(db) {
    const transaction = db.transaction([&#39;users&#39;], &#39;readwrite&#39;)
    const store = transaction.objectStore(&#39;users&#39;)

    return store.put(&#39;Zeeyoon&#39;)
}</code></pre>
<hr>
<ul>
<li><code>ObjectStore.delete()</code><ul>
<li><code>transaction</code>을 <code>complete</code> 해줘야한다.</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">dbPromise.then(function(db){
    const transaction = db.transaction([&#39;users&#39;], &#39;readwrite&#39;)
  // 키값을 id라는 프로퍼티로 하겠다!
    const store = transaction.objectStore(&#39;users&#39;, {keyPath:&#39;id&#39;})
    store.delete(&#39;Zeeyoon&#39;)

    return transaction.complete
}</code></pre>
<h4 id="4️⃣-나머지-작업-index-마다-dom-이벤트-수신해서-작업--결과-수행">4️⃣ 나머지 작업) index 마다 DOM 이벤트 수신해서 작업 &gt; 결과 수행</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] let,var,const 의 유효범위와 호이스팅 (+ 함수선언식)]]></title>
            <link>https://velog.io/@jiynn_12/JavaScript-letvarconst-%EC%9D%98-%EC%9C%A0%ED%9A%A8%EB%B2%94%EC%9C%84%EC%99%80-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@jiynn_12/JavaScript-letvarconst-%EC%9D%98-%EC%9C%A0%ED%9A%A8%EB%B2%94%EC%9C%84%EC%99%80-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Wed, 20 Apr 2022 00:52:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>JavaScript 의 변수와 유효범위- 호이스팅</p>
</blockquote>
<ul>
<li><code>var</code>, <code>const</code>, <code>let</code> </li>
<li>이때 <code>함수 선언문</code>은 함수 전체가 호이스팅</li>
<li><code>var</code> 변수는 저장시 <code>undefined</code>로 초기화  =&gt; ⛔️ 그 외 값 할당은 호이스팅되지 않는다!</li>
</ul>
<h2 id="1️⃣-javascript의-변수">1️⃣ JavaScript의 변수</h2>
<ul>
<li><code>let</code>, <code>const</code>, <code>var</code> ⇒ <code>let</code> 은 가변변수 , <code>const</code>는 불변변수!</li>
<li>대신 <code>const</code>로 선언한 데이터가 <code>객체</code>혹은 <code>배열</code>이라면 <strong><u>그안의 값은 변경 가능</u></strong>하다!</li>
</ul>
<table>
<thead>
<tr>
<th>Name</th>
<th>Scope</th>
<th>재정의</th>
<th>재선언</th>
</tr>
</thead>
<tbody><tr>
<td>var</td>
<td>Function Scoped</td>
<td>변경 가능</td>
<td>변경 가능</td>
</tr>
<tr>
<td>let</td>
<td>Block Scoped</td>
<td>변경 가능</td>
<td>변경 불가능</td>
</tr>
<tr>
<td>const</td>
<td>Block Scoped</td>
<td>변경 불가능</td>
<td>변경 불가능</td>
</tr>
</tbody></table>
<pre><code class="language-jsx">let x = 1;
const y = 2;
var z = 3;
console.log(x); 1
console.log(y); 2
console.log(z); 3

x = 12;
y = 43;
console.log(x); 12
console.log(y); // error

let x = 3;
const y = 8;
// both error
var z = 54;
console.log(x); // error
console.log(y); // error
console.log(z); // 54</code></pre>
<blockquote>
<p>💡 <code>const</code> 로 선언된 배열 또는 객체는 내용을 바꿀 수 있다</p>
</blockquote>
<pre><code class="language-jsx">const cars = [&quot;Saab&quot;, &quot;Volvo&quot;, &quot;BMW&quot;];
cars = [&quot;Toyota&quot;, &quot;Volvo&quot;, &quot;Audi&quot;];    // ERROR

// You can change an element:
cars[0] = &quot;Toyota&quot;;

// You can add an element:
cars.push(&quot;Audi&quot;);</code></pre>
<h2 id="2️⃣-변수의-유효범위variable-scope">2️⃣ 변수의 유효범위(Variable Scope)</h2>
<blockquote>
<ul>
<li><code>let</code>, <code>const</code> 는 <strong><em>블록레벨</em></strong> (<strong><code>{}</code></strong>, 중괄호)의 범위를 가진다.</li>
</ul>
</blockquote>
<pre><code class="language-jsx">const a = 7

function scope() {
  if (true) {
    console.log(a) //undefined
    const b = 123 
    var c = 456
        //a는 if문의 지역변수
    //블록레벨의 범위를 가진다. 
  } 
  console.log(b) //scope 에러 
  console.log(c) //456
}
scope()</code></pre>
<ul>
<li><code>var</code> (되도록 사용 X), <code>let</code>, <code>const</code><h3 id="🚫-var-비권장이유는-">🚫 <strong>var</strong> 비권장이유는 ?</h3>
</li>
<li>=&gt; <strong><em>함수레벨의 범위</em></strong>를 가지기 때문에 메모리 누수가 발생할수도 있음,</li>
<li>최신 프론트엔드 개발에선 비권장!</li>
</ul>
<pre><code class="language-jsx">function scope2() {
  if (true) {
        console.log(a) //undefined
    var a = 123 
  } 
  **console.log(a) //123**
}
console.log(a) //함수범위의레벨이 아니기때문에 에러

scope2()</code></pre>
<h2 id="3️⃣-호이스팅-hoisting">3️⃣ 호이스팅 (hoisting)</h2>
<ul>
<li>함수 선언부가 <strong><em>유효범위 최상단</em></strong>으로 끌어올려지는 현상</li>
<li><strong><code>var</code></strong> <strong>변수 선언</strong>과 <strong><code>함수선언문</code></strong>에서만 <strong>호이스팅</strong>이 일어난다.<ul>
<li>var 변수/함수의 선언만 위로 끌어 올려지며, <strong><em>할당은 끌어 올려지지 않는다.</em></strong>🚫</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">        function scope2() {
          **a = 123;**
          if (true) {
            console.log(a) //123
            **var a; 
                //var 변수선언으로 호이스팅 되었음**
          } 
          console.log(a) //123
        }
        //==================================================

        b = 345
        console.log(b) //345
        var b

        //==================================================

        // ***할당은 끌어 올려지지 않는다 -&gt; 따라서 undefined***
        console.log(c) //undefined
        c = 345
        var c
</code></pre>
<ul>
<li><code>let</code>/<code>const</code> 변수 선언과 <strong><code>함수표현식</code>에서는 호이스팅이 발생하지 않는다</strong></li>
</ul>
<pre><code class="language-jsx">const a = 7

double() //14

//함수호이스팅이발생 윗줄에서 
//함수호출해도 실행된다.

// 함수선언문
function double() { 
  console.log(a*2)
}</code></pre>
<pre><code class="language-jsx">const a = 7

double() //error

//함수호이스팅이 발생안하므로 에러

//함수표현식
const double = function() { 
    console.log(a*2)
}</code></pre>
<blockquote>
<p>💡 <strong>Q. 호이스팅은 언제 유용할까?</strong> </p>
</blockquote>
<ul>
<li>전체적인 로직으로 보았을때, 만약 함수내부의 로직이 매우 길다면,</li>
<li>어디에서 실행되는지 찾기전에 긴로직의 함수를 지나서 함수 실행 부분을 확인 가능 
⇒ 따라서 가독성을 위해 최하단부에 적음</li>
</ul>
<blockquote>
<p>💡 <strong>var 변수선언으로 호이스팅 발생</strong>
    ⇒ 변수에 선언을 먼저 하지 않아도 할당이 되기때문에 복잡한 상황 발생할 가능성 높다. 🚫🚫🚫🚫
    ⇒ 웬만하면 <strong><code>var</code></strong> 사용을 주의하기</p>
</blockquote>
<p>📍 <strong>참고자료</strong> : 코어자바스크립트,정재남</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 화살표 함수 사용방법]]></title>
            <link>https://velog.io/@jiynn_12/JavaScript-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@jiynn_12/JavaScript-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Mon, 18 Apr 2022 06:54:56 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Arrow Function<br>📍 화살표 함수는 함수표현식 혹은 익명함수에서만 가능하다
📍 매개변수, 함수내부 로직의 길이에 따라 소괄호,중괄호를 생략할 수 있음 </p>
</blockquote>
<h1 id="화살표-함수-사용법">화살표 함수 사용법</h1>
<ul>
<li><strong><code>() =&gt; {}</code></strong> vs <strong><code>function () {}</code></strong></li>
<li>화살표는 함수 표현식 혹은 익명함수에 가능</li>
<li>함수 선언만 할 때는 불가능</li>
</ul>
<pre><code class="language-javascript">toObject (x,y) =&gt; x+y //불가능
const toObject = (x,y) =&gt; x + y</code></pre>
<ol>
<li><strong><code>function</code></strong>키워드 생략 , <strong><code>=&gt;</code></strong> 화살표 추가</li>
<li><strong><code>return</code></strong> 값앞에 실행문이 따로 없다면 <strong><code>{}</code></strong> 생략 가능</li>
<li>매개변수가 1개라면 <strong><code>()</code></strong>괄호 생략 가능</li>
</ol>
<pre><code class="language-javascript">const double = function(x) {
  return x * 2
}
console.log(&#39;double: &#39;, double(7))

const doubleArrow = x =&gt; x*2</code></pre>
<ul>
<li>중괄호<strong><code>{}</code></strong>를 쓰면 <strong><code>return</code></strong> 키워드 반드시 써야한다.</li>
</ul>
<pre><code class="language-javascript">const doubleArrow = x =&gt; {return x * 2}</code></pre>
<ul>
<li>객체 데이터를 사용하고 싶다면 중괄호가 중복된다. (<strong><code>{}</code></strong>)<ul>
<li>함수에서 중괄호는 블록으로 인식 따라서 소괄호(<strong><code>()</code></strong>)를 묶어준다.</li>
<li><strong><code>매개변수 ⇒ ( {객체데이터} )</code></strong></li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">const Zeeyoon = {
    name: &#39;jiyoon&#39;,
    age: 27,
    email: abc@gmail.com
}

const doubleArrow = x =&gt; { name: &#39;Zeeyoon&#39;} //undefined
const doubleArrow = x =&gt; ({ name: &#39;Zeeyoon&#39;}) //{name: &#39;Zeeyoon&#39;}</code></pre>
<hr>
<ul>
<li><a href="https://velog.io/@jiynn_12/TIL14#2%EF%B8%8F%E2%83%A3-this-%EA%B0%80-%EA%B0%80%EB%A5%B4%ED%82%A4%EB%8A%94%EA%B2%83">화살표함수와 일반함수의 this</a> 바인딩에 관한 내용도 알아두기</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] import, export로 js모듈화와 Class]]></title>
            <link>https://velog.io/@jiynn_12/TIL11-import-export%EB%A1%9C-js%EB%AA%A8%EB%93%88%ED%99%94%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jiynn_12/TIL11-import-export%EB%A1%9C-js%EB%AA%A8%EB%93%88%ED%99%94%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 18 Apr 2022 06:53:20 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📍 <strong>오늘배운 내용</strong></p>
</blockquote>
<ul>
<li>이후에 react를 배울때 나오는 컴포넌트라는 개념을 위해서는 import, export 을 어떻게 사용하는지 알아야한다!</li>
<li>클래스형 컴포넌트보다 함수형을 더많이 사용하지만 Class 사용법을 알고있자</li>
</ul>
<h1 id="1️⃣-import-export">1️⃣ import, export</h1>
<ul>
<li><a href="https://caniuse.com/">https://caniuse.com/</a> &gt; import 지원 여부</li>
<li>export 는 public 함수 (외부에서도 사용 가능!)<ul>
<li>import를 활용하여 외부에 있는 public 함수에 접근</li>
<li><code>모듈화</code> 시켜야 제대로 작동 된다.<pre><code class="language-jsx">//profile.js 파일
function daynight (x) {
console.log(x);
}
function day (y) {
console.log(y);
}
function night (y) {
console.log(y);
}
</code></pre>
</li>
</ul>
</li>
</ul>
<p>export {daynight, day, night} </p>
<pre><code>&lt;hr&gt;

```jsx
//html 파일에서 사용시
&lt;script type=&quot;module&quot;&gt;
    import {dayNight} from &#39;./daynight.js&#39;
&lt;/script&gt;

//js 파일에서 사용시
import {dayNight} from &#39;./daynight.js&#39;;
//혹은
import * as mode from &#39;./daynight.js&#39;;</code></pre><h1 id="2️⃣-export-default">2️⃣ export default</h1>
<ul>
<li>모듈은 함수가 여러가지 있는 <strong>라이브러리</strong> 형태 혹은 모듈과 <strong>개체 하나만 선언</strong> 되어 있는 형태이다. </li>
<li><code>export default</code>를 사용하면 <span style="color:red">&#39;해당 모듈엔 개체가 하나만 있다’</span>는 의미.</li>
<li><code>export default</code> 키워드 사용시 <code>import</code> 할때 대괄호를 생략할 수 있다.</li>
<li>각 파일마다 <code>export default</code>는 대개 1개만 존재한다.</li>
</ul>
<pre><code class="language-jsx">//방법1
export default function Profile(name) { 
 console.log(name);
}

//방법2
function Profile(name) {
    console.log(name);
}

export default User;</code></pre>
<h1 id="3️⃣-import시-as-로-별칭-정하기">3️⃣ import시 as 로 별칭 정하기</h1>
<ul>
<li>import 한 모듈을 <code>as</code> 키워드를 통해 원하는 이름으로 사용할 수 있다.</li>
</ul>
<pre><code class="language-jsx">import {introduce} as intro from &#39;./profile.js&#39;;

intro(&#39;Hello my name is Zeeyoon&#39;);
</code></pre>
<h1 id="4️⃣-와일드-카드-로-import-하기">4️⃣ 와일드 카드(*) 로 import 하기</h1>
<ul>
<li>와일드 카드로 여러개의 함수를 가지고있는 라이브러리 모듈을 <code>import</code> 해서 사용할 때는 
객체처럼 사용한다. <pre><code class="language-jsx">//profile.js 파일
function name (x) {
console.log(x);
}
function hello (y) {
console.log(y);
}
</code></pre>
</li>
</ul>
<p>export {name, hello};</p>
<pre><code>

```jsx
import * as bio from &#39;./profile.js&#39;;

bio.name(&#39;Zeeyoon&#39;);
bio.hello(&#39;안녕하세요&#39;);</code></pre><hr>

<ul>
<li>import 와 export를 활용해서 컴포넌트화 시킨다 (컴포넌트는 나중에 react에서 자세히..)</li>
<li>Class와 상속개념에 대해서는 따로 정리한 포스팅을 올려야겠다! </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] DOM API - window, document, element 객체 ]]></title>
            <link>https://velog.io/@jiynn_12/TIL9-DOM-API-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@jiynn_12/TIL9-DOM-API-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 14 Apr 2022 14:02:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>📍 <strong>포스팅 목적!</strong></p>
</blockquote>
<ul>
<li>각 객체마다 사용가능한 메소드가 있다 </li>
<li>cheatsheet 처럼 정리해놔야 나중에 삽질을 덜할것같다!^^ </li>
<li>그런 의미에서 mdn 문서 뒤지면서 그때그때 계속 업데이트 해야하는 게시물로 사용하자👍</li>
</ul>
<h1 id="1️⃣-window-객체">1️⃣ window 객체</h1>
<blockquote>
<p>📍 MDN window 객체 문서
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Window">Window - Web APIs | MDN</a></p>
</blockquote>
<ul>
<li><code>.onload()</code></li>
<li><code>.close()</code></li>
<li><code>.setInerval(함수, 시간)</code>, <code>.setTimeout()</code> <ul>
<li>주의 사항 &gt; 요소에 해당 함수를 적용시킬때 <code>요소.속성값(임의로정한) = 함수()</code>
형태로 한뒤 <code>clearTimeout(요소.속성값);</code> 으로 해야 잘 적용된다.!<ul>
<li>아래의 객체와 속성을 이해하고 보면 된다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Working_with_Objects#%EA%B0%9D%EC%B2%B4%EC%99%80_%EC%86%8D%EC%84%B1">객체로 작업하기 - JavaScript | MDN</a></p>
<ul>
<li><p><code>setInterval (function() { 실행코드 }, ms )</code></p>
</li>
<li><p><code>setTimeout( 함수, 시간)</code></p>
</li>
<li><p><code>clearTimeout(함수이름)</code></p>
<ul>
<li><code>.innerwidth</code> : 윈도우의 내부 가로사이즈(px), 가로 스크롤바의 길이도 포함한다. (가로스크롤이 있을경우)</li>
<li><code>.scrollTo( 여러 매개변수가 존재..)</code></li>
</ul>
<pre><code class="language-javascript">window.scrollTo({
   ‘behavior’ : ‘smooth’,      //부드럽게 이동 
   ‘top’ : xxx.offsetTop      // 특정영역의 위에서의 좌표값
           //offsetTop은 선택된 영역의 상단까지의 거리를 절대 좌표로 반환하는 메서드입니다
})</code></pre>
</li>
</ul>
<h1 id="2️⃣-document-객체">2️⃣ Document 객체</h1>
<blockquote>
<p>📍 MDN - Document 객체 문서
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Document#properties">Document - Web APIs | MDN</a></p>
</blockquote>
<ul>
<li><code>.getElementsById(&#39;&#39;)</code></li>
<li><code>.append()</code></li>
<li>create 메소드에는 <strong>DOM Element</strong> 와 <strong>node</strong> 객체를 만들어내는 메소드가 모두 있음<ul>
<li><code>createElement(’태그’)</code></li>
<li><code>createAttribute(’속성&#39;)</code></li>
<li><strong><code>createTextNode(’데이터’)</code> : 텍스트 노드를 만들어낸다.</strong><ul>
<li><strong>&gt; DOM에서는 <code>element.innerTEXT</code></strong></li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>*<em>요소 접근 메소드 *</em></p>
<ul>
<li><code>.getElementById()</code></li>
<li><code>.getElementsByClassName()</code></li>
<li><code>.getElementsByTagName()</code></li>
<li><code>.querySelector()</code></li>
<li><code>.querSelectorAll()</code><h1 id="3️⃣-element-객체-요소객체">3️⃣ Element 객체 (요소객체)</h1>
</li>
</ul>
</li>
<li><p><a href="http://event.target">event.target</a> 그리고 <code>event.currentTarget</code> &gt; 이것도 결국 요소</p>
<ul>
<li>The read-only <strong><code>target</code></strong> property of the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Event">Event</a>     interface is a reference to the object onto which the event was dispatched. It is different from <a href="https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget">Event.currentTarget</a>     when the event handler is called during the bubbling or capturing phase of the event.</li>
<li><strong>eventTarget 과는 무슨차이...?</strong></li>
</ul>
</li>
</ul>
<blockquote>
<p>📍 MDN - Element 객체 문서
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Element#methods">Element - Web APIs | MDN</a></p>
</blockquote>
<ul>
<li><p><strong>요소 접근 프로퍼티</strong></p>
<ul>
<li><code>.children</code>    : 자식 노드 중 요소 노드만 HTMLCollection로 반환(텍스트 노드제외)</li>
<li><code>.firstElementChild</code> :    첫 번째 자식 요소 노드</li>
<li><code>.lastElementChild</code> :    마지막 자식 요소 노드</li>
<li><code>.parentElement</code>    : 부모 요소 노드</li>
<li><code>.previousElementSibling</code> : 자신의 이전 형제 요소 노드</li>
<li><code>nextElementSibling</code>    자신의 다음 형제 요소 노드</li>
</ul>
</li>
<li><p><code>.innerHTML</code>, <code>.innerText</code>, <code>.textContent</code> </p>
<ol>
<li>innerHTML (태그와 텍스트 모두 그대로 텍스트로)</li>
<li>innerText (태그(마크업언어,스타일까지)들이 적용된 텍스트로)</li>
<li>textContent (태그는 제거하고 텍스트만 골라서)</li>
</ol>
</li>
<li><p><code>.animate()</code></p>
<pre><code class="language-jsx">  xxx.animate({
      //keyframes
      marginLeft: [&quot;0px&quot;, &quot;1024px&quot;]
  },{
      //animation options
    duration: 500,
      easeing: &quot;ease&quot;,
      interations: 1,
      fill: &quot;both&quot;
  })</code></pre>
</li>
<li><p><code>xxx.classList ()</code></p>
<ul>
<li>선택된 Element의 클래스명들을 반환</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>.add(클래스명)</td>
<td>선택된 Element에 클래스명 추가</td>
</tr>
<tr>
<td>.remove(클래스명)</td>
<td>선택된 Element에 클래스명 삭제</td>
</tr>
<tr>
<td>.toggle(클래스명)</td>
<td>선택된 Element에 클래스명이 존재하면 삭제하고, 없으면 추가</td>
</tr>
</tbody></table>
<ul>
<li><p><code>.className</code> : 클래스명 (대입도 가능)</p>
<ul>
<li>클래스명이 여러개라면 모두 출력함 (인덱스를 활용하면 클래스단위가 아니라 첫번째 클래스의 문자열 인덱스로 접근한다...)</li>
<li><code>li.className = &quot;list-group&quot;</code></li>
</ul>
</li>
<li><p><code>.attributes</code></p>
<ul>
<li><code>.attributes.name</code></li>
<li><code>.attributes.value</code></li>
<li><code>input</code> 태그는 <code>value</code> 값은 <code>on(disabled 한다면 off)</code> ,<code>checked</code> 값은 <code>true</code> or <code>false</code></li>
</ul>
</li>
<li><p><code>.addEventListener (”event”, function(){})</code></p>
<ul>
<li><p>선택된 Element가 어떠한 이벤트를 가질 때 뒤의 함수가 호출</p>
<pre><code class="language-jsx">  document.getElementById(&quot;button&quot;).addEventListener(&quot;click&quot;, function(){
      //button이 클릭될 때
      //호출 될 함수
      alert(&quot;button clicked&quot;)
  });</code></pre>
</li>
</ul>
</li>
<li><p>addEventListener의 첫번째 인자에 들어갈수있는 이벤트 리스트</p>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/Events">Event reference | MDN</a><h3 id="자주사용하는-이벤트">자주사용하는 이벤트</h3>
</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>이벤트</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>click</td>
<td>클릭 시 (마우스 버튼에서 손가락을 땐 순간)</td>
</tr>
<tr>
<td>mouseenter</td>
<td>마우수를 요소 위에 올리면</td>
</tr>
<tr>
<td>mouseover</td>
<td>마우스를 요소 위에 올리면 (자식 Element도 영향을 받음)</td>
</tr>
<tr>
<td>mouseout</td>
<td>마우스가 요소 밖으로 벗어날 때</td>
</tr>
<tr>
<td>mousedown</td>
<td>클릭 하고 버튼에서 손가락을 때기 전</td>
</tr>
<tr>
<td>focus</td>
<td>포커스가 갔을 때</td>
</tr>
<tr>
<td>keypress</td>
<td>키를 누르는 순간에 발생, 그리고 누르고 있는 동안 계속 발생</td>
</tr>
<tr>
<td>keydown</td>
<td>키를 누를 때</td>
</tr>
<tr>
<td>keyup</td>
<td>키를 눌렀다가 떼는 순간</td>
</tr>
<tr>
<td>load</td>
<td>웹 페이지 소스가 다운로드 되었을 때</td>
</tr>
<tr>
<td>resize</td>
<td>창크기를 조절 할 때</td>
</tr>
<tr>
<td>scroll</td>
<td>스크롤바, 마우스 휠, up, down 버튼으로 스크롤 할 시</td>
</tr>
<tr>
<td>unload</td>
<td>링크를 클릭해서 다른 페이지로 이동하거나 브라우저나 브라우저 탭을 닫았을 때</td>
</tr>
<tr>
<td>change</td>
<td>form 필드의 상태가 변경 되었을 때</td>
</tr>
</tbody></table>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] DOM 과 Node > Element,node 에 접근하기]]></title>
            <link>https://velog.io/@jiynn_12/TIL8</link>
            <guid>https://velog.io/@jiynn_12/TIL8</guid>
            <pubDate>Wed, 13 Apr 2022 23:05:25 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘 배운 내용</strong>
DOM 과 Node 두가지 개념을 정확히 익히고 차이점을 알아보자!
⛔️ <code>appendChild()</code> &gt; node 에 접근하는 메소드의 인자로 element가 아닌 <code>노드객체</code>가 와야한다! ⛔️</p>
</blockquote>
<h1 id="1️⃣-dom이란">1️⃣ Dom이란?</h1>
<ul>
<li>문서 객체 모델(Document Object Model)</li>
<li><code>DOM</code> 은 객체 지향 모델로써 <strong>문서(XML,HTML)</strong>의 <strong>구조화된 표현</strong>을 제공</li>
<li>프로그래밍 언어가 문서 구조, 스타일, 내용 등을 변경할 수 있도록 하는 <strong>인터페이스</strong></li>
<li><code>HTML DOM</code> : HTML 문서를 조작하고 접근하는 표준화된 방법 (모든 HTML요소는 HTML DOM 을통해 접근)</li>
<li><code>Document</code> : 웹페이지를 의미하는 객체, 웹페이지에 존재하는 HTML 요소에 접근하고자한다면 <code>Document</code>객체부터 시작해야한다!</li>
</ul>
<h2 id="📍document-메소드">📍Document 메소드</h2>
<p>: html요소와 관련된 작업을 도와주는 다양한 메소드 제공</p>
<h3 id="html-요소의-선택">HTML 요소의 선택</h3>
<p>HTML의 아이디, 클래스, 태그, 네임을 그대로 작성해준다.  </p>
<ul>
<li><code>document.getElementByID()</code><ul>
<li>태그,클래스,name은 배열로 반환한다.</li>
</ul>
</li>
<li><code>document.getElementsByClassName()</code></li>
<li><code>document.getElementsByTagName()</code></li>
<li><code>document.getElementsByName()</code></li>
</ul>
<p>CSS 선택자 작성과 동일하게 사용! </p>
<ul>
<li><code>document.querySelector()</code> </li>
<li><code>document.querySelectorAll()</code> : 해당되는 요소의 첫번째 값만 반환한다.</li>
</ul>
<h3 id="html-요소의-생성">HTML 요소의 생성</h3>
<ul>
<li><code>document.createElement()</code> : 지정된 HTML 요소를 생성  &gt; 오브젝트를 넘기는것</li>
<li><code>document.write()</code> : HTML 출력 스트림을 통해 텍스트 출력 &gt; 단순 출력</li>
</ul>
<h3 id="html-이벤트-핸들러-추가">HTML 이벤트 핸들러 추가</h3>
<ul>
<li><code>요소.onclick = function() {}</code></li>
<li><code>function (”click”, function객체)</code></li>
</ul>
<h3 id="html-객체의-선택">HTML 객체의 선택</h3>
<h1 id="2️⃣-js와-dom">2️⃣ JS와 DOM</h1>
<ul>
<li>DOM 요소를 선택하여 변수에 저장하여 활용한다!</li>
<li>DOM 요소의 스타일 변경 (<code>.style</code> 속성 ⇒ bg, color, text,....)</li>
<li>DOM 요소의 내용 변경 (<code>.innerHTML</code> , <code>.innerText</code> ,<code>textContent</code> 속성)</li>
</ul>
<pre><code class="language-javascript">// 요소 선택
let eleOne = document.getElementById(&#39;main&#39;);
// 스타일 변경
eleOne.style.backgroundColor = &quot;blue&quot;;
// 요소의 내용 변경
let str = document.getElementById(&quot;title&quot;);
str.innerHTML = &quot;subTitle&quot;;</code></pre>
<h1 id="3️⃣-node-객체">3️⃣ Node 객체</h1>
<p>DOM에 계층과 관계를 곁들인,,, 느낌</p>
<ul>
<li>노트 트리란 노드들의 집합으로, 노드간의 관계를 나타낸다.</li>
<li>JS에서는 html dom을 이용하여 노트드리에 포함된 모든 노드에 접근 가능!</li>
<li>노드란 html dom 에서 정보를 저장하는 계층적 단위(모든 노드는 서로 계층적 관계를 맺음→ 자식,부모,형제)</li>
</ul>
<h3 id="node의-종류">Node의 종류</h3>
<ul>
<li><code>문서 노드</code> : html 전체 나타내는 노드</li>
<li><code>요소 노드</code>: html요소 노드, <code>속성 노드</code>를 가지는 유일한 노드 (온갖 태그 생각하면 된다..)</li>
<li>주석모드 : 잘사용X</li>
<li><code>속성노드</code> : html요소의 속성은 속성노드, 요소 노드에 관한 정보를 가짐, 해당 요소 노드의 자식 노드에는 포함X (src,href,style 과같은 속성 생각하면 된다.)</li>
<li><code>텍스트 노드</code> : html문서의 모든 텍스트는 텍스트 노드! (태그안에있는 텍스트나 그냥 텍스트 생각하면된다.)</li>
</ul>
<h3 id="node에-접근하기">Node에 접근하기</h3>
<ul>
<li>아래의 프로퍼티를 통해 접근한여 노드에 대한 정보를 알 수 있다.</li>
<li><code>nodeName</code>  : 이름정보를 알 수 있다. &gt; 변경까지 (text,div,li ...)</li>
<li><code>nodeValue</code> : 값 정보를 알 수 있다. &gt; 변경까지 (content에 해당하는)</li>
<li><code>nodeType</code> : 타입 정보를 알 수 있다. &gt; 변경까지<ul>
<li><code>요소 노드</code>:1</li>
<li><code>속성 노드</code>: 2</li>
<li><code>텍스트 노드</code>: 3</li>
<li><code>주석 노드</code>: 8</li>
<li><code>문서 노드</code>: 9</li>
</ul>
</li>
<li><code>childNodes</code> : 자식노드들을 모두 확인 할 수 있다.</li>
<li><code>childNodes[index]</code> : head~body 태그 안쪽의 엔터나 공백도 노드(텍스트노드)로 들어가는점 유의하기!</li>
<li>⛔️⛔️⛔️⛔️<strong><code>appendChild(노드객체)</code> : 해당 노드의 자식에 덧붙히기</strong></li>
</ul>
<pre><code class="language-jsx">// 첫번째 자식이 누구인지 보여주는것
console.log(mom.firstChild); //&quot;sister&quot;
// 첫번째 자식의 값
console.log(mom.firstChild.nodeName);  //#text
console.log(mom.firstChild.nodeType);   //3
console.log(mom.firstChild.nodeValue); //sister</code></pre>
<ul>
<li>노드 객체의 프로퍼티와 메소드 살펴보자!</li>
</ul>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Node#properties">Node - Web APIs | MDN</a></p>
<h1 id="4️⃣-dom-과-이벤트event">4️⃣ DOM 과 이벤트(Event)</h1>
<ul>
<li>이벤트란 ?</li>
</ul>
<p>; 웹 브라우저가 알려주는 HTML 요소에 대한 <strong>사건의 발생 (마우스, 키보드,등..)</strong>
  자바스크립트는 이벤트에 반응하여 특정 동작을 수행할 수 있다.</p>
<h3 id="이벤트-타입-발생-이벤트-종류">이벤트 타입 (발생 이벤트 종류)</h3>
<ul>
<li>폼, 키보드, 마우스, HTML DOM, window 객체 등...</li>
</ul>
<pre><code class="language-html">&lt;div class=&quot;btn&quot; onclick=&quot;changeColor(this)&quot;&gt;box1&lt;/div&gt;
&lt;script&gt;
    function changeColor (ele) {
        ele.style.color = &#39;red&#39;;
    }
&lt;/script&gt;</code></pre>
<h3 id="이벤트-핸들러-이벤트-처리하는-함수">이벤트 핸들러 (이벤트 처리하는 함수)</h3>
<ul>
<li>이벤트가 발생했을때 그 처리를 담당하는 함수
지정된 이벤트가 발생하면 웹 브라우저는 그 요소에 등록된 이벤트 핸들러를 실행</li>
</ul>
<pre><code class="language-jsx">window.onload = function() {

    let one = document.getElementById(&#39;one&#39;);
  one.innerHTML = &quot;this is one!!&quot;;
}</code></pre>
<hr>

<ul>
<li>node와 element의 차이에 대해 알고 있어야 여러 노드와 요소를 활용한 코드 작성시 좋을거같다는 생각.. 추가 내용 찾아보고 포스팅해보자! </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JS 프로퍼티와 메소드.zip]]></title>
            <link>https://velog.io/@jiynn_12/TIL-JS-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EC%99%80-%EB%A9%94%EC%86%8C%EB%93%9C</link>
            <guid>https://velog.io/@jiynn_12/TIL-JS-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0%EC%99%80-%EB%A9%94%EC%86%8C%EB%93%9C</guid>
            <pubDate>Tue, 12 Apr 2022 07:50:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>오늘 배운내용</strong>
📍 데이터 타입별 프로퍼티와 유용한 메소드
📍 sort가 문자열객체 메소드였다는 사실..?</p>
</blockquote>
<h4 id="백틱을-사용하면-줄바꿈과-보간법을-사용할-수-있다">백틱(`)을 사용하면 줄바꿈과 보간법을 사용할 수 있다.</h4>
<ul>
<li><code>${변수명}</code></li>
</ul>
<pre><code class="language-javascript">let str = &#39;zeeyoon&#39;;
console.log(`저의 이름은 ${str}이라고 합니다!`);
// 저의 이름은 zeeyoon이라고 합니다!</code></pre>
<h1 id="🔡-문자열객체의-메서드">🔡 문자열객체의 메서드</h1>
<ul>
<li><code>charAt(N)</code> : 문자열객체의 N번째 문자를 추출!(zeorbased index)</li>
<li><code>.length</code> : 변수의길이</li>
<li><code>.split(&quot;조건&quot;)</code> : 문자열을 조건 기준으로 나눈다.</li>
</ul>
<pre><code class="language-jsx">var str1 = &quot;Hello World&quot;;

document.write(str1.length); ///11
document.write(str1.charAt(0)); //H
document.write(str1.split(&quot; &quot;)); //Hello , World</code></pre>
<ul>
<li><code>sort()</code> : 문자열을 순서대로 정렬한다.<ul>
<li><code>sort((a,b) ⇒ a-b )</code> : 숫자 정렬시 ⇒ 작은숫자부터</li>
<li><code>sort((a,b)⇒ b-a)</code> : 숫자 정렬시 ⇒ 큰 숫자부터</li>
</ul>
</li>
</ul>
<h1 id="📍배열객체의-메서드">📍배열객체의 메서드</h1>
<ul>
<li><p><code>length</code> : 배열의 길이</p>
</li>
<li><p><strong>원본 배열을 제어하는 메서드</strong></p>
<ul>
<li><code>.push(&quot;데이터&quot;)</code> : 배열 맨끝의 데이터 추가하기</li>
<li><code>.pop()</code> : 배열 맨끝의 데이터 제거하기</li>
<li><code>.unshift(”데이터”)</code> : 배열 맨앞의 데이터 추가하기</li>
<li><code>.shift()</code> : 배열 맨앞의 데이터 제거하기</li>
</ul>
</li>
<li><p><code>filter(el ⇒ el관련 실행문)</code> : filter의 실행문의 조건에 맞는 결과값을 출력</p>
</li>
<li><p><code>Array(배열의갯수).fill(배열을채울데이터)</code></p>
<pre><code class="language-jsx">  let input = 10
  let result = Array(input).fill().map((v,i) =&gt; i+1);
  //input의 길이만큼 배열을 생성후 map메서드의 반환값으로 채워넣겠다. </code></pre>
</li>
<li><p><code>concat()</code> : a배열.concat(b배열) &gt; a배열에 b배열 덧붙히기</p>
</li>
<li><p><code>reduce()</code></p>
</li>
<li><p><code>forEach()</code></p>
</li>
<li><p><code>map()</code></p>
</li>
</ul>
<h1 id="🧮-math객체의-메서드">🧮 Math객체의 메서드</h1>
<ul>
<li><strong><code>abs</code></strong> : 절대값 출력</li>
<li><strong><code>ceil</code></strong> : 소수점 무조건 올림</li>
<li><strong><code>floor</code></strong> : 소수점 무조건 버림</li>
<li><strong><code>random</code></strong> : 0과 1사이의 임의의 숫자 (0과 1은 미포함</li>
<li><code>round</code> : 입력받은 값을 반올림해 반환한다.</li>
</ul>
<pre><code class="language-jsx">ath.abs(-12);  // 12
Math.ceil(3.4);  // 4
Math.floor(5.6);  //5
Math.random();  // 0과 1 사이의 임의의 숫자 출력</code></pre>
<ul>
<li>1~6 사이의 임의의 숫자 출력하기</li>
</ul>
<pre><code class="language-jsx">function ran(maxNum) {
    //  random 함수는 0과1사이의 임의의 숫자이므로
    //  0*6 = 6 , 1 * 6 =6 -&gt; 즉 0과 6사이 난수
        // 0값을 1로 바꾸고 6미만이므로 +1 을 해준다.
    var tmp = Math.floor(Math.random() * (maxNum)) + 1;
    document.write(tmp);
}

ran(6);</code></pre>
<h1 id="⛓-형변환-메서드">⛓ 형변환 메서드</h1>
<ul>
<li><code>parseInt()</code> : 문자열을 정수로</li>
<li><code>parseFloat()</code> : 문자열을 소수로, 문자열이 “20” 이여도 작동</li>
<li><code>Number()</code> , <code>toString()</code></li>
</ul>
<pre><code class="language-jsx">var str1 = &quot;20.14&quot;;

document.write(parseInt(str1)); // 20
document.write(parseFloat(str1)); // 20.14</code></pre>
<h3 id="documentwirte">document.wirte()</h3>
<ul>
<li>콘솔창이 아니라 화면에 출력됨</li>
<li><code>document.writeln()</code> : 웹화면에 출력값 사이에 공백을 넣으면서 출력한다.</li>
</ul>
<hr>

<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects">MDN 문서 </a>사이트에서 데이터타입별로 메소드와 프로토타입 개념과 예시코드를 볼 수 있음! -&gt; 예시코드 따라하면서 연습해보기! <img src="https://velog.velcdn.com/images/jiynn_12/post/e684e58c-15bb-450b-a5fd-f1a362dca35c/image.png" alt=""><img src="https://velog.velcdn.com/images/jiynn_12/post/66d4343f-64fa-41dd-9148-74a9a761d251/image.png" alt=""></li>
</ul>
<p>출처 : <a href="https://academy.elice.io/">엘리스아카데미(예시코드)</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects">MDN 문서</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 변수, 데이터타입과 기본문법 활용]]></title>
            <link>https://velog.io/@jiynn_12/TIL6-Javascript-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@jiynn_12/TIL6-Javascript-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Tue, 12 Apr 2022 07:36:08 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>2주차 시작 !</strong>
<strong>오늘 배운 내용</strong>
📍 <code>javascript</code>의 특징과 간단한 이벤트핸들러
📍 <code>var</code>, <code>let</code>, <code>const</code>의 유효범위와 호이스팅 현상 (책 코어자바스크립트 추가공부) </p>
</blockquote>
<h1 id="1️⃣-javascript-란">1️⃣ Javascript 란?</h1>
<ul>
<li>웹사이트의 여러 효과와 기능을 제작할 시 사용하는 프로그래밍 언어이다.</li>
<li>자바스크립트는 동적인 특징이 있다. (ex]1+1을 &#39;1+1&#39;가 아닌 2로 표현)</li>
<li>자바스크립트는 이벤트 프로그램이다.<h3 id="js의-변수">JS의 변수</h3>
</li>
<li><code>let</code>: 블록단위의 scope를 가진다. 데이터 재할당 가능</li>
<li><code>const</code>: 블록단위의 scope를 가진다. 데이터 재할당 불가</li>
<li><code>var</code>: 함수단위 scope를 가진다. 데이터 재할당이 가능하며 호이스팅 된다.(데이터 할당은 호이스팅의 대상이 아니고 <strong>변수 선언</strong>만 호이스팅된다.)<pre><code class="language-javascript">var a = 7
function scope() {
if (true) {
  //할당은 호이스팅되지 않는다.
  console.log(a) //undefined 
  const b = 123; 
  var c = 456;
  var a = 2;    
  //b는 if문의 지역변수
  //블록레벨의 범위를 가진다. 
  //전역 변수 a가 있어도 undefined인 이유는 스코프체이닝 전에 자신의 innerscope에서 변수a를 발견했기 때문에!
} 
console.log(b); //scope 에러 
console.log(c); //456
}
scope();</code></pre>
</li>
</ul>
<h3 id="데이터-타입">데이터 타입</h3>
<ul>
<li><code>String</code>: 큰 따옴표 혹은 작은따옴표 (혼용불가)</li>
<li><code>Number</code>: 음수,정수,실수,0 ...</li>
<li><code>Function</code>: <ul>
<li>함수선언: <code>function 함수명(매개변수) {실행코드 return 값}</code> (기명함수)</li>
<li>함수호출: <code>함수명(인자)</code>;</li>
</ul>
</li>
<li><code>Array</code>: <code>[데이터,데이터,데이터]</code> =&gt; 비슷한 성격의 데이터 모음<ul>
<li><code>index</code> : 배열의 방번호, 0부터 시작한다.</li>
</ul>
</li>
<li><code>Object</code><ul>
<li>프로퍼티, 메서드(name,age..), 데이터(Zeeyoon, 27,..)로 구성<pre><code class="language-javascript">const introduce = {
name: &quot;Zeeyoon&quot;,
age : 27,
skills : [&quot;JS&quot;, &quot;HTML&quot;, &quot;CSS&quot;, &quot;React&quot;],
mul : function (num1, num2) {return num1 * num2},
}
//객체데이터 접근방법
console.log(introduce[&quot;name&quot;]);  //Zeeyoon
console.log(introduce.age);       //27</code></pre>
</li>
</ul>
</li>
<li><code>Boolean</code>: true, false (비교연산자~Flow-control에서 필수값)</li>
<li><code>undefined</code> : 데이터할당 아직 이뤄지지 않은것(의도적X)</li>
<li><code>null</code> : 의도적으로 데이터를 비워두기 위해 사용<h3 id="연산자">연산자</h3>
</li>
<li>산술 연산자 : <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>%</code></li>
<li>비교연산자 : <code>==</code>, <code>===</code>, <code>&gt;</code>, <code>&lt;</code>, <code>&gt;=</code>, <code>&lt;=</code><ul>
<li><code>==</code> : 값만 비교한다.</li>
<li><code>===</code> : 데이터타입을 우선으로 비교하고 값을 비교한다.</li>
</ul>
</li>
<li>증감 연산자<ul>
<li><code>++N , --N</code> : 전위증감, 출력하기전에 증감하기</li>
<li><code>N++, N--</code> : 후위증감, 출력한후 증감하기</li>
</ul>
</li>
<li>논리 연산자 : <code>||(둘중 하나만 만족)</code>, <code>&amp;&amp;(모두만족)</code></li>
</ul>
<h3 id="조건문과-반복문">조건문과 반복문</h3>
<blockquote>
<h4 id="조건문"><strong>조건문</strong></h4>
</blockquote>
<ul>
<li><code>if(조건) {조건이 true일때 실행될내용}</code></li>
<li><code>if ( ) else if ( ) { } else { }</code></li>
</ul>
<blockquote>
<h4 id="반복문"><strong>반복문</strong></h4>
</blockquote>
<ul>
<li><code>for(초기화한 변수값; 조건; 증감표시) { 실행내용 }</code></li>
<li><code>while</code>: 조건이 true 이면 명령을 계속 수행</li>
<li><code>do~while</code> 문은 조건에 상관없이 무조건 한번은 실행시키는 반복문!<ul>
<li><code>do</code>는 일단 실행! 단, <code>while</code>안 조건에 충족할때까지</li>
</ul>
</li>
<li><code>break</code> : 반복문 탈출<pre><code class="language-javascript">for(let i=0; i&lt;4; i++) {
      console.log(i) // 1 2 3
}
//===========================================
var i = 3;
var cnt = 0;
while (true) {
  cnt++;
  if(cnt ==2) break;
}
do {
  document.write(i);
  i--;
} while (i &gt;= 0);
// 3 2 1 0</code></pre>
</li>
</ul>
<h1 id="2️⃣-javascript를-활용한-간단한-이벤트-실습">2️⃣ Javascript를 활용한 간단한 이벤트 실습</h1>
<ul>
<li><code>prompt</code> : 사용자에게 입력값을 받아 콘솔창에 출력</li>
<li><code>confirm</code> : true, false (확인,취소로 사용자가 선택)</li>
<li><code>alert</code> : 알림창 띄우기
<img src="https://velog.velcdn.com/images/jiynn_12/post/567b5aa2-280a-4d4d-ab79-0e04e8c07684/image.png" alt=""></li>
<li><strong><code>speechSynthesis.speak(new SpeechSynthesisUtterance(&#39;hello world&#39;));</code></strong><ul>
<li>브라우저에서 음성이 나온다....대박...!</li>
</ul>
</li>
<li><strong>메소드체이닝 방식</strong>으로 이벤트 주기<ul>
<li><code>querySelector(&#39;선택자&#39;).스타일속성.CSS속성=&quot;값&quot;;</code><img src="https://velog.velcdn.com/images/jiynn_12/post/79d2f155-cb7e-4875-9e26-5f98b479d3d7/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="js-이벤트-핸들링-실습">JS 이벤트 핸들링 실습</h3>
<ul>
<li><code>onclick</code>, <code>onmouseleave</code> 로 간단한! 실습<pre><code class="language-html">&lt;input type=&quot;button&quot; value=&quot;night&quot; 
    onclick=&quot;
      alert(&#39;야간!&#39;);&quot;  
    onmouseleave=&quot;
      alert(&#39;안녕히가세요!&#39;);&quot;
  &quot;
&gt;</code></pre>
</li>
<li>야간모드/낮모드 간단구현해보기<ul>
<li><code>this</code>를 활용하여 버튼하나로 만들어보기!</li>
<li><code>value</code>가 day 인 input과 night인 input을 구분하기 위해서 <code>this</code> 필요!<pre><code class="language-html">&lt;input type=&quot;button&quot; value=&quot;night&quot; 
  onclick=&quot;
  if(this.value === &#39;night&#39;) {
    document.querySelector(&#39;body&#39;).style.backgroundColor = &#39;black&#39;;
    document.querySelector(&#39;*&#39;).style.color = &#39;white&#39;;    
    // 쿼리 선택자로 하면 2가지 모두 Input 이기때문에 value값 추적이 어려움   
    // document.querySelector(&#39;input&#39;).value = &#39;day&#39;;
    this.value = &#39;day&#39;;
  } else if (this.value === &#39;day&#39;){
    document.querySelector(&#39;body&#39;).style.backgroundColor = &#39;white&#39;;
    document.querySelector(&#39;*&#39;).style.color = &#39;black&#39;; 
    // document.querySelector(&#39;input&#39;).value(&#39;night&#39;);
    this.value = &#39;night&#39;;
  }
  &quot;
&gt;</code></pre>
</li>
</ul>
</li>
</ul>
<hr>

<p>📚 <strong>호이스팅 코드 출처</strong> : 코어자바스크립트,정재남</p>
]]></description>
        </item>
    </channel>
</rss>