<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>bella.log</title>
        <link>https://velog.io/</link>
        <description>기록하며 공부하기</description>
        <lastBuildDate>Wed, 13 Jul 2022 06:00:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>bella.log</title>
            <url>https://images.velog.io/images/suyeon-hong/profile/b1be8880-f024-4cf6-996b-c868c87f5ad9/daniel-ramirez-q4TfWtnz_xw-unsplash.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. bella.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/suyeon-hong" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[오픈소스 101 기본교육 Git]]></title>
            <link>https://velog.io/@suyeon-hong/%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-101-%EA%B8%B0%EB%B3%B8%EA%B5%90%EC%9C%A1-Git</link>
            <guid>https://velog.io/@suyeon-hong/%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-101-%EA%B8%B0%EB%B3%B8%EA%B5%90%EC%9C%A1-Git</guid>
            <pubDate>Wed, 13 Jul 2022 06:00:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>수단(도구) 보다 목적이 중요하다
목적: 협업을 잘 하기 위해서!</p>
</blockquote>
<p>단순히 commit, push 하는 방법을 배우는 것이 아닌, 왜 이것이 필요한지, 어떤 상황에서 사용할 수 있는지 컨셉을 정하고 상황을 시뮬레이션하면서 진행되었다.
실제로 알고 있던 명령어도 상황을 예시로 진행하려고보니 막막한 부분이 있었고, 터미널만을 이용해서 git을 관리했던 적이 없다보니 낯선 명령어도 많았다. 여러번 해보면서 익혀야할 것 같다.</p>
<br>


<h3 id="📍-기본실습">📍 기본실습</h3>
<p>기본 과정에서는 <a href="https://ide.goorm.io/">Groom IDE</a>를 이용해서 웹으로 터미널을 조작하며 실습이 진행됐다.</p>
<blockquote>
<p>필수로 알고 있어야 한다고 말씀해주신 기본명령어들</p>
<p><strong>ls</strong>: 폴더 내용을 확인
<strong>mv</strong>: 파일명 변경, 혹은 파일 이동
<strong>cd</strong>: (change directory)폴더 이동
<strong>pwd</strong>: (print working directory)현재 경로를 출력</p>
</blockquote>
<br>



<h4 id="🚩-오픈소스-프로젝트-pytorch에-개발참여를-한다는-컨셉으로-진행샘플-디렉토리-이용">🚩 오픈소스 프로젝트 pytorch에 개발참여를 한다는 컨셉으로 진행(샘플 디렉토리 이용)</h4>
<blockquote>
<p>** 🔥 오픈소스 기여 순서 **</p>
</blockquote>
<ol>
<li>개발환경 구축(구름 IDE 컨테이너 생성)</li>
<li>fork (github 프로젝트 복사)</li>
<li>clone (로컬에 소스 다운로드)</li>
<li>프로젝트 개발 현황 파악/분석 (Reading Skill)</li>
<li>소스 수정한 뒤 commit 히스토리 저장</li>
<li>수정내용 제출 (Pull-Request(PR))</li>
</ol>
<p>4) Reading Skill
    -&gt; 오픈소스 Git 프로젝트 읽는법: 누가 제일 많이 개발에 참여했는지 확인하기
    (협업하고 소통하기 위해서 확인해야 함, 누구한테 리뷰받고 조언을 얻을 수 있는지 판단)</p>
<blockquote>
<p>** git log --oneline | wc -l ** : 전체 커밋 갯수 한 줄 조회 
** git shortlog | -sn ** : 커밋 갯수 많은 사람부터 오름차순 조회
-&gt; 커밋 갯수 많은 사람이 개발에 많이 참여한 사람</p>
</blockquote>
<blockquote>
<p><strong>git log ** : 커밋 내역 조회
**--oneline</strong> : 한 줄로 조회
<strong>|</strong> : 하이픈으로 구분 시 왼쪽 영역에 우선순위
<strong>wc</strong> : (word count) 전체 커밋 갯수 확인(수정된 횟수)
<strong>-l</strong> : (line) 
<strong>-- &#39;mnist/&#39;</strong> : 특정 폴더(mnist)내에서 조회
<strong>--after=2020-01-01
--before=2020-01-31</strong> : 특정 날짜 내에서 조회
<strong>--reverse</strong> : 순서 반대로 조회
<strong>-p</strong> : 히스토리 내역 세부적으로 조회</p>
</blockquote>
<blockquote>
<p><strong>git shortlog</strong> : 커밋 갯수 + 작성자 조회
<strong>-sn</strong> : (summary, number) 요약, 오름차순 조회</p>
</blockquote>
<blockquote>
<p><strong>git show</strong> &#39;커밋아이디&#39; : 수정사항 확인
<strong>grep &quot;diff --git&quot;</strong> : &quot;&quot;를 포함하는 내용 조회
<strong>git diff</strong> : 수정된 내용 조회</p>
</blockquote>
<br>

<blockquote>
<h4 id="👉-커밋-메세지--소스-수정의-이유를-작성하는-것">👉 커밋 메세지 : 소스 수정의 &#39;이유&#39;를 작성하는 것</h4>
<p><strong>Fix</strong> : 잘못된 것을 고친 것
<strong>Improve</strong> : 원래는 잘 되던 것을 개선한 것(예: 10초 -&gt; 5초)
<strong>Add</strong> : 없는 기능, 옵션 추가할 때
<strong>Implement</strong> : 설계를 구현하는 것(미리 commision된 부분을 구현)
<strong>Support</strong> : 윈도우에서만 가능하던 것 -&gt; 리눅스에서도 가능하게(ARM =&gt; x86)</p>
</blockquote>
<br>

<h3 id="🔥-오픈소스-개발참여-준비">🔥 오픈소스 개발참여 준비</h3>
<blockquote>
<h4 id="👉-git-설정하기">👉 Git 설정하기</h4>
<p>git config --global user.name &quot;본인이름&quot; : 이름 등록
git config --global user.email &quot;본인메일&quot; : 메일 등록
git config --global core.editor nano
sudo apt install -y nano</p>
</blockquote>
<p>git config --list : 등록된 정보 확인
(잘못 입력했을경우 다시 입력하면 덮어쓰기 됨)</p>
<blockquote>
<h4 id="👉-branch-생성하기">👉 Branch 생성하기</h4>
<p>git checkout -b &#39;브랜치명&#39; : 브랜치 생성 및 해당 브랜치로 이동
git branch -D &#39;브랜치명&#39; : 브랜치 삭제
rm &#39;폴더명/&#39;: 폴더 삭제</p>
</blockquote>
<blockquote>
<h4 id="👉-토큰-생성하기push할때-idpw-대신-사용">👉 토큰 생성하기(push할때 ID/PW 대신 사용)</h4>
<p><a href="https://github.com/settings/tokens">https://github.com/settings/tokens</a></p>
</blockquote>
<ol>
<li>Generate token 버튼 클릭</li>
<li>토큰명 적기 (예:test)</li>
<li>workflow 체크하기</li>
<li>하단 Generate token 버튼 클릭</li>
<li>생성된 토큰 복사하기</li>
<li>git push origin &#39;폴더명&#39;</li>
<li>username 대신 토큰 붙여넣기</li>
<li>password는 그냥 enter 키</li>
<li>fork 프로젝트 github 사이트 들어가기</li>
<li>수정한 브랜치 선택하기</li>
<li>contribute 버튼으로 PR</li>
</ol>
<p>❓ git을 통해서 파일을 다루는 방법이 왜 필요한가?</p>
<ul>
<li>commit 생성하기 전, 내가 수정한 사항을 체크하고 싶을 때 &#39;git diff&#39;로 조회가능</li>
<li>수정한 파일을 복구하고 싶을 때 &#39;git checkout -- 폴더명&#39;를 입력하면 복구 가능</li>
</ul>
<p>checkout : 히스토리 창고(.git)에서 가져온다는 뜻 (도서관 책을 대출받을 때 사용하는 의미와 비슷하다), 단순히 브랜치 이동하는 명령어가 아님</p>
<blockquote>
<p><strong>git commit --amend</strong> : 최신 commit에 흡수
소스 수정 -&gt; git add -&gt; commit 생성 -&gt; 놓친 수정사항 발견 -&gt; 기존의 commit을 수정하려면?
-&gt; --amend 옵션으로 최신 commit을 수정할 수 있다.</p>
</blockquote>
<br>
<br>

<h3 id="📍-고급실습rebaseblame">📍 고급실습(rebase/blame)</h3>
<p>고급실습에서는 git bash를 이용해 터미널 환경을 구축한 뒤 실습을 진행했다.</p>
<blockquote>
<h4 id="👉-rebase가-필요한-상황">👉 rebase가 필요한 상황</h4>
<p>여러명이 협업할 때 base commit이 변경될 수 있음 -&gt; base commit이 다를경우 충돌이 발생할 수 있음 -&gt; rebase를 통해 base commit을 최신화 가능</p>
</blockquote>
<blockquote>
<h4 id="🔥-rebase-사용방법">🔥 rebase 사용방법</h4>
</blockquote>
<ol>
<li>오픈소스 프로젝트에 commit 추가된 상황</li>
<li>추가된 최신 commit 들을 로컬로 가져온다
<strong>git fetch upstream master</strong> (pull = fetch + merge)
fetch만 하면 .git 히스토리 창고에만 저장</li>
<li>&#39;upstream/master&#39; 브랜치가 자동 생성됨</li>
<li>현재 Base를 최신으로 갱신한다
<strong>git rebase upstream/master</strong></li>
</ol>
<blockquote>
<h4 id="👉-2개-commit-있었던-과거로-rewind한-뒤-파일-3개-추가하기">👉 2개 commit 있었던 과거로 rewind한 뒤 파일 3개 추가하기</h4>
</blockquote>
<ol>
<li>git rebase -i --root (i: interactive, root: 최초커밋부터 조회)</li>
<li>두번째 commit 위치에 pick -&gt; edit 으로 수정</li>
<li>touch hello_1.c &amp;&amp; git add hello_1.c &amp;&amp; git commit -m &#39;test: add hello_1.c&#39;</li>
<li>git rebase --continue : 되돌렸던 로그 복원</li>
</ol>
<blockquote>
<p> 👉 ** 위에서 추가한 3개의 커밋 1개로 합치기(최초 1개 커밋만 남기기)**</p>
</blockquote>
<ol>
<li>git rebase -i --root (i: interactive, root: 최초커밋부터 조회)</li>
<li>세 번째 파일 commit 위치에 pick -&gt; edit 으로 수정</li>
<li>git reset --soft HEAD~1 : 최신 커밋 삭제, 내용은 보존</li>
<li>git commit --amend : 최신커밋 덮어쓰기 (수정파일에 3번째 파일 추가됨, 커밋메세지 수정)</li>
<li>git rebase --continue : 되돌렸던 로그 복원</li>
<li>(1~5)반복해서 두 번째 커밋, 첫 번째 커밋과 합치기</li>
<li>git status로 상태 확인</li>
</ol>
<blockquote>
<p>reset --soft HEAD~1 : --hard와는 다르게 commit 정보만 삭제하고 파일 변경분은 남겨둔다.
git rebase --abort : rebase 작업을 취소하고 원래 상태로 되돌아감
git reset --hard origin/master : 히스토리 전체 원상 복구 하는 방법</p>
</blockquote>
<blockquote>
<h4 id="❓-blame-기능을-사용하는-이유">❓ blame 기능을 사용하는 이유</h4>
</blockquote>
<ol>
<li>특정 소스 라인을 수정해야하는 상황
760번째 라인이 문제가 있다고 판단 =&gt; 760번째 라인을 만든 commit을 찾아내서 이해한 다음 =&gt; Bug fix commit 생성해서 수정한 뒤 제출</li>
<li>소스 분석 / 리딩</li>
<li>클래스, 함수 추가 =&gt; 역추적</li>
</ol>
<blockquote>
<h4 id="👉-충돌상황-해결하는-방법-실습">👉 충돌상황 해결하는 방법 실습</h4>
</blockquote>
<ol>
<li>git remote add upstream &#39;클론할 프로젝트 주소&#39; : 포크한 본래 프로젝트 주소 추가하기</li>
<li>git fetch upstream master : 새로 추가된 사항 가져오기</li>
<li>git rebase upstream/master : 새로 추가된 사항으로 rebase 진행</li>
<li>git status : 충돌 상황 확인하기</li>
<li>git diff : 수정사항 확인</li>
<li>nano README.md : 에디터 이용해서 충돌 부분 수동으로 수정 및 정리하기</li>
<li>git add README.md : 수정 파일 올리기</li>
<li>git rebase --continue : rebase 돌아가기</li>
<li>git push origin master -f : 마스터로 변경사항 강제 푸쉬</li>
</ol>
<br>

<h5 id="기본-ppt--고급-ppt"><a href="https://docs.google.com/presentation/d/1a01PRIkVKNboEVZykPXjibh4-yxoJXkvV1j04iUbd28/edit#slide=id.g8666479880_0_1378">기본 ppt</a> / <a href="https://docs.google.com/presentation/d/1wZNt_3AHDg7guPjIn1vD-CYXupGzHU_c2wWb4PSwMJg/edit#slide=id.g86633d5308_0_270">고급 ppt</a></h5>
]]></description>
        </item>
        <item>
            <title><![CDATA[Swiper 안드로이드 오류]]></title>
            <link>https://velog.io/@suyeon-hong/Swiper-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@suyeon-hong/Swiper-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Tue, 07 Jun 2022 13:21:42 GMT</pubDate>
            <description><![CDATA[<pre><code>&lt;link
  rel=&quot;stylesheet&quot;
  href=&quot;https://unpkg.com/swiper@8/swiper-bundle.min.css&quot;
/&gt;

&lt;script src=&quot;https://unpkg.com/swiper@8/swiper-bundle.min.js&quot;&gt;&lt;/script&gt;</code></pre><p>안드로이드에서만 슬라이드 클릭시 해당 슬라이드가 활성화되는 오류가 발생
SlideToClickedSlide: true 속성을 넣었을때 실행되는 이벤트인데
SlideToClickedSlide: false 로 속성지정을 해주어도 계속 발생했다..</p>
<p>결론</p>
<p>최신버전이라 안정화가 덜 되어있어 발생했던 버그..
8버전을 7버전으로 바꾸어주니 사라졌다!</p>
<p>그리고 슬라이드 바깥으로 버튼을 내보내고 싶을 때
슬라이드를 감싸는 부모태그를 하나 더 만들어 슬라이드 바깥으로 버튼을 빼주었었는데
이렇게 하지 않아도 swiper 속성을 static으로 바꾸어주면 가능했다!
하지만 위치를 잡아주기위해 부모태그로 한번 더 감싸고 부모태그에 position:relative값을 줘야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최신 CSS 속성]]></title>
            <link>https://velog.io/@suyeon-hong/%EC%B5%9C%EC%8B%A0-CSS-%EC%86%8D%EC%84%B1</link>
            <guid>https://velog.io/@suyeon-hong/%EC%B5%9C%EC%8B%A0-CSS-%EC%86%8D%EC%84%B1</guid>
            <pubDate>Tue, 31 May 2022 23:11:07 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p>color-mix() 색상 혼합 기능
background-color: color-mix(red30%, blue70%);</p>
</li>
<li><p>accent-color HTML 요소의 색상 변경
:hover, :active 등등 라디오버튼, 셀렉트버튼 등의 기본 속성 컬러를 바꿀 수 있음</p>
</li>
<li><p>color-contrast() 배경색에 대비되는 색 지정
color: color-contrast(red) / color-contrast(blue vs red, pink, yellow)
(배경색 vs 원하는 색1, 원하는 색2, 원하는색 3) 배경색과 가장 대비되는 색으로 지정해줌</p>
</li>
<li><p>insert 페이지 섹션 안으니 클릭, 포커스와 같은 유저 상호작용을 중단시킴
유저가 이미 한 번 클릭한 뒤 버튼을 얼리거나, 양식을 전송하고 유저가 다른곳을 클릭하지 못하게 할 때 사용할 수 있음</p>
<form insert></form>
</li>
<li><p>:has 부모요소에 특정 자식이 있는지 체크해서 스타일 적용
form:has(button) {color:red;}
form:has(:not li) {color: blue;}</p>
</li>
<li><p>lvh, svh, dvh
lvh: 가장 큰 viewport 높이
svh: 가장 작은 viewport 높이
dvh: 동적 viewport 높이</p>
</li>
<li><p>@nest 중첩 셀렉팅을 도와주고 코드 반복을 줄여주는 문법
&amp;이 부모태그를 지칭</p>
<pre><code>.header {
background-color: blue;
&amp; p {
 font-size: 16px;
 &amp; span {
   &amp;:hover {
     color: green
   }
 }
}
}</code></pre></li>
<li><p>@scope: 스타일 범위 지정, 테마별로 스타일 분기처리할 때 좋음</p>
</li>
<li><p>@container: 반응형 디자인에서 페이지 넓이뿐 아니라 부모요소의 넓이를 기준으로 잡을 수 있음</p>
</li>
<li><p>Custom-media 쿼리 : 미디어 쿼리를 변수화해서 재사용 가능</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[모바일 100vh 오류 해결방법]]></title>
            <link>https://velog.io/@suyeon-hong/%EB%AA%A8%EB%B0%94%EC%9D%BC-100vh-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@suyeon-hong/%EB%AA%A8%EB%B0%94%EC%9D%BC-100vh-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 31 May 2022 23:04:49 GMT</pubDate>
            <description><![CDATA[<h3 id="발생-오류">발생 오류</h3>
<p>화면을 가득채우는 팝업페이지를 구현해야해서 높이값으로 100vh를 설정해주었다.
PC에서는 문제가 없었지만 모바일에서 확인해보니 스크롤이 생기는 문제가 발생했다.</p>
<p>이유는 모바일 브라우저에서 100vh는 상단 주소창 영역과 하단 네비게이션바 영역을 포함하기 때문이었다.</p>
<br>

<h3 id="해결-방법">해결 방법</h3>
<ol>
<li>스크립트를 이용해 스크린 높이값을 구해준 뒤 css에 넣어주는 방식을 이용했다.</li>
</ol>
<pre><code>//script
funciton setScreenSize() {
  let vh = window.innerHeight * 0.01;

  document.documentElement.style.setProperty(&#39;--vh&#39;, `${vh}px`);
}

setScreenSize();

//css
height: calc(var(--vh, 1vh) * 100);</code></pre><br>

<h3 id="또다른-오류">또다른 오류</h3>
<p>문제가 해결된 줄 알았지만 테스트과정에서 갤럭시탭 가로모드 -&gt; 세로모드 변환시 높이가 정상적으로 돌아오지 않는 문제가 발생했다.</p>
<br>

<h3 id="해결방법">해결방법</h3>
<ol start="2">
<li>html, body, body 내부의 가장 상위 태그 에 &#39;height: 100%&#39; 속성을 넣어주었다.</li>
</ol>
<pre><code>//css
html,body{
    height: 100%;
}
wrapper{
    height: 100%;
}</code></pre><p>굳이 스크립트를 사용하지않아도 css만으로 간단히 해결이 가능한 문제였다.
오히려 스크립트를 사용했을 때 오류가 있었던 반면, 스크립트 대신 css를 사용했을땐 다른 오류가 발견되지 않았다.
html, css에 대해 쉽게 생각했었는데 일을 하다보니 기본적인 것들이 얼마나 중요한지 깨달아가고 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[파라미터값 가져오는 방법]]></title>
            <link>https://velog.io/@suyeon-hong/%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EA%B0%92-%EA%B0%80%EC%A0%B8%EC%98%A4%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@suyeon-hong/%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0%EA%B0%92-%EA%B0%80%EC%A0%B8%EC%98%A4%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 31 May 2022 22:46:46 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>location.href : 현재 페이지 전체 URL 반환</p>
</li>
<li><p>location.search : 현재 페이지 URL의 Parameter 반환</p>
</li>
<li><p>new URLSearchParams() : location.search 안에 존재하는 [key, value] 형식으로 묶여있는 모든 파라미터를 배열로 반환</p>
</li>
</ul>
<br>

<p>** 모든 파라미터 가져오는 방법**</p>
<pre><code>const locationSearch = &#39;?name=user&amp;age=20&#39;;
const searchParams = new URLSearchParams(locationSearch);

for (const param of searchParams) {
  console.log(param);
}
// 결과
[&#39;name&#39;, &#39;user&#39;]
[&#39;age&#39;, &#39;20&#39;]</code></pre><br>


<p>** 전체 URL에서 특정 파라미터만 가져오는 방법 **</p>
<pre><code>const urlParams = new URL(location.href).searchParams;
const name = urlParams.get(&#39;name&#39;);

console.log(name)</code></pre><br>]]></description>
        </item>
        <item>
            <title><![CDATA[확대방지 meta 태그]]></title>
            <link>https://velog.io/@suyeon-hong/%ED%99%95%EB%8C%80%EB%B0%A9%EC%A7%80-meta-%ED%83%9C%EA%B7%B8</link>
            <guid>https://velog.io/@suyeon-hong/%ED%99%95%EB%8C%80%EB%B0%A9%EC%A7%80-meta-%ED%83%9C%EA%B7%B8</guid>
            <pubDate>Tue, 31 May 2022 22:13:40 GMT</pubDate>
            <description><![CDATA[<pre><code>&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot; /&gt;</code></pre><p>viewport 부분에 &#39;user-scalable=no&#39; 추가하기</p>
<br>

<ul>
<li><p>width : 가로 크기
숫자로도 크기 지정 가능함
device-width 로 값을 지정할 경우 기기의 화면 크기에 맞춰짐
height=device-height 값으로 세로크기의 비율도 지정할 수 있음</p>
</li>
<li><p>initial-scale : 로드되었을 때 줌 레벨 </p>
</li>
</ul>
<p>1.0 (= 100%)</p>
<ul>
<li><p>maximum-scale : 최대 줌 레벨 지정
기본값 0.25</p>
</li>
<li><p>minimum-scale : 최소 줌 레벨 지정
기본값 1.6</p>
</li>
<li><p>user-scalable : 확대축소 가능한지 yes, no 값으로 지정 
기본값은 yes
no 값으로 설정할경우 input영역 선택시 확대되는 것을 막고, 사용자가 화면을 확대, 축소하는 것을 방지함</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[바닐라자바스크립트로 구현한 미니게임 회고]]></title>
            <link>https://velog.io/@suyeon-hong/%EB%B0%94%EB%8B%90%EB%9D%BC%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%9C-%EB%AF%B8%EB%8B%88%EA%B2%8C%EC%9E%84-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@suyeon-hong/%EB%B0%94%EB%8B%90%EB%9D%BC%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%9C-%EB%AF%B8%EB%8B%88%EA%B2%8C%EC%9E%84-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 31 May 2022 22:03:33 GMT</pubDate>
            <description><![CDATA[<p>드림코딩 프론트엔드 필수 브라우저 101 강의를 듣고 실습 프로젝트로 진행한 미니게임</p>
<h3 id="📋-구현내용">📋 구현내용</h3>
<p>✔ 플레이버튼 클릭시 게임 시작
✔ 당근 클릭 시 카운트 -1, 카운트 0 되면 게임 종료
✔ 벌레 클릭 시 게임 종료
✔ 타이머 0초 되면 게임 종료
✔ 게임 종료시 팝업창 노출, 게임 재시작 가능</p>
<br>

<h3 id="새롭게-알게-된-내용">새롭게 알게 된 내용</h3>
<p>.getBoundingClientRect()
컨텐츠의 x, y, width, height 값을 반환하는 함수
게임필드 영역을 확인하기 위해 width, height 값을 활용했다.</p>
<p>element.matches(&#39;selector&#39;)
element와 selector가 같은지 아닌지 확인해주는 메소드, true, false 반환
이벤트 버블링을 활용해 게임필드영역에 클릭이벤트를 적용하고 클릭된 타겟이 당근, 벌레인지 구별할 때 사용했다.</p>
<p>이전엔 항상 classList.contains()를 사용했었는데 matches로도 같은 기능을 사용할 수 있다는걸 알게됐다.</p>
<p>sound.currenTime = 0;
음악재생 초기화</p>
<p>각 기능별로 클래스 함수를 만들어 모듈화 시켰다.
클래스 함수를 이용하다보니 자연스럽게 this를 이용하고 this의 속성을 경험할 수 있었다.
이론으로만 외우고 있던 this 바인딩..
클릭이벤트에 함수를 적용하기위해서는 this바인딩이 필요하다.
해당 함수 안에서의 this값이 필요하기 때문!
화살표 함수를 이용하면 따로 바인딩 처리를 해주지않아도 되서 화살표함수를 사용했다.</p>
<p>자바스크립트로 타입 보장하기
Object.freeze() 를 이용해 문자열을 고정문자열로 만들어 주었다.
객체를 동결시키는 메소드로, 내부 속성을 변경할 수 없다는 특징을 갖고 있다.
게임종료시 게임 결과를 win, lose, cancle 문자열로 받아서 각기 다른 메세지를 제공한다.
Reason변수에 할당된 속성이기때문에 Reason 입력시 포함하고있는 3가지 속성을 확인가능해 오타를 방지할 수 있고, 자동입력이 가능하다는 장점이 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSR, SSR 렌더링이란]]></title>
            <link>https://velog.io/@suyeon-hong/CSRSSR-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@suyeon-hong/CSRSSR-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Thu, 07 Apr 2022 02:43:49 GMT</pubDate>
            <description><![CDATA[<h2 id="csr">CSR</h2>
<blockquote>
<p>클라이언트 사이드 렌더링 이란 사용자의 요청에 따라 필요한 부분만 응답 받아 렌더링 하는 방식</p>
</blockquote>
<ul>
<li>변경된 부분과 관련된 데이터만 가져오므로 SSR보다 빠른 속도</li>
<li>변경된 부분만 요청함으로써 서버의 부담을 줄임</li>
<li>첫 화면을 볼 때까지 시간이 오래걸림, 처음에 접속하면 빈 화면만 보임</li>
<li>app.js가 모든 정보를 담고있음</li>
<li>SEO 검색엔진에 노출되지않음</li>
</ul>
<p>장점 : 빠른 속도(초기화면 렌더링시x), 서버 부하 감소, 사용자 친화적
단점 : 느린 초기로딩, SEO에 불리</p>
<br>

<h2 id="ssr">SSR</h2>
<blockquote>
<p>서버사이드 렌더링의 약자로, 서버로부터 완전하게 만들어진 html파일을 받아와 페이지 전체를 렌더링 하는 방식</p>
</blockquote>
<ul>
<li>모든 데이터가 이미 HTML에 담겨진 채로 브라우저에 전달되기 때문에 검색엔진 최적화에 유리, 빠른 초기 로딩속도</li>
<li>TTV(Time To View)와 TTI(Time To Interact) 간에 시간 간격이 존재한다. (사용자가 버튼을 클릭하거나 이동하려고 해도 아무런 반응이 없을 수 있음)</li>
<li>페이지를 요청할 때마다 새로 고침 되기 때문에 사용자 경험이 떨어짐</li>
<li>페이지를 구성하는 모든 리소스를 준비해서 응답하므로 서버 부담 증가</li>
</ul>
<p>장점 : 검색엔진최적화에 유리, 빠른 초기로딩
단점 : 사용자 친화적이지 않음, 요청응답시 화면 깜빡임, 서버 부하</p>
<br>

<h3 id="❓-렌더링-방식-선택기준">❓ 렌더링 방식 선택기준</h3>
<p>서비스, 프로젝트, 콘텐츠의 성격에 따라 달라진다.</p>
<ol>
<li>SSR</li>
</ol>
<ul>
<li>상위노출 필요</li>
<li>페이지마다 데이터가 자주 바뀌는 경우</li>
<li>누구에게나 동일한 내용을 노출</li>
</ul>
<ol start="2">
<li>CSR</li>
</ol>
<ul>
<li>개인정보 데이터를 기준으로 노출</li>
<li>보다 나은 사용자 경험 제공</li>
<li>상위노출보다 고객의 데이터 보호가 더 중요한 경우</li>
</ul>
<br>

]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저 저장소 차이점]]></title>
            <link>https://velog.io/@suyeon-hong/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%A0%80%EC%9E%A5%EC%86%8C-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@suyeon-hong/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EC%A0%80%EC%9E%A5%EC%86%8C-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Thu, 24 Mar 2022 14:13:05 GMT</pubDate>
            <description><![CDATA[<p>HTML5에서는 웹 사이트의 데이터를 클라이언트에 저장할 수 있는 새로운 자료구조인 Web Storage 스펙이 포함되어있다.</p>
<h3 id="web-storage">Web Storage</h3>
<blockquote>
<p><strong>key:value</strong> 쌍으로 데이터를 저장하고 <strong>key를 기반으로 데이터를 조회</strong>하는 패턴이다.
영구저장소(LocalStorage)와 임시저장소(SessionStorage)를 따로 두어 데이터의 지속성을 구분하여 응용 환경에 맞는 선택이 가능하다.
Web Storage는 기본 웹 환경의 Cookie와 매우 유사한 개념이다.</p>
</blockquote>
<h4 id="특징">특징</h4>
<ul>
<li><p>서버 전송이 없다.
저장된 데이터가 클라이언트에 존재할 뿐 서버로 전송은 이루어 지지 않는다.</p>
</li>
<li><blockquote>
<p>네트워크 트래픽 비용을 줄여준다.</p>
</blockquote>
</li>
<li><p>단순 문자열을 넘어 객체정보를 저장할수 있다.
문자열 기반 데이터 이외에 체계적으로 구조화된 객체를 저장할 수 있는 점은 개발편의성을 제공해주는 주요한 장점이다. 단, 브라우저의 지원 여부를 확인해 봐야 하는 항목이다.</p>
</li>
<li><p>용량의 제한이 없다.</p>
</li>
<li><p>영구 데이터 저장이 가능하다.</p>
</li>
<li><blockquote>
<p>만료 기간의 설정이 없다. 즉, 한번 저장한 데이터는 영구적으로 존재한다.</p>
</blockquote>
</li>
<li><p>Cookie와 마찬가지로 사이트의 도메인 단위로 접근이 제한된다.</p>
</li>
</ul>
<br>


<h4 id="localstorage">localStorage</h4>
<ul>
<li><p>저장한 데이터를 <strong>영구적으로 보관</strong>할 수 있다.
(브라우저를 종료하더라도 다음번에 접속했을 때 그 데이터를 사용할수 있다.)</p>
</li>
<li><p><strong>도메인 마다 별도의 localStorage가 생성</strong>된다.
Windows 전역 객체의 LocalStorage라는 컬렉션을 통해 저장과 조회가 이루어 진다.
도메인만 같으면 전역으로 공유가 가능하다.</p>
</li>
</ul>
<br>

<h4 id="sessionstorage">sessionStorage</h4>
<ul>
<li><p>데이터가 지속적으로 보관되지 않는다.
현재 페이지가 브라우징 되고 있는 <strong>브라우저 컨텍스트 내에서만 데이터가 유지</strong>된다.</p>
</li>
<li><p>Windows 전역 객체의 sessionStorage 라는 컬렉션을 통해 저장과 조회가 이루어진다.
브라우저가 종료되면 데이터도 같이 지워진다. (<strong>브라우저가 종료되면 SssionStorage도 삭제</strong>)</p>
</li>
<li><p><strong>브라우저마다 별도의 sessionStorage가 생성</strong>된다.
같은사이트 같은 도메인이라 할지라도 브라우저가 다르면 서로 다른 영역이된다. (브라우저 컨텍스트가 다르기 때문)
브라우저를 하나 더 실행해서 같은 페이지를 실행 했을때, 이 두페이지의 sessionStorage는 각각 별개의 영역으로 침범하지 못한다.</p>
</li>
<li><p>자동 임시저장 기능</p>
</li>
</ul>
<br>

<h3 id="cookie">Cookie</h3>
<blockquote>
<p>Cookie란 웹사이트에 의해 <strong>유저의 컴퓨터에 놓여지는 작은 텍스트 파일</strong>들이다.
Cookie는 사이트에서 <strong>방문한 페이지</strong>를 저장하거나 <strong>유저의 로그인 정보</strong>를 저장하는 등 다양한 방법으로 사용된다. 그리고 <strong>문자열만 저장</strong>할 수 있다는 제한이 있다.</p>
</blockquote>
<h4 id="특징-1">특징</h4>
<ul>
<li><p>매번 서버로 전송된다. (서버 데이터를 공유)
웹사이트에서 쿠키를 설정하면 이후 <strong>모든 웹 요청은 쿠키 정보를 포함하여 서버로 전송</strong>된다.</p>
</li>
<li><p>제한적인 용량
쿠키는 <strong>개수와 용량에 제한</strong>이 있는데, 하나의 사이트에서 저장할수 있는 최대 쿠키수와 용량은 20개, 4KB로 제한되어있다. 그러나 쿠키도 하위키를 이용하면 이러한 제한을 일부 해소할수 있지만, 대부분 쿠키의 제한으로 까지 데이터를 저장할 일이 없다.</p>
</li>
<li><p><strong>반 영구적으로 데이터 저장이 가능</strong>하다
쿠키는 <strong>만료일자를 지정</strong>하게 되어 있어 만료일자로 <strong>지정된 날짜에 쿠키는 제거</strong>된다.
만약 만료일자를 지정하지 않으면 Session cookies 된다. 만일 영구 쿠키를 원한다면 만료일자를 굉장히 멀게 설정하여 해결할 수 있다.</p>
</li>
</ul>
<br>

<h4 id="💡-서버에-쿠키가-전송되는-이유">💡 서버에 쿠키가 전송되는 이유</h4>
<p>서버는 요청 자체만으로 그 요청이 누구에게서 오는지 알수 없기 때문에 응답을 보낼수 없다.
이때 쿠키에 나에 대한 정보를 담아 서버로 보내면, 서버는 쿠키를 읽어서 내가 누군지 파악한다.
쿠키는 <strong>서버와 클라이언트 간의 지속적인 데이터 교환을 위해 만들어 졌기 때문에</strong> 서버로 계속 전송된다.</p>
<br>

<h4 id="persistent-cookies">persistent cookies</h4>
<ul>
<li>만료일을 포함하지 않는다.</li>
<li>브라우저 탭이 열려있는 동안에만 저장된다.</li>
<li>은행 웹사이트에서 사용한다.</li>
</ul>
<br>

<h4 id="session-cookies">session cookies</h4>
<ul>
<li>만료일을 가진다.</li>
<li>만료일 까지 유저의 저장소에 저장되고 만료일이 지나면 삭제된다.</li>
</ul>
<br>


<h3 id="데이터-범위-및-보안">데이터 범위 및 보안</h3>
<p>WebStorage의 보안은 서로 다른 도메인의 데이터 침범을 막고는 있지만 클라이언트, 즉 사용자를 막고 있지는 않다. 클라이언트는 얼마든지 저장된 값을 임의로 수정이 가능하다. 이것은 쿠키와 동일한 개념이다. 그렇다고 쿠키에 비해 별다른 보안 취약점을 더 가진 것은 아니다. 따라서 개발자는 사용자에 의한 이러한 임의 변경에 항상 예의 주시하고 방어 코드의 작성을 잊지 말아야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이벤트 루프란?]]></title>
            <link>https://velog.io/@suyeon-hong/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84</link>
            <guid>https://velog.io/@suyeon-hong/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84</guid>
            <pubDate>Thu, 24 Mar 2022 11:24:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>Event Loop는 Call Stack과 Callback Queue의 상태를 체크하여, Call Stack이 빈 상태가 되면, Callback Queue의 첫번째 콜백을 Call Stack으로 밀어넣는 역할을 한다.</strong></p>
</blockquote>
<p><img src="https://images.velog.io/images/suyeon-hong/post/50b3b263-b815-44fe-88fb-1452cb7f2968/%EC%9D%B4%EB%B2%A4%ED%8A%B8%EB%A3%A8%ED%94%84.png" alt=""></p>
<ul>
<li>V8 엔진에서 함수가 호출되면 Call Stack에 쌓인다.</li>
<li>Stack의 선입후출의 룰에 따라 제일 마지막에 들어온 함수가 먼저 실행되며, Stack에 쌓여진 함수는 실행이 완료되면 Call Stack에서 빠져나간다.</li>
<li>비동기함수가 실행될 경우 Web API가 호출된다.</li>
<li>Web API는 비동기함수의 콜백함수를 Callback Queue에 밀어넣는다.</li>
<li>Event Loop는 Call Stack이 빈 상태가 되면 Callback Queue에 있는 첫번째 콜백을 Call Stack으로 이동시킨다. (이러한 반복적인 행동을 틱(tick)이라 한다.)</li>
</ul>
<br>

<h3 id="js-engine">JS Engine</h3>
<blockquote>
<p>자바스크립트 엔진은 <strong>Memory Heap</strong>과 <strong>Call Stack</strong>으로 구성되어 있다.
가장 유명한 것이 구글의 V8 engine이다.
자바스크립트는 <strong>단일 스레드 프로그래밍 언어</strong>이며, 이것은 <strong>Call Stack이 한 개</strong>라는 이야기다.
(한 번에 한 가지씩 일을 처리하는 것을 의미)</p>
</blockquote>
<ul>
<li>Memory Heap: 메모리 할당이 일어나는 곳</li>
<li>Call Stack: 코드가 실행될 때 쌓이는곳, stack 형태로 쌓인다.</li>
<li>stack: 자료구조 중 하나로 선입후출의 룰을 따른다.</li>
</ul>
<br>

<h3 id="web-api">Web API</h3>
<blockquote>
<p>web api는 자바스크립트 엔진이 아닌 <strong>브라우저에서 제공하는 API</strong>로, 대표적으로 <strong>DOM, Ajax, Timeout</strong> 등이 있다.
콜스택에서 실행된 비동기 함수는 Web API를 호출하고, Web API는 콜백함수를 콜백큐에 밀어넣는다.</p>
</blockquote>
<br>

<h3 id="callback-queue">Callback Queue</h3>
<blockquote>
<p><strong>비동기적으로 실행된 콜백함수(Web API에서 넘어오는 함수)가 보관되는 영역</strong>이다.</p>
</blockquote>
<ul>
<li>Queue(큐): 자료구조 중 하나로, 선입선출의 룰을 따른다.</li>
</ul>
<br>


<h4 id="💡-자바스크립트는-단일-스레드-프로그래밍-언어라-한번에-하나씩-밖에-실행할-수-없지만-web-api-callback-queue-event-loop-덕분에-멀티-스레드-처럼-보여진다">💡 자바스크립트는 단일 스레드 프로그래밍 언어라 한번에 하나씩 밖에 실행할 수 없지만 Web API, Callback Queue, Event Loop 덕분에 멀티 스레드 처럼 보여진다.</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[GET, POST의 특징 및 차이]]></title>
            <link>https://velog.io/@suyeon-hong/GET-POST%EC%9D%98-%ED%8A%B9%EC%A7%95-%EB%B0%8F-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@suyeon-hong/GET-POST%EC%9D%98-%ED%8A%B9%EC%A7%95-%EB%B0%8F-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 20 Mar 2022 07:30:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>GET</strong> 방식은 이름 그대로 <strong>무언가를 가져오는 것</strong>
<strong>POST</strong> 방식은 포스트를 붙이듯이 <strong>무언가를 만들거나 수정하는 것</strong></p>
</blockquote>
<ul>
<li><p>Get은 서버에서 어떤 데이터를 가져와서 보여줄때 사용</p>
</li>
<li><blockquote>
<p>어떤 값이나 내용, 상태등을 바꾸지 않는 경우에 사용</p>
</blockquote>
</li>
<li><blockquote>
<p>글의 내용에 대한 목록을 보여주는 경우나, 글의 내용을 보는 경우</p>
</blockquote>
</li>
<li><p>Post는 서버상의 데이터 값이나 상태를 바꾸기 위해서 사용</p>
</li>
<li><blockquote>
<p>글의 내용을 저장하고, 수정하는 경우</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="📍-get-방식">📍 GET 방식</h3>
<ul>
<li>클라이언트가 서버로 데이터를 요청하기 위해 사용되는 Method</li>
<li>GET 요청을 할 때 Body 부분은 비어있고 헤더에 Body의 콘텐츠 타입을 명시하는 Content-Type 헤더 필드도 적지 않는다.</li>
<li>URL뒤에 쿼리 스트링(Key와 Value)을 붙이고 HTTP 패킷의 헤더에 포함해서 서버에 데이터를 요청한다.</li>
</ul>
<h4 id="특징">특징</h4>
<ul>
<li>URL에 쿼리 스트링(데이터)을 붙여서 서버에 전송</li>
<li>데이터를 Header(헤더)에 포함하여 전송</li>
<li>URL에 정보들이 그대로 노출되기 때문에 POST 방식보다 상대적으로 보안에 취약</li>
<li>캐싱이 가능</li>
<li>POST 방식보다 상대적으로 전송 속도가 빠름</li>
<li>전송하는 데이터양에 한계가 있음 (브라우저마다 GET 요청 길이 제한 존재)</li>
<li>브라우저 히스토리에 기록이 남음</li>
<li>브라우저마다 글자 수 제한이 있기 때문에 게시판의 게시물, 목록 조회와 같은 간단한 데이터 요청할 때 적합</li>
</ul>
<p>💡 캐싱이란 한번 접근 후 또 요청할 시 빠르게 접근하기 위해 레지스터에 데이터를 저장시켜 놓는 것</p>
<br>

<h3 id="📍-post-방식">📍 POST 방식</h3>
<ul>
<li>클라이언트가 서버로 데이터를 전송해 리소스를 추가하거나 생성하기 위해 사용되는 Method</li>
<li>POST 요청 시 HTTP 패킷의 헤더에 Body의 콘텐츠 타입을 명시하는 Content-Type 헤더 필드를 포함하고 HTTP 패킷의 Body에는 데이터를 담아서 서버로 전송한다.</li>
</ul>
<h4 id="특징-1">특징</h4>
<ul>
<li>데이터들을 URL뒤에 붙여서 서버로 보내는 것이 아닌 Body에 담아서 전송</li>
<li>요청 헤더의 Content-Type에 콘텐츠 타입을 명시</li>
<li>데이터들이 URL에 노출되지 않기 때문에 GET 방식보다 상대적으로 보안적</li>
<li>데이터들을 Body에 담기 때문에 서버로 보내는 데이터의 양은 제한 없음</li>
<li>URL에 데이터가 노출되지 않으므로 캐싱 불가</li>
<li>클라이언트에서 인코딩, 서버에서 디코딩</li>
<li>요청받는 시간제한 존재</li>
<li>브라우저 히스토리에 기록이 남지 않음</li>
<li>보통 서버의 값이나 상태를 변경하기 위해 사용되므로 글쓰기, 글 수정과 같은 작업에 적합하다.</li>
</ul>
<br>

<h3 id="👁🗨-비교표">👁‍🗨 비교표</h3>
<table>
<thead>
<tr>
<th align="center">HTTP Method</th>
<th align="center">GET 방식</th>
<th align="center">POST 방식</th>
</tr>
</thead>
<tbody><tr>
<td align="center">URL 예시</td>
<td align="center"><code>http://localhost:3000/login?id=admin&amp;pw=1234</code></td>
<td align="center"><code>http://localhost:3000/login</code></td>
</tr>
<tr>
<td align="center">데이터가 담기는 곳</td>
<td align="center">HTTP 패킷 Header</td>
<td align="center">HTTP 패킷 Body</td>
</tr>
<tr>
<td align="center">리소스 전달 방식</td>
<td align="center">쿼리스트링</td>
<td align="center">HTTP Body</td>
</tr>
<tr>
<td align="center">HTTP 응답 코드</td>
<td align="center">200</td>
<td align="center">201</td>
</tr>
<tr>
<td align="center">URL에 데이터 노출 여부</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="center">캐싱 가능 여부</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="center">브라우저 기록</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="center">북마크 추가</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="center">데이터 길이 제한</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="center">멱등성(idempotent)</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
</tbody></table>
<p>💡 <strong>멱등성</strong>은 <strong>연산을 여러 번 하더라도 결과가 달라지지 않는 성질</strong>을 의미하며, get 요청의 경우 여러 번 요청해도 응답이 같지만 post 요청의 경우엔 리소스를 새로 생성하거나 업데이트하므로 서버에게 동일한 요청을 여러 번 전송해도 응답은 항상 다를 수 있다.</p>
<br>

<h3 id="📍-post-vs-put">📍 POST vs PUT</h3>
<ul>
<li>POST는 INSERT, <strong>PUT은 UPDATE</strong></li>
<li>POST는 멱등하지 않고 PUT은 멱등하다.</li>
<li>POST는 새로운 데이터를 계속 생성하기 때문에 요청시마다 데이터를 생성하지만, PUT은 사용자가 데이터를 지정하고 수정하는 것이기 때문에 같은 요청을 계속하더라도 데이터가 계속 생성되지 않는다.</li>
</ul>
<br>

<h3 id="📍-put-vs-patch">📍 PUT vs PATCH</h3>
<ul>
<li>PUT은 해당 자원의 전체를 교체, <strong>PATCH는 일부를 변경</strong></li>
<li>PUT은 멱등하지만, PATCH는 멱등하지 않다.</li>
<li>PUT은 전체 자원을 업데이트 하기 때문에 동일 자원에 대해서 동일하게 PUT을 처리하는 경우 멱등하게 처리되는 반면 PATCH로 처리되는 경우 자원의 일부가 변경되기 때문에 멱등성을 보장할 수 없다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript this 정리]]></title>
            <link>https://velog.io/@suyeon-hong/javascript-this-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@suyeon-hong/javascript-this-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 20 Mar 2022 04:24:08 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>this는 함수를 호출할 때 결정</strong>된다.
this는 <strong>this가 바라보고 있는 객체</strong>를 말하며, this의 값은 <strong>함수를 호출하는 방법에 의해 결정</strong>된다.
누가 호출했나? 누가 = this</p>
</blockquote>
<br>

<h4 id="전역-공간에서-this가-바라보는-대상">전역 공간에서 this가 바라보는 대상</h4>
<ul>
<li>client(브라우저)에서는 window</li>
<li>Node.js에서는 global</li>
</ul>
<br>


<h4 id="원하는-대상으로-this-binding">원하는 대상으로 this binding</h4>
<ul>
<li><strong>call</strong> : <strong>함수를 호출할 때</strong>, 원하는 대상의 <strong>객체를 인자로</strong> 넘겨준다.</li>
<li><strong>apply</strong> : call 메서드와 완전히 같은 기능이나, 호출할 함수에 <strong>인자를 배열로</strong> 넘겨준다.</li>
<li><strong>bind</strong> : call과 비슷하지만, <strong>바로 호출하는 것이 아니라 대상을 묶어놓기(binding)만</strong> 하는 것</li>
</ul>
<br>


<h4 id="arrow-function">arrow function</h4>
<ul>
<li>this의 대상이 어떤 객체가 호출했느냐로 결정되지 않는다.</li>
<li>함수 내부에 this는 없으며, scope chain의 가장 가까운 this로 대상이 결정된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[실행컨텍스트 - 클로저, 스코프]]></title>
            <link>https://velog.io/@suyeon-hong/%EC%8B%A4%ED%96%89%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%81%B4%EB%A1%9C%EC%A0%80-%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@suyeon-hong/%EC%8B%A4%ED%96%89%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%81%B4%EB%A1%9C%EC%A0%80-%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Sat, 19 Mar 2022 08:57:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>처음 코드를 실행(브라우저가 스크립트를 로딩해서 실행하는 것)하는 순간 <strong>모든 것을 포함하는 전역 컨텍스트</strong>가 생긴다.
전역 컨텍스트는 모든 것을 관리하는 환경으로, <strong>페이지가 종료될 때까지 유지</strong>된다.</p>
</blockquote>
<br>

<h3 id="컨텍스트의-원칙">컨텍스트의 원칙</h3>
<ul>
<li>전역 컨텍스트 하나 생성 후, 함수를 호출할 때마다 함수 컨텍스트가 생긴다.</li>
<li>컨텍스트 생성 시 컨텍스트 안에 변수객체(arguments, variable), scope chain, this가 생성된다.</li>
<li>컨텍스트 생성 후 함수가 실행되면서 사용되는 변수들은 변수 객체 안에서 값을 찾고, 없다면 스코프 체인을 따라 올라가며 찾는다.</li>
<li>함수 실행이 마무리되면 해당 컨텍스트는 사라진다. (클로저 제외)</li>
<li>페이지가 종료되면 전역 컨텍스트가 사라진다.</li>
</ul>
<br>

<h3 id="클로저">클로저</h3>
<ul>
<li><p><strong>함수를 선언할 때 만들어진 scope가 사라진 후에도 scope에 저장되었던 변수를 사용할 수 있는 함수</strong></p>
</li>
<li><blockquote>
<p>어떤 함수 A에서 선언한 변수 a를 참조하는 내부함수 B를 외부로 전달할 경우, A의 실행 컨텍스트가 종료된 이후에도 변수 a가 사라지지 않는 현상</p>
</blockquote>
</li>
<li><p><strong>클로저를 통한 은닉화</strong></p>
</li>
<li><blockquote>
<p>클로저를 사용하여 외부에서 변수에 직접 접근하는 것을 제한할 때 사용한다.</p>
</blockquote>
</li>
</ul>
<br>


<h3 id="스코프">스코프</h3>
<ul>
<li><p><strong>변수가 유효한(살아있는) 범위</strong></p>
</li>
<li><p><strong>Global Scope</strong></p>
<ul>
<li>코드 어디에서든지 참조 가능</li>
<li>var로 선언한 변수는 전역 객체에 속하게 된다.</li>
</ul>
</li>
<li><p><strong>Local Scope</strong></p>
<ul>
<li>scope의 범위는 <strong>함수</strong> 블록 내이다. ({} 블록과 상관이 없다) = 함수에 의해서만 scope가 생성된다.</li>
<li>let, const로 변수를 선언할 때의 scope의 범위는 블록({}) 단위이다.</li>
</ul>
</li>
<li><p><strong>스코프 체인</strong></p>
<ul>
<li>변수가 해당 scope에서 유효하지 않을 때, 안에서부터 바깥으로만 차례로 검색해 나가는 것</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[호이스팅(Hoisting)이란]]></title>
            <link>https://velog.io/@suyeon-hong/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@suyeon-hong/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sat, 19 Mar 2022 06:53:14 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>코드가 실행하기 전 변수선언/함수선언이 먼저 메모리에 저장되었다는 것을 의미하며, 곧 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상을 말한다.</strong></p>
</blockquote>
<ul>
<li><p>자바스크립트 엔진은 코드를 실행하기 전 실행 컨텍스트를 위한 과정에서 모든 선언(var, let, const, function, class)을 스코프에 등록한다.</p>
</li>
<li><p>코드 실행 전 이미 변수선언/함수선언이 저장되어 있기 때문에 선언문보다 참조/호출이 먼저 나와도 오류 없이 동작한다. (var 변수 선언, 함수선언문일 경우에만 해당)</p>
</li>
</ul>
<br>


<h3 id="변수의-호이스팅">변수의 호이스팅</h3>
<ul>
<li><p>자바스크립트의 모든 선언에는 호이스팅이 일어난다.</p>
</li>
<li><p>let, const, class를 이용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작하는 이유</p>
</li>
<li><blockquote>
<p>var 키워드는 선언 단계와 초기화 단계가 한번에 진행되어 메모리에 저장,</p>
</blockquote>
</li>
<li><blockquote>
<p>let과 const는 선언 단계와 초기화 단계가 분리되어 진행되며, 초기화되지 않은 상태로 선언만 메모리에 저장되기 때문에 일시적 사각지대에 빠져 호이스팅이 일어나지 않는 것처럼 보인다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="변수-생성-단계">변수 생성 단계</h3>
<ul>
<li><p>1단계: 선언 단계(Declaration phase)
변수를 실행 컨텍스트의 변수 객체에 등록한다.
이 변수 객체는 스코프가 참조하는 대상이 된다.</p>
</li>
<li><p>2단계: 초기화 단계(Initialization phase)
변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.
이 단계에서 변수는 undefined로 초기화 된다.</p>
</li>
<li><p>3단계: 할당 단계(Assignment phase)
undefined로 초기화된 변수에 실제 값을 할당한다.</p>
</li>
</ul>
<br>

<h3 id="함수선언문과-함수표현식에서의-호이스팅">함수선언문과 함수표현식에서의 호이스팅</h3>
<ul>
<li><p><strong>함수선언문은 호이스팅에 영향을 받지만, 함수표현식은 호이스팅에 영향을 받지 않는다.</strong></p>
</li>
<li><p><strong>함수선언문은 코드를 구현한 위치와 관계없이</strong> 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려진다.</p>
</li>
<li><p><strong>함수표현식은</strong> 함수선언문과 달리 <strong>선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.</strong></p>
<ul>
<li>함수표현식에서는 선언과 할당의 분리가 발생한다.<br></li>
<li>함수표현식의 선언이 호출보다 위에 있는 경우 - 정상 출력<br></li>
<li>함수표현식의 선언이 호출보다 아래에 있는 경우 (var 변수에 할당) - TypeError : not a function</li>
<li>-&gt; 호이스팅에 의해 undefined으로 지정되고, undefined은 함수로 인식되지않은 상태이기때문에 not a function 이라는 오류 발생<br></li>
<li>함수표현식의 선언이 호출보다 아래에 있는 경우 (const/let 변수에 할당) - ReferenceError : not defined</li>
<li>-&gt; 호이스팅이 이루어지지않아 선언이 되지 않은 상태이기때문에 not defined 라는 오류 발생</li>
</ul>
</li>
</ul>
<br>

<h3 id="호이스팅-우선순위동일한-변수명을-사용할-때">호이스팅 우선순위(동일한 변수명을 사용할 때)</h3>
<ul>
<li><strong>변수 선언 &gt; 함수 선언문</strong></li>
<li><strong>값이 할당되어 있지 않은 변수</strong>의 경우, <strong>함수선언문이 변수를 덮어쓴다.</strong></li>
<li><strong>값이 할당되어 있는 변수</strong>의 경우, <strong>변수가 함수선언문을 덮어쓴다.</strong></li>
</ul>
<br>

<h3 id="호이스팅-사용-시-주의할-점">호이스팅 사용 시 주의할 점</h3>
<ul>
<li>코드의 가독성과 유지보수를 위해 호이스팅이 일어나지 않도록 한다. (<strong>var 대신 let, const 사용하기</strong>)</li>
<li>호이스팅을 제대로 모르더라도 <strong>함수와 변수를 가급적 코드 상단부에서 선언</strong>하면, 호이스팅으로 인한 스코프 꼬임 현상은 방지할 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Heroku로 웹사이트 배포하는 방법]]></title>
            <link>https://velog.io/@suyeon-hong/Heroku%EB%A1%9C-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@suyeon-hong/Heroku%EB%A1%9C-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 19 Mar 2022 05:27:13 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p><a href="https://id.heroku.com/login">Heroku</a> 가입 및 로그인하기</p>
</li>
<li><p>Create a new app으로 배포 할 새로운 앱 만들기</p>
</li>
<li><p>App name 및 region 지정하기
(region은 United States로 지정해야 무료로 사용할 수 있다는 말이 있어 United States로 설정해주었다)</p>
</li>
<li><p>Heroku CLI 설치하기</p>
</li>
<li><p>설치 완료 후 커맨드창을 열어 <code>heroku login</code> 을 입력해 로그인 하기</p>
</li>
<li><p>배포 할 프로젝트가 위치한 경로로 이동하기
<code>cd [레파지토리 폴더명]</code></p>
</li>
<li><p>git 레파지토리 생성 및 원격 연결하기
<code>git init</code>
<code>heroku git:remote -a [레파지토리 폴더명]</code></p>
</li>
<li><p>수정사항 반영하기
<code>git add .</code>
<code>git commit -m &quot;커밋 메세지&quot;</code>
<code>git push heroku main</code></p>
</li>
</ol>
<br>

<hr>
<br>


<p>Heroku는 한 계정당 5개의 앱을 무료로 호스팅 할 수 있지만 해당 도메인에 몇 시간 동안 접속 요청이 없는 경우에는 앱이 수면 상태로 전환되어, 초기 접속이 느려진다는 단점이 있다.
이런 단점을 보완해주기 위해 일정 시간마다 request를 보내주는 <a href="https://kaffeine.herokuapp.com/">사이트</a>를 이용했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발자가 되려는 이유]]></title>
            <link>https://velog.io/@suyeon-hong/%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EB%90%98%EB%A0%A4%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@suyeon-hong/%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EB%90%98%EB%A0%A4%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Wed, 02 Mar 2022 08:48:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>전공자도, 관련업계 경험도 전혀 없는 내가 개발자가 되려는 이유</p>
</blockquote>
<h3 id="1-개발을-시작한-계기">1. 개발을 시작한 계기</h3>
<p>2020년 워홀에서 돌아온 뒤 창업을 한 지인을 잠시 도와준 적이 있다.
청년정보를 모두 모아 보여주는 사이트를 만드는게 목표였는데 정말 아무것도 없는 상태에서 막 시작한 상태라 이것저것 함께 의논하는 시간이 많았다. 이때 처음 개발자가 무슨 일을 하는지 조금이나마 경험할 수 있었지만 개발자를 꿈꾸진 않았다. 나에게 개발자란 넘사벽 직업이었기에..
대신 웹디자이너에 관심이 생겼는데 외주로 맡겼던 디자인시안이 뭣모르고 보니 쉽고 만만해 보였기 때문이다. (배워보니 디자인은 진짜 타고난 센스가 있어야 할 수 있는 것 같다..)</p>
<p>이 회사는 아쉽게도 얼마 안가 폐업하게 되었다.
내가 합류하고 얼마 안 지나 이미 몇 년 전 같은 아이템으로 사업을 시작한 경쟁업체가 있다는걸 발견했기 때문이다. 해당 업체에서는 우리가 하려던 모든 아이템들을 포함해 매우 잘 구성된 사이트를 국가지원을 받으며 운영중이었다. 큰 수익이 있는 모델도 아니었기에 회사는 빠르게 정리되었다.</p>
<p>이후로 나는 기술교육원에서 디자인 관련 툴과 마크업 기술을 배웠다. 코로나로 인해 수업진행에 어려움이 많았지만 이 교육을 통해 나에겐 디자인감각이 없다는 사실을 알 수 있었고, 오히려 코딩에 흥미를 가지게 되어 코딩 공부를 시작하게 되었다.</p>
<p>아직도 개발자라는 직업은 나에게 어렵고 도전적인 직업이다. 공부해보니 더더욱..
그래서 내가 진짜 개발자가 될 수 있을까? 에 대한 의문도 항상 갖고 있지만 그저 재밌어서 시작하게 되었고 하다보니 계속 더 배우게 되고 지금까지 오게 되었다.
누구에게나 처음은 어렵고 힘들었을 것이다. 이렇게 차근차근 배워가다보면 미래의 나도 진짜 개발자로 성장해 있을거라 기대해 본다.</p>
<br>

<h3 id="2-개발하면서-좋은-점-힘든-점">2. 개발하면서 좋은 점, 힘든 점</h3>
<h4 id="좋은점">좋은점</h4>
<ol>
<li><p>작업한 결과가 눈에 바로 보인다는 점이 가장 큰 장점인 것 같다.
화면을 통해 내가 작성한 코드가 제대로 작동할 때 큰 성취감을 느낀다.</p>
</li>
<li><p>무료 정보시장
에러코드 검색해보면 해결법이 다 나온다.
잘 정리된 예제들이 많아 필요한 코드를 가져다 쓰기 좋다.</p>
</li>
</ol>
<h4 id="힘든점">힘든점</h4>
<ol>
<li><p>계속 앉아서 작업하다보니 체력이 약해지는 것 같다.
 짧게라도 시간을 정해서 그 시간엔 무조건 운동을 해야겠다.</p>
</li>
<li><p>문제를 해결할때까지 잠이 안 온다.
 계속 봐도 모르겠을땐 잠깐 쉬었다 나중에 보면 해결되는 경우가 있다. 근데 그게 잘 안된다.
 이상하게 자려고 누우면 자꾸 새로운 방법이 떠오른다.</p>
</li>
<li><p>똑똑한 사람들이 너무 많다.
 비교하고싶지않지만 자꾸 비교되는 대단한 사람들이 너무 많다.
 내 길을 가자..</p>
</li>
</ol>
<br>

<h3 id="3-기대하는-미래의-모습">3. 기대하는 미래의 모습</h3>
<h4 id="배워서-남-주는-개발자">배워서 남 주는 개발자</h4>
<p>지금까지 내가 받아왔듯 나도 남들에게 도움이 되는 개발자가 되고 싶다. 블로그를 쓰는 것도 그 이유 중의 하나이다. 언젠가 누군가에게 필요한 정보가 될 수 있기에 최대한 정확하고 이해하기 쉽게 작성하려고 노력하고 있다. 아직은 남들이 주는 정보를 받는 역할이지만 내가 가진 정보들도 쌓이고 잘 정리되어서 누군가에겐 도움이 되었으면 좋겠다.</p>
<h4 id="함께-하고-싶은-개발자">함께 하고 싶은 개발자</h4>
<p>이번에 팀 프로젝트를 진행하면서 민폐만 끼친다는 생각이 많이 들었었는데 가장 큰 이유가 나의 부족한 실력때문이었다. 그래서 가장 먼저 실력이 뒷받침되는 개발자로 성장했으면 좋겠고, 그 다음으로는 함께 일하는 동료들의 상황을 잘 파악할 수 있는 세심함을 가졌으면 좋겠다. 내가 그랬듯 누군가는 힘들어하고 어려워할 수 있다는걸 생각하면서 다들 잘 이해하고 있는지, 모두가 함께 잘 할 수 있는 방법을 찾으려고 노력하는 그런 개발자로 성장하고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체, 배열 관련 함수 정리]]></title>
            <link>https://velog.io/@suyeon-hong/%EA%B0%9D%EC%B2%B4-%EB%B0%B0%EC%97%B4-%EA%B4%80%EB%A0%A8-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@suyeon-hong/%EA%B0%9D%EC%B2%B4-%EB%B0%B0%EC%97%B4-%EA%B4%80%EB%A0%A8-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 01 Mar 2022 11:56:54 GMT</pubDate>
            <description><![CDATA[<h3 id="💡-객체-object--key-value-키와-밸류값으로-이루어짐">💡 객체, Object = {key: value} 키와 밸류값으로 이루어짐</h3>
<h4 id="객체의-밸류를-조회하는-방법">객체의 밸류를 조회하는 방법</h4>
<pre><code>obj.key // 일반적인 방법
obj[&#39;key&#39;]
// 어떤 키값이 들어올지 모를때, props로 받아와서 진행해야하는 경우에 사용, key는 항상 string</code></pre><h4 id="객체의-키-값-가져오는-방법">객체의 키 값 가져오는 방법</h4>
<pre><code>for (key in object) {
    console.log(key)
}</code></pre><h4 id="객체-복사하는-방법-배열을-객체로-바꾸는-방법">객체 복사하는 방법, 배열을 객체로 바꾸는 방법</h4>
<pre><code>Object.assign(target, source: any[]) // source 값으로는 객체, 배열 둘 다 가능

const user2 = Object.assign({}, {name: &#39;bella&#39;, age: &#39;20&#39;})
// 주로 빈 객체를 target으로 두고 진행, 뒤에 오는 source가 taget을 덮어씌움</code></pre><h4 id="객체를-배열로-바꾸는-방법">객체를 배열로 바꾸는 방법</h4>
<pre><code>Object.entries()</code></pre><h3 id="💡-배열-인덱스를-기본으로-구성됨">💡 배열, 인덱스를 기본으로 구성됨</h3>
<h4 id="배열-분리하는-방법">배열 분리하는 방법</h4>
<pre><code>for (value of array){
    console.log(value)
}</code></pre><h4 id="배열에-값-추가-제거하는-방법">배열에 값 추가, 제거하는 방법</h4>
<pre><code>.push() : 배열의 제일 끝에 값 추가
.pop() : 배열의 제일 끝의 값 제거

.unshift() : 배열의 제일 앞에 값 추가
.shift() : 배열의 제일 앞의 값 제거

// unshift, shift는 index값의 변경을 요구하기 때문에 push, pop에 비해 굉장히 느린 작업이다</code></pre><h4 id="배열에서-원하는-인덱스-위치의-값-추가-제거-수정하는-방법">배열에서 원하는 인덱스 위치의 값 추가, 제거, 수정하는 방법</h4>
<pre><code>array.splice(start:number, deleteCount?:number, new)
// deleteCount를 지정하지않으면 start인덱스 이후의 모든 값을 제거
// 3번째 이후로 오는 파라미터에 추가하는 값은 지워진 인덱스자리에 추가
// 원본배열을 변경, 삭제된 요소를 배열로 반환</code></pre><pre><code>array.slice(start, end)
// start: 추출 시작 인덱스 값, 음수를 지정할 경우 배열의 끝에서부터 추출 시작
// end: 추출 종료 인덱스, 지정하지 않을경우 배열 끝까지 추출
// 원본배열은 수정되지않고 수정된 배열을 반환</code></pre><h4 id="배열-병합하는-방법">배열 병합하는 방법</h4>
<pre><code>array.concat(array2)</code></pre><h4 id="배열에-포함된-값인지-확인하는-방법-인덱스값-조회">배열에 포함된 값인지 확인하는 방법, 인덱스값 조회</h4>
<pre><code>array.includes(value) //불리언 반환
array.indexOf(value) //숫자 반환

.lastIndexOf(value) 중복된 값이 있을때 사용, 뒤에서부터 조회</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[정규표현식 정리]]></title>
            <link>https://velog.io/@suyeon-hong/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@suyeon-hong/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 01 Mar 2022 11:55:02 GMT</pubDate>
            <description><![CDATA[<table>
<thead>
<tr>
<th align="center">표현식</th>
<th>뜻</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>|</code></td>
<td>또는</td>
</tr>
<tr>
<td align="center"><code>()</code></td>
<td>그룹</td>
</tr>
<tr>
<td align="center"><code>[]</code></td>
<td>문자셋, 괄호안의 어떤 문자든</td>
</tr>
<tr>
<td align="center"><code>[^]</code></td>
<td>부정문자셋, 괄호안의 어떤 문자가 아닐 때</td>
</tr>
<tr>
<td align="center"><code>(?:)</code></td>
<td>찾지만 기억하지는 않음</td>
</tr>
</tbody></table>
<br>

<table>
<thead>
<tr>
<th align="center">표현식</th>
<th>뜻</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>?</code></td>
<td>없거나 있거나</td>
</tr>
<tr>
<td align="center"><code>*</code></td>
<td>없거나 있거나 많거나</td>
</tr>
<tr>
<td align="center"><code>+</code></td>
<td>하나 또는 많이</td>
</tr>
<tr>
<td align="center"><code>{n}</code></td>
<td>n번 반복</td>
</tr>
<tr>
<td align="center"><code>{min,}</code></td>
<td>최소</td>
</tr>
<tr>
<td align="center"><code>{min,max}</code></td>
<td>최소, 그리고 최대</td>
</tr>
</tbody></table>
<br>

<table>
<thead>
<tr>
<th align="center">표현식</th>
<th>뜻</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>\b</code></td>
<td>단어경계</td>
</tr>
<tr>
<td align="center"><code>\B</code></td>
<td>단어 경계가 아님</td>
</tr>
<tr>
<td align="center"><code>^</code></td>
<td>문장의 시작</td>
</tr>
<tr>
<td align="center"><code>$</code></td>
<td>문장의 끝</td>
</tr>
</tbody></table>
<br>

<table>
<thead>
<tr>
<th align="center">표현식</th>
<th>뜻</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>\</code></td>
<td>특수 문자가 아닌 문자</td>
</tr>
<tr>
<td align="center"><code>.</code></td>
<td>어떤 글자(줄바꿈 문자 제외)</td>
</tr>
<tr>
<td align="center"><code>\d</code></td>
<td>digit 숫자</td>
</tr>
<tr>
<td align="center"><code>\D</code></td>
<td>digit 숫자 아님</td>
</tr>
<tr>
<td align="center"><code>\w</code></td>
<td>word 문자</td>
</tr>
<tr>
<td align="center"><code>\W</code></td>
<td>word 문자 아님</td>
</tr>
<tr>
<td align="center"><code>\s</code></td>
<td>space 공백</td>
</tr>
<tr>
<td align="center"><code>\S</code></td>
<td>space 공백 아님</td>
</tr>
</tbody></table>
<br>

<table>
<thead>
<tr>
<th align="center">기호</th>
<th>뜻</th>
</tr>
</thead>
<tbody><tr>
<td align="center">i</td>
<td>ignore case, 대소문자를 구분하지 않음</td>
</tr>
<tr>
<td align="center">g</td>
<td>global, 모든 패턴들을 검색</td>
</tr>
<tr>
<td align="center">m</td>
<td>multiline, 다중 라인의 문자열인 경우에도 검색</td>
</tr>
</tbody></table>
<p><br><br></p>
<h6 id="정규표현식-연습-사이트-httpsregexrcom-br-연습-퀴즈-사이트-httpsregexonecom">정규표현식 연습 사이트 <a href="https://regexr.com/">https://regexr.com/</a> <br> 연습 퀴즈 사이트 <a href="https://regexone.com/">https://regexone.com/</a></h6>
]]></description>
        </item>
        <item>
            <title><![CDATA[스크롤 안보이게 하는 css]]></title>
            <link>https://velog.io/@suyeon-hong/%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%95%88%EB%B3%B4%EC%9D%B4%EA%B2%8C-%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@suyeon-hong/%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%95%88%EB%B3%B4%EC%9D%B4%EA%B2%8C-%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 26 Feb 2022 09:54:14 GMT</pubDate>
            <description><![CDATA[<pre><code>.box {
    -ms-overflow-style: none; /* IE and Edge */
    scrollbar-width: none; /* Firefox */
}
.box::-webkit-scrollbar {
    display: none; /* Chrome, Safari, Opera*/
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[드래그 방지 css]]></title>
            <link>https://velog.io/@suyeon-hong/%EB%93%9C%EB%9E%98%EA%B7%B8-%EB%B0%A9%EC%A7%80</link>
            <guid>https://velog.io/@suyeon-hong/%EB%93%9C%EB%9E%98%EA%B7%B8-%EB%B0%A9%EC%A7%80</guid>
            <pubDate>Sat, 26 Feb 2022 09:52:14 GMT</pubDate>
            <description><![CDATA[<pre><code>-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;</code></pre>]]></description>
        </item>
    </channel>
</rss>