<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>CHIMAN.log</title>
        <link>https://velog.io/</link>
        <description>기본기가 탄탄한 개발자가 되자!</description>
        <lastBuildDate>Sun, 13 Jul 2025 14:17:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>CHIMAN.log</title>
            <url>https://velog.velcdn.com/images/rlaclghks123/profile/0ab56033-809b-4736-9abb-d5d1ab5d2cd1/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. CHIMAN.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/rlaclghks123" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[삽질 방지 - input 같은 파일 올리면 변화없는 문제]]></title>
            <link>https://velog.io/@rlaclghks123/%EC%82%BD%EC%A7%88-%EB%B0%A9%EC%A7%80-input-%EA%B0%99%EC%9D%80-%ED%8C%8C%EC%9D%BC-%EC%98%AC%EB%A6%AC%EB%A9%B4-%EB%B3%80%ED%99%94%EC%97%86%EB%8A%94-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@rlaclghks123/%EC%82%BD%EC%A7%88-%EB%B0%A9%EC%A7%80-input-%EA%B0%99%EC%9D%80-%ED%8C%8C%EC%9D%BC-%EC%98%AC%EB%A6%AC%EB%A9%B4-%EB%B3%80%ED%99%94%EC%97%86%EB%8A%94-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Sun, 13 Jul 2025 14:17:37 GMT</pubDate>
            <description><![CDATA[<p>오늘 겪은 삽질은 같은 파일을 올렸을때 파일에 대한 변화가 없는 부분입니다.</p>
<p>바로 예시로 들어가보겠습니다.</p>
<h1 id="문제-발생">문제 발생</h1>
<p>프로필을 등록하기 위해 아래와 같은 단계별로 프로필을 추가했습니다.</p>
<ol>
<li>프로필 등록 페이지 접속 </li>
<li>react-easy-crop를 활용하여 원하는 이미지 추출 </li>
<li>파일 선택</li>
</ol>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/a93b543b-92d3-4c4e-92d9-248680a5e12f/image.png" alt=""></p>
<p>그러나 여기서 똑같은 파일을 클릭하게 되면, 화면 추출하는 모달이 열리지 않는 문제가 발생합니다. </p>
<blockquote>
<p>만약 사용자가 같은 파일을 선택하면 브라우저는 이전 값과 동일하다고 판단합니다</p>
</blockquote>
<p>그렇다면 같은 파일의 조건이 무엇일까요?
<img src="https://velog.velcdn.com/images/rlaclghks123/post/f698055d-2b2c-4ba7-b883-a46986cc790c/image.png" alt=""></p>
<blockquote>
<p>따라서 위 4가지가 같으면 브라우저는 같은 파일로 간주하여, 변화를 인식하지 않게됩니다. </p>
</blockquote>
<h1 id="문제-해결">문제 해결</h1>
<p>문제 해결은 아주 간단합니다. 
input의 value값을 빈문자열로 초기화 해주게 되면 됩니다. </p>
<p>onChange 이벤트를 핸들링 하는곳에서 event.target.value = &#39;&#39; 값으로 초기화 해주게 되면, 문제가 바로 해결됩니다.</p>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/d5943f25-a2ae-45b5-bba7-22e4d821b4f8/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발 도구 - Husky]]></title>
            <link>https://velog.io/@rlaclghks123/%EA%B0%9C%EB%B0%9C-%EB%8F%84%EA%B5%AC-Husky</link>
            <guid>https://velog.io/@rlaclghks123/%EA%B0%9C%EB%B0%9C-%EB%8F%84%EA%B5%AC-Husky</guid>
            <pubDate>Wed, 18 Jun 2025 14:31:47 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#git-hook%EC%9D%B4%EB%9E%80">Git Hook이란</a></li>
<li><a href="#husky%EB%9E%80">Husky란</a></li>
<li><a href="#%EC%8B%A4%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0">실제 사용해보기</a></li>
</ul>
<h1 id="git-hook이란">Git Hook이란</h1>
<ul>
<li><code>Git Hook</code>은 Git이 제공하는 <strong>이벤트 기반 스크립트 시스템</strong>입니다.<br>즉, Git에서 특정 이벤트(예: 커밋, 푸시 등)가 발생할 때 자동으로 실행되는 스크립트를 등록할 수 있습니다.</li>
</ul>
<h1 id="husky란">Husky란</h1>
<h3 id="husky란-1">Husky란</h3>
<ul>
<li>Husky는 <strong>Git Hook을 쉽게 설정하고 유지할 수 있게 도와주는 툴</strong>입니다.<br>원래 Git Hook은 <code>.git/hooks/</code> 안에 직접 스크립트를 넣어야 했지만, Husky를 사용하면 프로젝트 루트 디렉터리에서 <code>.husky/</code> 폴더로 Git Hook을 관리할 수 있습니다.</li>
</ul>
<h3 id="사용방법">사용방법</h3>
<h4 id="1️⃣-설치-및-실행">1️⃣ 설치 및 실행</h4>
<pre><code class="language-bash">npm install husky --save-dev

npx husky init </code></pre>
<h4 id="2️⃣-git-hook-활성화-설정">2️⃣ Git hook 활성화 설정</h4>
<pre><code class="language-json">// package.json
&quot;scripts&quot;: {
  &quot;prepare&quot;: &quot;husky install&quot;
}</code></pre>
<blockquote>
<p>prepare는 npm install 이후 자동으로 실행되도록 설계된 NPM 스크립트입니다.
이를 통해 다른 개발자들도 npm install만으로 hook이 자동 설치됩니다</p>
</blockquote>
<h3 id="3️⃣-🧪-lint-staged와-함께-사용하기-선택적">3️⃣ 🧪 lint-staged와 함께 사용하기 (선택적)</h3>
<blockquote>
<p>lint-staged란 커밋할 때 전체 파일을 검사하지 않고, Stage에 올라온 파일만 검사하고 싶을 땐 사용합니다.</p>
</blockquote>
<h4 id="3️⃣-1️⃣-설치">3️⃣-1️⃣ 설치</h4>
<pre><code class="language-bash">npm install lint-staged --save-dev</code></pre>
<h4 id="3️⃣-2️⃣-설정-packagejson-또는-별도-config">3️⃣-2️⃣ 설정 (package.json 또는 별도 config)</h4>
<pre><code class="language-javascript">
&quot;lint-staged&quot;: {
  &quot;src/**/*.{js,jsx,ts,tsx}&quot;: [
    &quot;eslint --fix&quot;,
    &quot;prettier --write&quot;
  ]
}</code></pre>
<h4 id="3️⃣-3️⃣-huskypre-commit-파일-수정">3️⃣-3️⃣ .husky/pre-commit 파일 수정</h4>
<pre><code class="language-javascript">npx lint-staged</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/aad10256-531e-4966-9d16-b7b17b296283/image.png" alt=""></p>
<h1 id="실제-사용해보기">실제 사용해보기</h1>
<h3 id="1️⃣-husky-사용전">1️⃣ Husky 사용전</h3>
<p>1️⃣-1️⃣ lint에 걸리도록 코드 작성
<img src="https://velog.velcdn.com/images/rlaclghks123/post/8065d7c0-de99-4db1-8c42-b7685da5ec2c/image.png" alt=""></p>
<p>1️⃣-2️⃣ 커밋 시도 : lint에 걸렸으나, 커밋이 잘 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/6c14f92d-2eec-413a-8843-240ef9e52043/image.png" alt=""></p>
<hr>
<h3 id="1️⃣-husky-사용후">1️⃣ Husky 사용후</h3>
<p>1️⃣-1️⃣ 커밋 시도 : lint에 커밋이 안되는걸 확인할 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/c50888c6-ac91-4b6c-972b-e67d9a240f09/image.png" alt=""></p>
<p>1️⃣-2️⃣ 코드 수정후 커밋 시도<br>-&gt; Vscode에서 사용되지 않는 값이 선언돼있어서 또 lint에 걸렸습니다.(lint에 해당 기능을 꺼놨나 봅니다) 
-&gt; 수정 후 다시 커밋을 해보면 잘 커밋이 되는 것을 확인할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/ad8e9afb-3011-430a-8b64-4e3ab0c49e4a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue - Hash mode 와 History mode 차이]]></title>
            <link>https://velog.io/@rlaclghks123/Vue-Hash-mode-%EC%99%80-History-mode-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@rlaclghks123/Vue-Hash-mode-%EC%99%80-History-mode-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 05 Jun 2025 11:33:29 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#vue%EC%97%90%EC%84%9C-%EB%9D%BC%EC%9A%B0%ED%8C%85">Vue에서 라우팅</a></li>
<li><a href="#%EA%B2%B0%EB%A1%A0">결론</a></li>
<li><a href="#%EC%B0%B8%EA%B3%A0">참고</a></li>
</ul>
<h1 id="vue에서-라우팅">Vue에서 라우팅</h1>
<ul>
<li><p>Vue.js로 SPA(Single Page Application)를 개발할 때 가장 중요한 부분 중 하나가 바로 <code>라우팅(Routing)</code>입니다. </p>
</li>
<li><p>Vue에서는 vue-router를 통해 라우팅을 손쉽게 구성할 수 있는데, 이때 라우팅 모드로 Hash mode와 History mode를 선택할 수 있습니다.</p>
</li>
<li><p>라우팅 모드는 <code>URL 경로를 어떻게 처리할지를 결정하는 방식입니다.</code> Vue Router는 기본적으로 두 가지 모드를 제공합니다.</p>
<ol>
<li>Hash Mode (기본값)</li>
<li>History Mode</li>
</ol>
</li>
</ul>
<h2 id="hash-mode">Hash Mode</h2>
<ul>
<li>Hash mode는 URL의 #(해시) 기호를 기준으로 라우팅을 처리합니다. 브라우저는 # 뒤의 내용을 서버에 요청하지 않고, 클라이언트에서만 처리합니다.</li>
<li><code>ex) https://example.com/#/about</code></li>
<li>위 URL은 서버에는 /만 요청되며, #/about은 브라우저에서만 처리됩니다.</li>
</ul>
<h3 id="✅-장점">✅ 장점</h3>
<ul>
<li>별도 서버 설정 없이 동작</li>
<li>브라우저 호환성이 뛰어남</li>
<li>서버에 요청이 가지 않기 때문에 404 에러 없음</li>
</ul>
<h3 id="❌-단점">❌ 단점</h3>
<ul>
<li>#이 URL에 포함되므로 깔끔하지 않음 -&gt; <code>ex) https://example.com/#/about</code></li>
<li>SEO(검색엔진 최적화)에 불리할 수 있음  </li>
</ul>
<h2 id="history-mode">History Mode</h2>
<ul>
<li><p>History mode는 HTML5의 History API를 사용해 URL을 처리합니다. 이 방식은 # 없이 일반적인 URL처럼 보입니다.</p>
</li>
<li><p><code>https://example.com/about</code></p>
</li>
<li><p>History Mode의 경우 브라우저는 실제 /about 경로로 요청을 보내기 때문에, 서버에서 해당 요청을 적절히 처리해줘야 합니다. 그렇지 않으면 404에러가 발생합니다.</p>
</li>
</ul>
<h3 id="✅-장점-1">✅ 장점</h3>
<ul>
<li>URL이 깔끔하고 직관적</li>
<li>SEO에 더 적합</li>
<li>실제 웹사이트처럼 보이기 때문에 UX 측면에서 유리</li>
</ul>
<h3 id="❌-단점-1">❌ 단점</h3>
<ul>
<li>서버 설정이 필요 (특히 새로고침 시)</li>
<li>잘못 설정 시 404 에러 발생 가능</li>
</ul>
<h1 id="결론">결론</h1>
<ul>
<li><p>Hash Mode는 간편하고 설정이 필요 없지만, URL이 깔끔하지 않고 SEO에 불리합니다.</p>
</li>
<li><p>History Mode는 깔끔한 URL과 더 나은 사용자 경험을 제공하지만, 서버 설정이 필요합니다.</p>
</li>
<li><p>라우팅 처리는 History mode로 사용하면서, 같은 페이지 내에서 탭을 통해 이동할 경우는 hash로 처리하면 좋을 것 같다는 생각이 듭니다.</p>
<ul>
<li>예를들어 홈페이지, 프로필 페이지, 리스트 페이지의 경우 History mode를 사용하여 아래와 같이 라우팅 처리를 합니다. <ul>
<li><code>ex) /home, /profile, /list</code></li>
</ul>
</li>
<li>그러나 같은 페이지 내부에서 (탭 이동 혹은 스크롤 이동시) hash를 사용하면 좋을 것 같습니다. <ul>
<li>ex) <code>/profile#top, /profile#bottom</code></li>
</ul>
</li>
</ul>
</li>
<li><p>결과적으로 hash와 history를 상황에 맞게 적재적소에 맞게 사용할 수 있으면 베스트가 아닐까 생각합니다.</p>
</li>
<li><p>추가적으로 이글 자체에 목차를 만들고, 목차를 클릭하면 이동되도록 하는 기능 또한 #으로 돼있는걸 확인할 수 있습니다.</p>
</li>
</ul>
<blockquote>
<p>현재 글에서 목차를 눌러보며 url의 변화를 확인 할 수 있습니다.</p>
</blockquote>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://v3.router.vuejs.org/kr/guide/essentials/history-mode.html#%E1%84%89%E1%85%A5%E1%84%87%E1%85%A5-%E1%84%89%E1%85%A5%E1%86%AF%E1%84%8C%E1%85%A5%E1%86%BC-%E1%84%8B%E1%85%A8%E1%84%8C%E1%85%A6">vue 공식문서</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Today I Learn]- URI, URL, URN에 대해]]></title>
            <link>https://velog.io/@rlaclghks123/Today-I-Learn-URI-URL-URN%EC%97%90-%EB%8C%80%ED%95%B4</link>
            <guid>https://velog.io/@rlaclghks123/Today-I-Learn-URI-URL-URN%EC%97%90-%EB%8C%80%ED%95%B4</guid>
            <pubDate>Sun, 01 Jun 2025 01:19:43 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#uri%EB%9E%80">URI란</a></li>
<li><a href="#url%EC%9D%B4%EB%9E%80">URL이란</a></li>
<li><a href="#urn%EC%9D%B4%EB%9E%80">URN이란</a></li>
<li><a href="#uri-%EC%97%B0%EC%8A%B5">URI 연습</a></li>
<li><a href="#%EC%B0%B8%EA%B3%A0">참고</a></li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/2bbae7a5-744d-43aa-b3ec-636e11afb602/image.jpg" alt=""></p>
<h1 id="uri란">URI란</h1>
<ul>
<li><p><code>U</code>niform <code>R</code>esource <code>I</code>dentifier의 약자로서 <code>어디서든 늘 같은 Resource(텍스트, 이미지, 비디오 등)를 보여줄 수 있도록 해주는 고유 식별자 입니다.</code></p>
</li>
<li><p>URI는 크게 <code>URL</code>, <code>URN</code>으로 나눌 수 있습니다.</p>
</li>
</ul>
<h1 id="url이란">URL이란</h1>
<ul>
<li><p><code>U</code>niform <code>R</code>esource <code>L</code>ocator의 약자로서 네트워크 상에서 Resource(텍스트, 이미지)가 위치한 정보를 나타냅니다.</p>
</li>
<li><p>일반적으로 사이트 도메인을 자주 의미합니다.</p>
</li>
<li><p>URL을 구성하는 요소는 Scheme(Protocal), Host(Damain), Port, Path입니다.</p>
<ul>
<li><h4 id="schemeprotocol--서로-다른-컴퓨터간의-통신을-하기-위한-규약으로서-http웹httpshttp보다-더욱-안전-ftp파일-talnet원격지-접속-등이-있습니다">Scheme(Protocol) : 서로 다른 컴퓨터간의 통신을 하기 위한 규약으로서 HTTP(웹),HTTPS(HTTP보다 더욱 안전), FTP(파일), Talnet(원격지 접속) 등이 있습니다.</h4>
</li>
<li><h4 id="hostdomain--인터넷에-접속되어-있는-각각의-컴퓨터를-가리키는-주소-입니다">Host(Domain) : <code>인터넷에 접속되어 있는 각각의 컴퓨터를 가리키는 주소</code> 입니다.</h4>
</li>
<li><h4 id="port---ip-내에서-애플리케이션-상호-구분프로세스-구분을-위해-사용하는-번호이며-http의-기본-포트는-80이며-https의-기본-포트는-443입니다-port번호를-직접-기입하지-않으면-웹-브라우져가-미리-약속한-80-443-포트를-사용합니다-왜냐하면-http-https의-포트를-이것으로-사용하겠다는-표준화가-되어-있기-때문입니다">port :  IP 내에서 애플리케이션 상호 구분(프로세스 구분)을 위해 사용하는 번호이며, http의 기본 포트는 80이며, https의 기본 포트는 443입니다. port번호를 직접 기입하지 않으면 웹 브라우져가 미리 약속한 80, 443 포트를 사용합니다. 왜냐하면 HTTP, HTTPS의 포트를 이것으로 사용하겠다는 표준화가 되어 있기 때문입니다.</h4>
</li>
<li><h4 id="path--컴퓨터-내부에-있는-디렉토리의-파일을-가리킵니다-즉-자원의-경로를-의미합니다">path : 컴퓨터 내부에 있는 디렉토리의 파일을 가리킵니다. 즉 <code>자원의 경로를 의미합니다.</code></h4>
</li>
</ul>
</li>
</ul>
<h1 id="urn이란">URN이란</h1>
<ul>
<li><p><code>U</code>niform <code>R</code>esource <code>N</code>ame의 약자로서, Resource의 이름값을 이용해서 접근하는 방식입니다.</p>
</li>
<li><p>프로토콜을 제외한 URL에 <code>Query, Fragment</code>로 구성되어져 있습니다.</p>
</li>
<li><p>실제 자원을 찾기 위해서는 URN을 URL로 변환하여 이용합니다.</p>
</li>
<li><h4 id="queryquery-string--웹-서버에-보내는-추가적인-질문입니다">Query(Query String) : 웹 서버에 보내는 추가적인 질문입니다.</h4>
</li>
<li><h4 id="fragment--html-내부-북마크-등에-사용되며-서버에-전송되는-정보는-아닙니다">fragment : html 내부 북마크 등에 사용되며 서버에 전송되는 정보는 아닙니다.</h4>
</li>
</ul>
<h1 id="uri-연습">URI 연습</h1>
<p>Javascript MDN사이트로 연습을 해볼려고 합니다. 아주 복잡해 보이지만, 한번 분해(?)를 해볼려고 합니다.
<code>https://developer.mozilla.org/ko/docs/Learn/JavaScript/First_steps/What_is_JavaScript#%EC%9B%B9_%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90%EC%84%9C_javascript%EB%8A%94_%EC%96%B4%EB%96%A4_%EC%9D%BC%EC%9D%84_%ED%95%98%EB%82%98%EC%9A%94</code></p>
<h2 id="차근차근-앞에서부터-해석을-해보겠습니다">차근차근 앞에서부터 해석을 해보겠습니다.</h2>
<ul>
<li><code>Scheme(protocal)</code> :  <code>https</code> 를 사용하고 있습니다. </li>
<li><code>Host</code> : <code>developer.mozilla.org/ko</code>를 사용하고 있습니다. ko는 한국을 의미합니다. </li>
<li><code>Port</code> : 기입을 따로 안했고 HTTPS이므로 443포트를 사용하고 있을것입니다.</li>
<li><code>Path</code> : <code>docs/Learn/JavaScript/First_steps/What_is_JavaScript</code>를 사용하고 있으며 해석 해보겠습니다.<ul>
<li><ol>
<li><code>docs(문서를 의미하겠죠?)</code>안에 </li>
</ol>
</li>
<li><ol start="2">
<li><code>learn(배우는 부분 인가봅니다)</code> 안에</li>
</ol>
</li>
<li><ol start="3">
<li><code>JavaScript(JS를 배우는곳 인가봅니다)</code> 안에 </li>
</ol>
</li>
<li><ol start="4">
<li><code>First_steps(첫단계 인가봐요)</code> 안에 </li>
</ol>
</li>
<li><ol start="5">
<li><code>What_is_JavaScript(JS가 무엇인지를 알려주나봅니다)</code> 중에서  </li>
</ol>
</li>
<li><ol start="6">
<li><code>%EC%9B%B9_%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90%EC%84%9C_javascript%EB%8A%94_%EC%96%B4%EB%96%A4_%EC%9D%BC%EC%9D%84_%ED%95%98%EB%82%98%EC%9A%94</code> 내부 북마크부분을 의미하나 봅니다. </li>
</ol>
</li>
</ul>
</li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Scripting/What_is_JavaScript#%EC%9B%B9_%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90%EC%84%9C_javascript%EB%8A%94_%EC%96%B4%EB%96%A4_%EC%9D%BC%EC%9D%84_%ED%95%98%EB%82%98%EC%9A%94">javascript MDN</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[삽질방지 - focus 발생시 input text와 radio 버튼 차이]]></title>
            <link>https://velog.io/@rlaclghks123/%EC%82%BD%EC%A7%88%EB%B0%A9%EC%A7%80-focus-%EB%B0%9C%EC%83%9D%EC%8B%9C-input-text%EC%99%80-radio-%EB%B2%84%ED%8A%BC-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@rlaclghks123/%EC%82%BD%EC%A7%88%EB%B0%A9%EC%A7%80-focus-%EB%B0%9C%EC%83%9D%EC%8B%9C-input-text%EC%99%80-radio-%EB%B2%84%ED%8A%BC-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 18 May 2025 07:46:21 GMT</pubDate>
            <description><![CDATA[<p>오늘은 어이없이 삽질했던 경험을 적어보려고 합니다. 
우선 요구사항은 여러 타입의 값을 입력받아서, 제출하도록 하는것입니다.</p>
<ol>
<li>input을 통한 짧은 text</li>
<li>text area를 통한 긴글 </li>
<li>input의 radio 타입 버튼</li>
<li>select의 선택한 값 
위와같이 여러개의 값을 입력받고, *를 통해 필수 여부를 받는 아주 일반적인 기능입니다. </li>
</ol>
<h1 id="문제-발생">문제 발생</h1>
<h3 id="input-text에-focus-될-경우">input text에 focus 될 경우</h3>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/a7a104db-a133-4de7-b70a-5700f234d83a/image.jpg" alt=""></p>
<ul>
<li><p>위 사진처럼 text 타입의 <code>input box를 focus할 경우</code> 제가 원했던 방식으로 문제없이 잘 작동합니다.</p>
</li>
<li><p>마찬가지로 input의 radio 타입의 Input box를 focus할 경우 아래의 사진과 같이 동작합니다. </p>
</li>
</ul>
<h3 id="input-radio에-focus-될-경우">input radio에 focus 될 경우</h3>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/35ad5cd3-7141-4e8f-b01e-497a8fbccacd/image.jpg" alt=""></p>
<blockquote>
<p>마치 focus가 동작하지 않는 것 처럼 보입니다</p>
</blockquote>
<ul>
<li><p>위 사진과 달리 범위를 넓혀보면 페이지가 이동하여 focus가 동작하는구나 알 수 있지만, <code>위 사진처럼 같은 화면 내부에 존재한다면, 페이지의 이동이 발생하지 않고, 테두리에 특정 UI 변화가 보이지 않아 동작하지 않는 것 처럼 보입니다.</code></p>
</li>
<li><p>GPT에게 물어보니 <code>라디오 버튼은 브라우저에 따라 기본 스타일이 적용되어 있으며, focus 시 기본적으로 outline이 적용되긴 하지만 시각적으로 거의 보이지 않거나, 표시되지 않도록 설정되어 있는 경우가 많기 때문입니다.</code> 라고 말합니다. </p>
</li>
<li><p>저는 Crome을 썼지만 safari, Brave Browser 모두 확인해본 결과 아무런 UI 변화가 보이지 않습니다.</p>
</li>
</ul>
<h1 id="문제-해결">문제 해결</h1>
<ul>
<li><p>따라서 focus가 될 경우 outline이라는 Css 속성을 직접 추가해주고, blur가 될 경우 css를 해제하는 방법으로 문제를 해결할 수 있습니다. </p>
<blockquote>
<p>focus이벤트는 요소가 포커스를 받으면 발생합니다. 
blur 이벤트는 요소가 포커스를 잃었을 때 실행되는 이벤트입니다.</p>
</blockquote>
</li>
<li><p>여러 방법이 존재합니다.</p>
<ol>
<li>CSS에 focus 스타일 추가 </li>
<li>onfocus, onblur 이벤트를 추가하여, style을 변경</li>
</ol>
</li>
</ul>
<h3 id="css에-focus-스타일-추가">css에 Focus 스타일 추가</h3>
<pre><code class="language-css">input[type=&quot;radio&quot;]:focus {
  outline: 2px solid blue;
  outline-offset: 2px;
}</code></pre>
<h3 id="onfocus-onblur-이벤트를-추가하여-style을-변경">onfocus, onblur 이벤트를 추가하여, style을 변경</h3>
<pre><code>  &lt;script&gt;
      const radio = document.getElementById(&#39;radio&#39;);

      radio.addEventListener(&#39;focus&#39;, () =&gt; {
        radio.style.outline = &#39;2px solid blue&#39;;
      });

      radio.addEventListener(&#39;blur&#39;, () =&gt; {
        radio.style.outline = &#39;none&#39;;
      });

      const button = document.querySelector(&#39;button&#39;);

      button.addEventListener(&#39;click&#39;, (e) =&gt; {
        const inputs = e.target.parentElement.parentElement
          .querySelector(&#39;div&#39;)
          .querySelectorAll(&#39;input&#39;);

        const input1 = inputs[0];
        input1.focus();
      });
    &lt;/script&gt;</code></pre><h1 id="느낀점">느낀점</h1>
<ul>
<li><p>사실 이번 삽질은 기술적으로 어려운 문제라기보다는, focus가 잘 동작하고 있었음에도 불구하고 화면 변화가 없어서, 동작하지 않는다고 착각했던 제 실수를 돌아보게 만든 경험이었습니다. </p>
</li>
<li><p>특히 <code>일반 텍스트 타입의 input과는 달리, 라디오 버튼은 focus 되었을 때 UI에 뚜렷한 변화가 보이지 않는다는 점</code>을 이번에 처음 알게 되었는데요. 저처럼 같은 실수를 반복하지 않으시길 바라는 마음으로 이 글을 남깁니다.</p>
</li>
<li><p>물론 focus가 동작하기 때문에 그냥 넘어가도 되지만, 확실히 outline을 나타내줌으로서 <code>여기 체크 하셔야됩니다!</code> 라고 직접적으로 표시해주는게 필수적이라는 사용자 경험에 대한 강박(?)이 있어서 한번 확인해봤습니다. </p>
<h1 id="참고">참고</h1>
</li>
<li><p><a href="https://developer.mozilla.org/ko/docs/Web/API/Window/blur_event">blurEvent MDN</a></p>
</li>
<li><p><a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/focus_event">focusEvent MDN</a></p>
</li>
<li><p><a href="https://chatgpt.com">Chat GPT</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript - 지연평가(Lazy Evaluation)]]></title>
            <link>https://velog.io/@rlaclghks123/Javascript-%EC%A7%80%EC%97%B0%ED%8F%89%EA%B0%80Lazy-Evaluation</link>
            <guid>https://velog.io/@rlaclghks123/Javascript-%EC%A7%80%EC%97%B0%ED%8F%89%EA%B0%80Lazy-Evaluation</guid>
            <pubDate>Sun, 11 May 2025 10:25:28 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#%EC%A7%80%EC%97%B0-%ED%8F%89%EA%B0%80%EB%9E%80">지연 평가란</a>
<a href="#%EC%A7%80%EC%97%B0-%ED%8F%89%EA%B0%80-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC">지연 평가 동작원리</a>
<a href="#%EC%B0%B8%EA%B3%A0">참고</a></p>
<hr>
<h1 id="지연-평가란">지연 평가란</h1>
<ul>
<li><p>지연 평가(Lazy Evaluation)란 말 그대로 필요할 때까지 값을 계산하지(지연) 않는 전략입니다. 즉 사용되기 전까지 평가하지 않고, 값을 미루는 방법입니다. </p>
</li>
<li><p>지연 평가는 원하는 시점까지 값의 평가를 지연시켜 메모리 사용량을 줄이고, 불필요한 연산을 방지함으로써 성능을 향상시킬 수 있습니다.</p>
</li>
</ul>
<h1 id="지연-평가-동작원리">지연 평가 동작원리</h1>
<ul>
<li>지연 평가의 동작원리는 일반 배열 자료구조를 이터레이터로 바꿔서 하나씩 값을 평가하는 방식입니다. </li>
</ul>
<h3 id="엄격-평가-동작원리">엄격 평가 동작원리</h3>
<ul>
<li><p>지연 평가의 동작원리 전, 비교가 되는(일반적으로 사용되는) 엄격 평가의 동작원리를 살펴보겠습니다. </p>
<ul>
<li><p>예를들어 <code>모두 1씩 더한 뒤, 홀수인 값들 중, 앞에서 3개를 추출하는 조건</code>의 경우</p>
<ol>
<li>100개의 요소가 존재하는 배열이 존재합니다.</li>
<li>map을 통해 모두 +1을 해줍니다. </li>
<li>filter를 통해 홀수를 필터링 한다.</li>
<li>slice를 통해 앞에서 3개를 추출한다. </li>
</ol>
<ul>
<li>위의 경우 총 203번 순회 과정이 진행됩니다.<ol>
<li>map 배열에서 100번</li>
<li>filter 배열에서 100번 </li>
<li>slice에서 3번</li>
</ol>
</li>
</ul>
</li>
<li><p><code>만약 100개가 아닌 1억개였다면 3개를 추출하기 위해 약 2억번의 과정이 필요합니다.</code></p>
</li>
</ul>
</li>
</ul>
<h3 id="지연-평가-동작-원리">지연 평가 동작 원리</h3>
<ul>
<li><p>지연평가의 경우 어떻게 동작하는지 알아보겠습니다. </p>
</li>
<li><p>지연 평가의 경우 1개씩 처리하는 과정으로 진행됩니다. </p>
</li>
<li><p>예를들어 [0,1,2,...99] 가 존재할 경우</p>
<ol>
<li>0에 +1을 해주는 과정 1번 </li>
<li>홀수인지 확인하는 과정 1번 </li>
<li>홀수면 추출 하는 과정 1번, 짝수면 0번 </li>
</ol>
</li>
<li><p>위 과정을 통해 앞에서 3개 추출을 위해서는 0요소에 관해 3번(홀수이므로), 1요소에 관해 (2번), 2요소에 관해 3번(홀수이므로), ... 이런식으로 진행됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/9635b8d8-5bb7-4871-a904-2c9d5a2b454b/image.jpg" alt=""></p>
</li>
<li><p>따라서 <code>총 15번만 진행되고</code>, 7이후 부터는 원하는 조건의 숫자 3개를 모두 추출했으므로, <code>불필요한 작업을 진행하지 않습니다.</code></p>
</li>
</ul>
<h3 id="실제-코드로-확인해보기">실제 코드로 확인해보기</h3>
<ul>
<li><p>1억개의 요소를 비교해보도록 하겠습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/1e19fed7-97fa-4f57-89b6-1367d25f2832/image.jpg" alt=""></p>
</li>
<li><p>실제로 엄청난 속도 차이를 확인 할 수 있습니다. </p>
</li>
</ul>
<ul>
<li>다만 지연평가를 실제로 어떻게 적용할지는 고민을 해봐야 될 것 같습니다. 대용량 데이터를 한 번에 처리할 필요 없이 데이터를 하나씩 처리할 경우가 생긴다면 적절하지 않을까 생각을 해봅니다. </li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><p><a href="https://armadillo-dev.github.io/javascript/whit-is-lazy-evaluation/">[Javascript] 지연 평가(Lazy evaluation) 를 이용한 성능 개선</a></p>
</li>
<li><p><a href="https://www.zerocho.com/category/JavaScript/post/5c0cb264f82a70001e47db0c">제로초 지연평가</a></p>
</li>
<li><p><a href="https://chatgpt.com/">chat GPT</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML - a태그를 활용하여 특정 영역으로 스크롤 이동]]></title>
            <link>https://velog.io/@rlaclghks123/HTML-a%ED%83%9C%EA%B7%B8%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%ED%8A%B9%EC%A0%95-%EC%98%81%EC%97%AD%EC%9C%BC%EB%A1%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%9D%B4%EB%8F%99</link>
            <guid>https://velog.io/@rlaclghks123/HTML-a%ED%83%9C%EA%B7%B8%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%ED%8A%B9%EC%A0%95-%EC%98%81%EC%97%AD%EC%9C%BC%EB%A1%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EC%9D%B4%EB%8F%99</guid>
            <pubDate>Sun, 27 Apr 2025 18:58:04 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#%ED%8E%98%EC%9D%B4%EC%A7%80%EC%9D%98-%ED%8A%B9%EC%A0%95-%EC%9C%84%EC%B9%98%EB%A1%9C-%EC%9D%B4%EB%8F%99%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95">페이지의 특정 위치로 이동하는 방법</a></li>
<li><a href="#%EC%9E%A5%EB%8B%A8%EC%A0%90">장단점</a></li>
<li><a href="#%EA%B0%9C%EC%84%A0%ED%95%B4%EB%B3%B4%EA%B8%B0">개선해보기</a></li>
<li><a href="#%EC%B0%B8%EA%B3%A0">참고</a></li>
</ul>
<h1 id="페이지의-특정-위치로-이동하는-방법">페이지의 특정 위치로 이동하는 방법</h1>
<ul>
<li><p>HTML의 a태그와, id 속성값 2가지를 활용하여 특정 위치로 이동시킬 수 있습니다. </p>
<ol>
<li>a태그를 통해 href 속성으로 페이지를 이동시킨다.</li>
<li>id 속성값을 통해 이동시킬 요소에 적용해준다. </li>
</ol>
</li>
<li><p>코드적으로 보면 아래와 같습니다.</p>
</li>
</ul>
<pre><code class="language-html">    --특정 위치로 클릭 할 버튼
    &lt;a href=&quot;#header&quot;&gt;header 버튼&lt;/a&gt;

    -- 이동하여 나타낼 html 요소     
    &lt;div id=&#39;header&#39;&gt;Header&lt;/div&gt;</code></pre>
<h3 id="실제-적용-화면">실제 적용 화면</h3>
<ul>
<li>실제 React를 사용하여 Header, Main, Footer를 나타내면 아래와 같이 나타낼 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/9375ac77-b2e2-424e-a868-58f96d72d8c2/image.gif" alt=""></li>
</ul>
<h3 id="실제-코드">실제 코드</h3>
<pre><code class="language-js">const list = [
  {
    id: 1,
    name: &#39;Header&#39;,
    bgColor: &#39;#A76545&#39;,
  },
  {
    id: 2,
    name: &#39;Main&#39;,
    bgColor: &#39;#FFA55D&#39;,
  },
  {
    id: 3,
    name: &#39;Footer&#39;,
    bgColor: &#39;#FFDF88&#39;,
  },
];

function App() {
  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;div&gt;목차&lt;/div&gt;
      &lt;ul&gt;
        {list.map((data) =&gt; (
          &lt;li&gt;
            &lt;a href={`#${data.id}`}&gt;{data.name}&lt;/a&gt;
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;

      &lt;div&gt;
        {list.map((data) =&gt; (
          &lt;div
            id={data.id}
            style={{
              height: &#39;100vh&#39;,
              fontSize: &#39;25px&#39;,
              backgroundColor: data.bgColor,
            }}&gt;
            {data.name}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<hr>
<h1 id="장단점">장단점</h1>
<h3 id="장점">장점</h3>
<ol>
<li>간단하고 직관적 : 특별한 자바스크립트 코드 없이 HTML만으로 특정 위치로 스크롤을 이동할 수 있습니다</li>
<li>브라우저 호환성 : HTML만을 사용하기 때문에 어느 브라우저든 동작 합니다.</li>
<li>SEO : HTML만을 사용하기 때문에 SEO에 유리합니다.</li>
</ol>
<h3 id="단점">단점</h3>
<ol>
<li><p>상황에 따라 다를 수 있지만, url에 #id값이 추가됩니다. 예를들어 localhost:3000/#1, localhost:3000/#2, localhost:3000/#3과 같이 나타나게 됩니다.</p>
</li>
<li><p>동적 콘텐츠 처리의 어려움
페이지의 콘텐츠가 동적으로 로딩되는 경우, 예를 들어 Ajax나 API를 통해 콘텐츠를 로드할 때, 해당 id로 이동할 때 예상치 못한 결과가 발생할 수 있습니다. </p>
</li>
<li><p>부드러운 스크롤 제어 부족
기본적으로 a 태그와 id를 활용한 이동은 즉시 이동하는 방식입니다. 이때 이동이 부드럽게 이루어지지 않기 때문에 사용자가 갑작스럽게 이동하는 느낌을 받을 수 있습니다.</p>
</li>
</ol>
<p>개선방법  :  CSS의 scroll-behavior: smooth 속성 적용 -&gt; 이 경우 동작하지 않는 브라우저가 있는 경우도 있습니다. -&gt; 따라서 js를 통해 클릭 이벤트 발생시 처리하여 개선 할 수 있습니다.</p>
<h1 id="개선해보기">개선해보기</h1>
<ul>
<li><p>React를 사용하여 부드럽게 스크롤 되도록 수정해보도록 하겠습니다.</p>
</li>
<li><p>코드설명 </p>
<ol>
<li>useRef를 사용하여 원하는 DOM 요소에 접근</li>
<li>버튼 클릭시 특정 요소로 이동하도록 click Event 적용</li>
<li>window.scrollTo를 통해 이동을 원하는 요소의 offsetTop 위치로 이동시키고, behavior: &#39;smooth&#39; 속성을 통해 부드럽게 이동하도록 적용</li>
</ol>
</li>
</ul>
<pre><code class="language-javascript">import { useRef } from &#39;react&#39;;

const list = [
  {
    id: 1,
    name: &#39;Header&#39;,
    bgColor: &#39;#A76545&#39;,
  },
  {
    id: 2,
    name: &#39;Main&#39;,
    bgColor: &#39;#FFA55D&#39;,
  },
  {
    id: 3,
    name: &#39;Footer&#39;,
    bgColor: &#39;#FFDF88&#39;,
  },
];

function App() {
  const targetRef = useRef(null);

  const handleScrollToTarget = (idx) =&gt; {
    const targetDiv = targetRef.current.querySelectorAll(&#39;div&#39;)[idx];
    window.scrollTo({ top: targetDiv.offsetTop, behavior: &#39;smooth&#39; });
  };

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;div&gt;목차&lt;/div&gt;
      &lt;ul&gt;
        {list.map((data, idx) =&gt; (
          &lt;li key={data.id}&gt;
            &lt;button onClick={() =&gt; handleScrollToTarget(idx)}&gt;{data.name}&lt;/button&gt;
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;

      &lt;div ref={targetRef}&gt;
        {list.map((data) =&gt; (
          &lt;div
            key={data.id}
            style={{
              height: &#39;100vh&#39;,
              fontSize: &#39;25px&#39;,
              backgroundColor: data.bgColor,
            }}&gt;
            {data.name}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<h2 id=""><img src="https://velog.velcdn.com/images/rlaclghks123/post/2e9a9583-666c-40f1-a789-f52bda8b421e/image.gif" alt=""></h2>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://chatgpt.com/">chat GPT</a></li>
<li><a href="https://ko.react.dev/learn/referencing-values-with-refs">react 공식문서 ref</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - JOIN]]></title>
            <link>https://velog.io/@rlaclghks123/SQL-JOIN</link>
            <guid>https://velog.io/@rlaclghks123/SQL-JOIN</guid>
            <pubDate>Wed, 16 Apr 2025 14:29:43 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#join%EC%9D%B4%EB%9E%80">JOIN이란</a></li>
<li><a href="#inner-join">INNER JOIN</a></li>
<li><a href="#left-join">LEFT JOIN</a></li>
<li><a href="#right-join">RIGHT JOIN</a></li>
<li><a href="#full-outer-join">FULL OUTER JOIN</a></li>
</ul>
<hr>
<h1 id="join이란">JOIN이란</h1>
<ul>
<li>JOIN은 두 개 이상의 테이블을 하나로 결합하는 SQL 연산입니다.</li>
<li>관계형 데이터베이스에서는 데이터가 여러 테이블에 나뉘어 저장되므로, 이를 하나의 쿼리로 조회하려면 JOIN이 필요합니다.</li>
</ul>
<h3 id="왜-join이-필요한가">왜 JOIN이 필요한가?</h3>
<ul>
<li>예를 들어 users 테이블에는 사용자 정보가, orders 테이블에는 주문 정보가 있을 때:<ul>
<li>한 사용자가 어떤 상품을 주문했는지 알고 싶다면?</li>
<li>주문 정보를 불러오되, 사용자 이름까지 같이 보이게 하고 싶다면?</li>
</ul>
</li>
</ul>
<p>👉 이런 경우 JOIN을 사용하면 테이블 간의 관계를 바탕으로 관련 데이터를 연결할 수 있습니다. (쉽게 말해서 여러 테이블을 합쳐서 나타내기 위해 필요합니다)</p>
<hr>
<p>join에 알아보기 전 이해하기 쉽도록 사진을 하나 보고 가겠습니다. 혼공시리즈 라는 카페에 잘 정리된 사진이 있어서 가져왔습니다. </p>
<p><a href="https://hongong.hanbit.co.kr/sql-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-joininner-outer-cross-self-join/">사진 출처 : 혼공시리즈</a>
<img src="https://velog.velcdn.com/images/rlaclghks123/post/9b1b71cc-1646-429a-9964-18165008d602/image.png" alt=""></p>
<hr>
<h1 id="inner-join">INNER JOIN</h1>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/d18d4da2-e389-43e4-8a93-69fc9bea27c9/image.png" alt=""></p>
<ul>
<li><p><a href="https://sql-joins.leopard.in.ua/">사진출처</a></p>
</li>
<li><p>INNER JOIN의 경우 2개의 테이블에 공통으로 속한 데이터만 반환합니다.</p>
</li>
<li><p>만약 일치하지 않는다면 결과에서 제외됩니다.</p>
</li>
</ul>
<h3 id="inner-join-사용해보기">INNER JOIN 사용해보기</h3>
<ul>
<li>inner join은 줄여서 join으로 사용할 수 있습니다.</li>
<li>아래는 Book tabel, AUTHOR table 2개가 존재합니다.</li>
<li>아래의 2개의 테이블을 INNER JOIN을 하게 되면 아래와 같이 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/9c06c5a7-973a-4e31-8968-e0ec5707b7f1/image.png" alt=""></li>
</ul>
<pre><code class="language-js">-- join 쿼리문 
  SELECT *
  from BOOK bk
  JOIN (AUTHOR) au   -- inner join이 아닌 join으로 축약해서 사용 가능
  on bk.AUTHOR_ID = au.AUTHOR_ID; -- 두개의 테이블을 연결시킬 공통 key</code></pre>
<ul>
<li>아래와 같이 합쳐지게 됩니다. (위 테이블의 경우 author_id가 두 테이블 모두에 존재하므로, 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/515ffb57-b5c5-4ee3-b879-0393b2bc3077/image.png" alt=""></li>
</ul>
<h1 id="left-join">LEFT JOIN</h1>
<ul>
<li>왼쪽 테이블의 모든 데이터를 가져오고, 오른쪽 테이블에 일치하는 데이터가 없으면 NULL을 반환합니다.</li>
<li>아래는 Book tabel, AUTHOR table 2개가 존재합니다.</li>
<li>아래의 2개의 테이블을 LEFT JOIN을 하게 되면 아래와 같이 됩니다.</li>
<li>위 inner join과 달리 이번에는 BOOK에는 존재하지만(id=3), AUTHOR에는 존재하지 않는 데이터가(id=3) 있을 경우를 살펴보겠습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/9ec075f0-bb72-45ed-ab70-adbe0f61bff6/image.png" alt=""></li>
</ul>
<h3 id="inner-join할-경우">inner join할 경우</h3>
<ul>
<li>아래와 같이 BOOK에만 존재하던  id값이 3인 경우가 사라지고, 2개의 테이블에 공통을 존재하는 데이터만 나타내게 됩니다. </li>
</ul>
<pre><code class="language-js">-- 쿼리문
SELECT *
from BOOK bk
JOIN (select * from AUTHOR where author_id !=3) au
on bk.AUTHOR_ID = au.AUTHOR_ID;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/937496d6-467b-4b9a-8210-18263fdf91ce/image.png" alt=""></p>
<hr>
<h3 id="left-join할-경우">LEFT JOIN할 경우</h3>
<pre><code class="language-js">-- 쿼리문
SELECT *
from BOOK bk
LEFT JOIN (select * from AUTHOR where author_id !=3) au
on bk.AUTHOR_ID = au.AUTHOR_ID;</code></pre>
<ul>
<li><p>아래의 사진처럼 왼쪽 테이블(BOOK)의 데이터를 먼저 나타내고, 오른쪽 테이블(AUTHOR)에 BOOK과 다른 데이터(id=3)인 부분은 null값으로 나타내게 됩니다.</p>
</li>
<li><p>따라서 한쪽 테이블의 데이터를 무조건 남기고 싶다면 inner join이 아닌 left join을 사용할 수 있습니다. </p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/6aa99bdc-28d8-4e2e-b435-3541821b0b95/image.png" alt=""></p>
<h1 id="right-join">RIGHT JOIN</h1>
<ul>
<li>LEFT JOIN은 기준이 왼쪽 테이블이라면, RIGHT JOIN은 기준이 오른쪽 테이블입니다.</li>
<li>오른쪽 테이블의 모든 데이터를 가져오고, 왼쪽 테이블에 일치하는 데이터가 없으면 NULL을 반환합니다.</li>
</ul>
<pre><code class="language-js">-- RIGHT JOIN 쿼리문
  SELECT *
  from (select * from AUTHOR where author_id !=3) au
  RIGHT JOIN BOOK bk
  on bk.AUTHOR_ID = au.AUTHOR_ID;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/edbbfd5f-37e1-4ef1-8781-c7f764b1a0a0/image.png" alt=""></p>
<h1 id="full-outer-join">FULL OUTER JOIN</h1>
<ul>
<li><p>양쪽 테이블의 모든 데이터를 가져오고, 일치하지 않는 부분은 NULL로 채웁니다.</p>
</li>
<li><p>MY SQL의 경우 FULL OUTER JOIN을 지원하지 않습니다. 하지만 UNION을 사용하여 같은 기능을 하도록 흉내는 낼 수 있습니다.</p>
</li>
<li><p>아래의 2개의 테이블의 구성을 살펴보면 </p>
<ul>
<li>공통 1개, 서로 다른 id값이 각각 1개씩 존재합니다.</li>
<li>BOOK : id가 1,3으로 구성</li>
<li>AUTHOR : id가 1,2로 구성</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/a01cb2a6-5d05-4df6-8a60-ea54b2d0027b/image.png" alt=""></p>
<pre><code class="language-js">  SELECT *
  from (select * from AUTHOR where author_id !=3) au
  FULL OUTER JOIN (select * from BOOK where author_id !=2) bk
  on bk.AUTHOR_ID = au.AUTHOR_ID;</code></pre>
<ul>
<li>FULL OUTER JOIN을 하게 되면 아래와 같이 모두 나타내지만, 한쪽만 존재하는 데이터에는 null 값이 채워지게 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/8420a803-9e19-43d0-8957-10b3d6dc732a/image.png" alt=""></li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://sql-joins.leopard.in.ua/">SQL Joins Visualizer</a></li>
<li><a href="https://opentutorials.org/course/3884/25180">생활코딩 JOIN</a></li>
<li><a href="https://hongong.hanbit.co.kr/sql-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-joininner-outer-cross-self-join/">혼공시리즈</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL - select]]></title>
            <link>https://velog.io/@rlaclghks123/SQL-select</link>
            <guid>https://velog.io/@rlaclghks123/SQL-select</guid>
            <pubDate>Sun, 13 Apr 2025 15:10:52 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#sql%EC%9D%B4%EB%9E%80">SQL이란</a></li>
<li><a href="#select%EB%AC%B8-%EC%9E%91%EC%84%B1-%EB%B0%A9%EB%B2%95">select문 작성 방법</a></li>
</ul>
<h1 id="sql이란">SQL이란</h1>
<ul>
<li><p>SQL (Structured Query Language) 은 데이터베이스에서 데이터를 조회하고, 추가하고, 수정하고, 삭제(CRUD) 하기 위한 언어입니다.</p>
</li>
<li><p><code>데이터베이스를 조작하는 언어</code>입니다.</p>
</li>
<li><p>MySQL, PostgreSQL, Oracle등 SQL 문법은 대부분 공통이며, 일부 차이가 있습니다.</p>
</li>
</ul>
<h1 id="select문-작성-방법">select문 작성 방법</h1>
<ul>
<li>아래와 같이 select문을 작성할때는 순서가 있으며 이 순서대로 코드를 작성해야합니다. </li>
<li>select - from - where - group by - order by - limit을 주로 사용하는 것 같습니다. </li>
<li>출처 : <a href="#https://dev.mysql.com/doc/refman/8.4/en/select.html">MySQL 공식 홈페이지</a>
<img src="https://velog.velcdn.com/images/rlaclghks123/post/db537915-459e-4b88-a6bd-02e4acc67cd3/image.png" alt=""></li>
</ul>
<h3 id="select">select</h3>
<ul>
<li><p>사용방법 : <code>SELECT 컬럼명 FROM 테이블명;</code> </p>
</li>
<li><p>만약 모든 컬럼을 조회하고 싶다면 <code>*</code>를 사용할 수 있습니다. <code>select * from user</code></p>
</li>
<li><p>프로그래머스 문제로 알아보겠습니다.</p>
<ul>
<li><p>모든 컬럼 조회
<img src="https://velog.velcdn.com/images/rlaclghks123/post/301732dc-f8ca-4aa4-a5b5-652db1c53df7/image.png" alt=""></p>
</li>
<li><p>특정 컬럼 조회(user_id, age)
<img src="https://velog.velcdn.com/images/rlaclghks123/post/41301c53-1ba3-4dad-a1a5-758e0944c116/image.png" alt=""></p>
</li>
</ul>
</li>
</ul>
<h3 id="where">where</h3>
<ul>
<li>WHERE은 조건을 지정할 수 있는 키워드</li>
<li><code>=, &gt;, &lt;, &gt;=, &lt;=, !=</code> 등 연산자를 지원</li>
<li>아래의 경우 25살 이상인 경우 조건에 만족하는 데이터 조회
<img src="https://velog.velcdn.com/images/rlaclghks123/post/7feac160-1569-4d16-b183-fa710e776a0d/image.png" alt=""></li>
</ul>
<h3 id="group-by">group by</h3>
<ul>
<li>GROUP BY는 데이터를 그룹으로 묶어 집계할 때 사용</li>
<li>아래의 경우 25세 이상이면서 age를 기준으로 그룹화 해서, 각 나이의 총 인원수를 조회</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/325ba44e-eeb5-41d5-a5ac-58858c18bbbc/image.png" alt=""></p>
<h3 id="having-by">having by</h3>
<ul>
<li>having by는 group by를 통해 그룹화한 데이터의 조건을 주는 쿼리문입니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/7d6790e0-1289-49d4-ab49-f0c442c9730d/image.png" alt=""></li>
</ul>
<h3 id="order-by">order by</h3>
<ul>
<li>조회한 데이터에 대한 정렬 하는 쿼리문 </li>
<li>ASC: 오름차순 (기본값)</li>
<li>DESC: 내림차순
<img src="https://velog.velcdn.com/images/rlaclghks123/post/09c38123-fbd8-4058-aac5-c422692263e2/image.png" alt=""></li>
</ul>
<h3 id="limit">limit</h3>
<ul>
<li>개수를 제한할때 사용
<img src="https://velog.velcdn.com/images/rlaclghks123/post/c9d0fa0f-a778-45d1-ac5f-356296fea7a9/image.png" alt=""></li>
</ul>
<h3 id="집계함수">집계함수</h3>
<ul>
<li><p>이미 위에서 하나 사용했지만 <code>COUNT(), AVG(), SUM(), MAX(), MIN()</code> 등 다양한 집계 함수 제공</p>
</li>
<li><p>사용 위치는 select 컬럼명 from ... 으로 작성할때 컬럼명을 기입하는 부분에서 사용</p>
</li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://dev.mysql.com/doc/refman/8.4/en/select.html">my sql 공식홈페이지</a></li>
<li><a href="https://opentutorials.org/course/3161/19540!%5B%5D(https://velog.velcdn.com/images/rlaclghks123/post/52802969-680d-4779-a93a-4dc5fe8ca3e6/image.jpg)">생활코딩 SQL</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS - 마진 병합]]></title>
            <link>https://velog.io/@rlaclghks123/CSS-%EB%A7%88%EC%A7%84-%EB%B3%91%ED%95%A9</link>
            <guid>https://velog.io/@rlaclghks123/CSS-%EB%A7%88%EC%A7%84-%EB%B3%91%ED%95%A9</guid>
            <pubDate>Sun, 06 Apr 2025 12:06:01 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#%EB%A7%88%EC%A7%84-%EB%B3%91%ED%95%A9%EC%9D%B4%EB%9E%80">마진 병합이란</a></li>
<li><a href="#%EB%A7%88%EC%A7%84-%EB%B3%91%ED%95%A9%EC%9D%B4-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0">마진 병합이 발생하는 이유</a></li>
<li><a href="#%EB%A7%88%EC%A7%84-%EB%B3%91%ED%95%A9%EC%9D%B4-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-%EA%B2%BD%EC%9A%B0">마진 병합이 발생하는 경우</a></li>
<li><a href="#%EB%A7%88%EC%A7%84-%EB%B3%91%ED%95%A9-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95">마진 병합 해결 방법</a></li>
<li><a href="#%EC%B0%B8%EA%B3%A0">참고</a></li>
</ul>
<hr>
<h1 id="마진-병합이란">마진 병합이란</h1>
<ul>
<li>마진 병합(Margin Collapse)이란, <code>두 개의 블럭 요소의 상하 마진이 만날 때</code>, 두 마진 중 더 <code>큰 값 하나만 적용되는 현상</code>을 의미합니다. 즉, 마진이 단순히 더해지지 않고 병합되어 하나의 값으로 계산됩니다.</li>
</ul>
<h1 id="마진-병합이-발생하는-이유">마진 병합이 발생하는 이유</h1>
<ul>
<li><p>마진 병합이 발생하는 이유는 무엇일까요? 버그일까요? </p>
</li>
<li><p>마진 병합은 CSS 설계상 의도된 동작입니다. <code>CSS는 문단 간의 자연스러운 간격이나 레이아웃 흐름을 위해</code> 마진병합을 발생시키도록 의도했습니다. </p>
</li>
<li><p>레이아웃의 자연스러운 흐름을 위해 의도된 동작이지만, 상황에 따라서 잘못된 경우가 있기 때문이 이 경우 의도적으로 마진병합이 발생하지 않도록 처리 할 수 있습니다.</p>
</li>
</ul>
<h1 id="마진-병합이-발생하는-경우">마진 병합이 발생하는 경우</h1>
<ul>
<li>형제 요소 간의 마진 병합</li>
<li>부모와 자식 요소 간의 마진 병합</li>
<li>빈 블록 요소에서의 마진 병합</li>
</ul>
<h3 id="1-형제-요소-간의-마진-병합">1. 형제 요소 간의 마진 병합</h3>
<ul>
<li><p>두 개의 블록 요소가 수직으로 배치될 때, 아래쪽 요소의 margin-top과 위쪽 요소의 margin-bottom이 병합됩니다.</p>
</li>
<li><p>아래의 코드를 보면 .box1과 .box2 사이의 마진은 20px + 30px = 50px으로 예상되지만, 실제로는 30px로 병합됩니다.</p>
</li>
</ul>
<pre><code class="language-css">    .box1 {
      margin-bottom: 20px;
    }

    .box2 {
      margin-top: 30px;
    }</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/e68171aa-33d1-45c2-b023-08fe0caa63d5/image.jpg" alt=""></p>
<ul>
<li><p>참고로 두 개의 요소가 수직이 아닌 수평(가로)으로 배치 될 경우 병합이 발생하지 않습니다.</p>
<pre><code class="language-css">  .box1 {
    margin-right: 20px;
  }

  .box2 {
    margin-left: 30px;
  }</code></pre>
</li>
<li><p>따라서 아래의 경우 서로의 마진은 20 + 30 = 50px이 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/2035ebde-e19a-45aa-8b06-8abac99f94ce/image.jpg" alt=""></p>
</li>
</ul>
<h3 id="2-부모와-자식-요소-간의-마진-병합">2) 부모와 자식 요소 간의 마진 병합</h3>
<ul>
<li>자식 요소의 margin-top이 부모 요소의 margin-top과 병합되는 경우입니다.</li>
</ul>
<pre><code class="language-css">  .parent {
    margin-top: 20px;
  }

  .child {
    margin-top: 30px;
  }</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/9dd56d8b-d8f0-4871-a978-67888745570c/image.jpg" alt=""></p>
<ul>
<li>물론 부모자식 관계에서도 <code>수평 배치는 마진병합이 발생하지 않습니다.</code></li>
</ul>
<pre><code class="language-css">  .parent {
    margin-left: 20px;
  }

  .child {
    margin-left: 30px;
  }</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/9bafd5d1-e7ab-4640-a4a9-4ae3fd0e350d/image.jpg" alt=""></p>
<h3 id="3-빈-블록-요소에서의-마진-병합">3) 빈 블록 요소에서의 마진 병합</h3>
<ul>
<li><p>내용이 없는 블록 요소도 마진 병합이 발생할 수 있습니다.</p>
</li>
<li><p>30 + 40 = 40px로 마진병합이 발생합니다.</p>
<pre><code class="language-css">    .box1 {
      background-color: green;
      width: 200px;
      height: 200px;
      margin-bottom: 30px;
    }
    .empty {
      background-color: tomato;
      margin-top: 40px;
    }
</code></pre>
</li>
</ul>
<pre><code>
![](https://velog.velcdn.com/images/rlaclghks123/post/20a9a5ff-47d2-4dd1-a72f-ac24d60d3f3a/image.jpg)

- 물론 수평일때는 발생하지 않습니다.

- 수평으로 배치 될 경우 30 + 40 = 70px의 마진이 발생합니다.
![](https://velog.velcdn.com/images/rlaclghks123/post/5c86df59-67c1-4082-ba02-96f51ad8e894/image.jpg)


---

# 마진 병합 해결 방법
- 형제간 마진병합 발생시 `빈 table 태그 추가`
- 형제간 마진병합 발생시 둘 중 하나 혹은 모두 `display 속성값을 inline-block 적용`
- 부모 - 자식간의 마진병합시 `부모 요소에 overflow:hidden 적용`
- 부모 - 자식간의 마진병합시 `부모 요소에 padding 적용`
- 부모 - 자식간의 마진병합시 `부모 요소에 border 적용`
- 부모 - 자식간의 마진병합시 `부모 요소에 내용 추가`

### 1. 형제간 마진병합 발생시 빈 table 태그 추가
- 형제간의 마진병합이 일어난 경우 형제 사이에 table 태그를 추가하면 마진병합을 방지할 수 있습니다.
</code></pre><pre><code>&lt;div class=&quot;wrapper&quot;&gt;
  &lt;div class=&quot;box1&quot;&gt;box1&lt;/div&gt;
  &lt;table&gt;&lt;/table&gt; // 사이에 table 태그 추가
  &lt;div class=&quot;box2&quot;&gt;box2&lt;/div&gt;
&lt;/div&gt;</code></pre><pre><code>
![](https://velog.velcdn.com/images/rlaclghks123/post/c2190a51-24c9-4b68-94a5-454c28259d58/image.png)


### 2. 형제간 마진병합 발생시 둘 중 하나 혹은 모두 display 속성값을 inline-block 적용

```css
 .box1 {
        border: 1px solid black;
        background-color: blue;
        width: 200px;
        height: 200px;
        margin-bottom: 50px;
      }
 .box2 {
        border: 1px solid black;
        background-color: orange;
        display: inline-block;  // display속성 inline 적용
        width: 200px;
        height: 200px;
        margin-top: 20px;
      }</code></pre><pre><code class="language-html">    &lt;div class=&quot;wrapper&quot;&gt;
      &lt;div class=&quot;box1&quot;&gt;box1&lt;/div&gt;
      &lt;div class=&quot;box2&quot;&gt;box2&lt;/div&gt;
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/c2190a51-24c9-4b68-94a5-454c28259d58/image.png" alt=""></p>
<h3 id="3-부모---자식간의-마진병합시-부모-요소에-overflowhidden-적용">3. 부모 - 자식간의 마진병합시 부모 요소에 overflow:hidden 적용</h3>
<pre><code class="language-css">.parent {
        background-color: beige;
        overflow: hidden; // 부모 요소에 overflow:hidden 적용
        margin-top: 50px;
      }

.child {
        border: 1px solid black;
        background-color: blue;
        width: 200px;
        height: 200px;
        margin-top: 20px;
      }</code></pre>
<pre><code class="language-html">     &lt;div class=&quot;parent&quot;&gt;
      &lt;div class=&quot;child&quot;&gt;child&lt;/div&gt;
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/df2661b8-c969-46fd-9c94-75f79dd82fe0/image.png" alt=""></p>
<h3 id="4-부모---자식간의-마진병합시-부모-요소에-padding-적용">4. 부모 - 자식간의 마진병합시 부모 요소에 padding 적용</h3>
<pre><code class="language-css">.parent {
        background-color: beige;
        padding: 1px; // 부모 요소에 padding 적용
        margin-top: 50px;
      }

.child {
        border: 1px solid black;
        background-color: blue;
        width: 200px;
        height: 200px;
        margin-top: 20px;
      }</code></pre>
<pre><code class="language-html">     &lt;div class=&quot;parent&quot;&gt;
      &lt;div class=&quot;child&quot;&gt;child&lt;/div&gt;
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/df2661b8-c969-46fd-9c94-75f79dd82fe0/image.png" alt=""></p>
<h3 id="5-부모---자식간의-마진병합시-부모-요소에-border-적용">5. 부모 - 자식간의 마진병합시 부모 요소에 border 적용</h3>
<ul>
<li>이건 border가 보이기 때문에 단순히 마진병합을 없애는 용도로 사용하기엔 그닥 좋아보이진 않음</li>
</ul>
<pre><code class="language-css">.parent {
        background-color: beige;
        border: 1px solid black; // 부모 요소에 border적용
        margin-top: 50px;
      }

.child {
        border: 1px solid black;
        background-color: blue;
        width: 200px;
        height: 200px;
        margin-top: 20px;
      }</code></pre>
<pre><code class="language-html">     &lt;div class=&quot;parent&quot;&gt;
      &lt;div class=&quot;child&quot;&gt;child&lt;/div&gt;
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/7e89e69b-57d5-4a3b-971b-795cd0771ec3/image.png" alt=""></p>
<h3 id="6-부모---자식간의-마진병합시-부모-요소에-내용-추가">6. 부모 - 자식간의 마진병합시 부모 요소에 내용 추가</h3>
<ul>
<li>이것 또한 부모 요소의 내용이 보이기 때문에 단순히 마진병합을 없애는 용도로 사용하기엔 그닥 좋아보이진 않음</li>
</ul>
<pre><code class="language-css">.parent {
        background-color: beige;
        margin-top: 50px;
      }

.child {
        border: 1px solid black;
        background-color: blue;
        width: 200px;
        height: 200px;
        margin-top: 20px;
      }</code></pre>
<pre><code class="language-html">     &lt;div class=&quot;parent&quot;&gt;
       부모 // 부모 요소에 내용 추가
      &lt;div class=&quot;child&quot;&gt;child&lt;/div&gt;
    &lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/c0faa767-aca5-47b7-98ff-d14e921040b2/image.png" alt=""></p>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://www.youtube.com/watch?v=c19Mjg-ivxc">veamcamp 마진병합</a></li>
<li><a href="https://www.youtube.com/watch?v=zZjTUDAR0ik">생활코딩 마진 겹침</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/CSS/CSS_box_model/Mastering_margin_collapsing">CSS MDN - 여백 상쇄 정복</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - useEffect 의존성 배열 내부 데이터 타입에 따른 리렌더링 비교]]></title>
            <link>https://velog.io/@rlaclghks123/React-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85%EC%97%90-%EB%94%B0%EB%A5%B8-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@rlaclghks123/React-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85%EC%97%90-%EB%94%B0%EB%A5%B8-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Sun, 23 Mar 2025 12:26:34 GMT</pubDate>
            <description><![CDATA[<p><code>이번에 작성한 글은 저의 생각과 GPT를 활용하여 궁금한 부분을 확인한 내용이므로 신뢰성이 비교적 낮을 수 있습니다. 만약 잘못된 지식이 존재한다면 댓글 부탁드립니다.</code></p>
<p>문득 useEffect 의존성 배열에 아래의 2가지 값을 담을 경우 어떻게 출력되는지 궁금해졌습니다. </p>
<ol>
<li>전역 변수로 선언된 경우(원시값, 참조값) </li>
<li>지역 변수로 선언된 경우(원시값, 참조값)</li>
</ol>
<h1 id="데이터-타입에-따른-리렌더링-비교">데이터 타입에 따른 리렌더링 비교</h1>
<ul>
<li><p>따라서 총 테스트 할 부분은 전역변수 3가지(문자열, 배열, 객체)와 지역변수(문자열, 배열, 객체)입니다.</p>
</li>
<li><p>테스트 해볼 코드 </p>
<ul>
<li>전역변수 : 빨간색</li>
<li>지역변수 : 초록색</li>
<li>useEffect를 통해 리렌더링 여부 확인</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/c67ba699-684d-4e0a-9558-7d13e1aa6436/image.png" alt=""></p>
<ul>
<li><p>결과는 아래와 같이 나옵니다. </p>
<ol>
<li>처음 렌더링시 모든 값이 출력됩니다. </li>
<li>버튼을 클릭하여 상태값을 변경시켜 리렌더링을 발생시킵니다.</li>
<li>리렌더링이 발생합니다.</li>
<li>내부에 선언된 object 타입(객체, 배열)만 리렌더링이 발생합니다.</li>
</ol>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/8cf19678-d186-4460-b1ca-00941d0ae02c/image.png" alt=""></p>
<ol>
<li>왜 외부에 선언한 object 타입은 호출되지 않을까?</li>
<li>왜 내부에 선언한 object 타입은 호출이 될까?</li>
<li>왜 외부에 선언한 원시값은 호출되지 않을까?</li>
<li>왜 내부에 선언한 원시값은 호출되지 않을까?</li>
</ol>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/53b4dfc3-7ee5-4c16-b037-9b9c523644e0/image.png" alt=""></p>
<ul>
<li>리액트의 경우 위 사진과 같이 리렌더링이 발생하면 새롭게 App 함수를 실행하게 됩니다. 이 과정에서 가상돔은 이전 App 컴포넌트와 비교해서 <code>변경이 발생한 부분만 수정합니다.</code></li>
</ul>
<h3 id="외부에-선언한-값은-왜-호출되지-않을까">외부에 선언한 값은 왜 호출되지 않을까?</h3>
<p>1번과 3번의 질문인 외부에 선언한 경우 원시값이든, 참조값이든 외부 저장소에 해당값이 저장되어 있기 때문에 App 컴포넌트가 매번 새롭게 만들어지더라도, 변하지 않는 고정된 값을 가리키기 때문에 이전값과 달라지지 않아 useEffect가 실행되지 않고, 따라서 호출되지 않습니다.</p>
<h3 id="내부에-선언한-원시값은-왜-호출되지-않을까">내부에 선언한 원시값은 왜 호출되지 않을까?</h3>
<p>내부에 선언된 원시값은 App 함수가 리렌더링될 때마다 새로 생성됩니다. 그러나 useEffect의 의존성 배열에 포함된 원시값은 Object.is 비교를 통해 이전 값과 동일한지 확인하고, 동일하다면 useEffect는 실행되지 않습니다. 따라서 호출되지 않습니다.</p>
<h3 id="내부에-선언한-참조값은-왜-호출될까">내부에 선언한 참조값은 왜 호출될까?</h3>
<p>useEffect의 의존성 배열에 내부에 선언된 참조값을 추가할 경우, 이전값과 Object.is로 비교할때 이전값과 현재값은 동등하지만, 참조값이 달라지기 때문에 같다고 판단되지 않아 useEffect가 실행되고, 따라서 호출이 됩니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Today I Learn]- SSH란]]></title>
            <link>https://velog.io/@rlaclghks123/Today-I-Learn-SSH%EB%9E%80</link>
            <guid>https://velog.io/@rlaclghks123/Today-I-Learn-SSH%EB%9E%80</guid>
            <pubDate>Sun, 09 Mar 2025 10:54:36 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#ssh%EB%9E%80">SSH란</a>
<a href="#ssh-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0">SSH 접속하기</a>
<a href="#%EC%B0%B8%EA%B3%A0%EC%9E%90%EB%A3%8C">참고자료</a></p>
<hr>
<h3 id="ssh란">SSH란</h3>
<ul>
<li><p>SSH란 Secure Shell의 줄임말로, <code>원격 호스트에 접속하기 위해 사용되는 보안 프로토콜입니다</code></p>
</li>
<li><p>등장배경</p>
<ul>
<li><p>기존 원격 접속은 텔넷(Telnet)이라는 방식을 사용했는데, 암호화를 제공하지 않기 때문에 보안상 취약하다는 단점이 있었습니다.  </p>
</li>
<li><p>따라서 이를 암호화하는 SSH 기술이 등장했습니다.</p>
</li>
<li><p>SSH 클라이언트와 SSH 서버의 관계로 상호작용하면서 SSH 서버가 설치된 운영체제를 제어합니다.</p>
</li>
<li><p>클라이언트와 서버 사이에는 강력한 암호화 방법을 통해서 연결되어 있기 때문에 데이터를 중간에서 가로채도 해석 할 수 없는 암호화된 문자만이 노출됩니다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/74e7ae74-a39b-4570-89ca-acf5d0f4f510/image.png" alt=""></p>
</li>
</ul>
<blockquote>
<p>쉽게 말해서 SSH란 shell 즉 터미널을 이용해서 원격서버와 정보를 안전하게 교환할 수 있는 하나의 방법이라고 볼 수 있습니다. </p>
</blockquote>
<hr>
<h1 id="ssh-접속하기">SSH 접속하기</h1>
<h3 id="mac에서-ssh-접속하기">MAC에서 SSH 접속하기</h3>
<ul>
<li><p>리눅스와 Mac과 같은 Unix 계열의 운영체제는 기본적으로 SSH 클라이언트가 설치 되어 있기 때문에 SSH를 이용하기 위해서 특별한 클라이언트가 필요하지 않습니다.</p>
</li>
<li><p>그렇다면 어떻게 사용할까요?</p>
<ol>
<li>터미널을 켭니다.</li>
<li>명령어를 통해 접속합니다. <code>ssh 계정@IP주소</code> 입력 (파란색 박스)</li>
<li>비밀번호 입력(초록색 박스)</li>
<li>원격 서버에 접속(노란색 박스)</li>
</ol>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/3d8fe893-6e20-4982-8e90-96836aa5b6ca/image.jpg" alt=""></p>
<h3 id="window에서-ssh-접속하기">WINDOW에서 SSH 접속하기</h3>
<ul>
<li><p>윈도우 운영체제에는 SSH 클라이언트가 설치되어 있지 않습니다. 따라서 SSH 클라이언트를 설치해야 윈도우에서 Unix 계열의 운영체제를 제어 할 수 있습니다.</p>
</li>
<li><p>Xshell, Putty, mobaxterm 등 여러개 중 하나 다운받아서 사용할 수 있습니다.</p>
</li>
<li><p>저는 mobaxterm를 통해 진행해보겠습니다. <a href="https://mobaxterm.mobatek.net/">mobaxterm 다운로드 하기</a></p>
</li>
<li><p>mobaxterm를 선택한 이유는 SSH뿐 아니라 FTP, SFTP, Telnet, AWS S3 등 여러가지를 사용할 수 있기 때문에 선택했습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/baffead0-3df7-47c8-843d-003f90fcd376/image.jpg" alt=""></p>
</li>
</ul>
<ul>
<li>사용방법 <ol>
<li>SSH 툴을 실행한다.(저의 경우 mobaxterm 사용)</li>
<li>SSH session을 킨다.</li>
<li>SSH에 로그인한다.</li>
<li>원격서버에 접속</li>
</ol>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/1b6e520c-48c6-4e8a-ac36-9b0eb0eef633/image.jpg" alt=""></p>
<hr>
<h1 id="참고자료">참고자료</h1>
<ul>
<li><a href="https://opentutorials.org/module/432/3738">생활코딩 SSH</a></li>
<li><a href="https://library.gabia.com/contents/infrahosting/9002/">가비아 라이브러리</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue - computed vs method]]></title>
            <link>https://velog.io/@rlaclghks123/Vue-computed-vs-method-vs-watch</link>
            <guid>https://velog.io/@rlaclghks123/Vue-computed-vs-method-vs-watch</guid>
            <pubDate>Sun, 02 Mar 2025 12:09:33 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#computed-%EC%86%8D%EC%84%B1">computed 속성</a>
<a href="#method-%EC%86%8D%EC%84%B1">method 속성</a>
<a href="#computed%EC%99%80-method-%EC%B0%A8%EC%9D%B4">computed와 method 차이</a>
<a href="#%EC%B0%B8%EA%B3%A0">참고</a></p>
<hr>
<h1 id="computed-속성">computed 속성</h1>
<ul>
<li><p>vue에서 데이터 바인딩의 가장 기본 형태는 “Mustache” 구문(이중 중괄호)을 사용한 텍스트 보간을 통해 작성할 수 있습니다. </p>
</li>
<li><p>간단한 코드는 템플릿 내에 보간법을 사용해서 작성할 수 있지만, 코드가 비대해지면 문제점이 발생합니다.</p>
</li>
</ul>
<ol>
<li>가독성 저하</li>
<li>유지보수 어려움</li>
</ol>
<ul>
<li>그래서 등장한 것이 바로 computed 입니다.</li>
</ul>
<pre><code class="language-javascript">    // 보간법 사용
    &lt;div id=&quot;example&quot;&gt;
      {{ message.split(&#39;&#39;).reverse().join(&#39;&#39;) }}
    &lt;/div&gt;


    // computed 사용
    &lt;div id=&quot;example&quot;&gt;
      {{ reversecMessage }}
    &lt;/div&gt;</code></pre>
<hr>
<h1 id="method-속성">method 속성</h1>
<ul>
<li><p>method 속성 함수는 일반 자바스크립트 함수와 같다고 볼 수 있습니다. </p>
</li>
<li><p>즉 vue에서 함수를 사용하는 방법 중 하나로 method를 사용하면 됩니다.</p>
</li>
</ul>
<blockquote>
<p>단순히 가독성, 유지보수를 위해 코드를 분리하기 위한 방법은 method, computed 2개가 존재하는데  그럼 computed랑 어떤 차이가 있을까?? 궁금해졌습니다.</p>
</blockquote>
<hr>
<h1 id="computed와-method-차이">computed와 method 차이</h1>
<ul>
<li><p>가장 큰 차이점은 캐싱의 유무입니다.</p>
</li>
<li><p>method는 캐싱이 되지 않지만, computed는 캐싱이 됩니다. </p>
</li>
<li><p>computed는 <code>data 변경이 없으면</code> 컴포넌트가 리랜더링이 되어도 함수를 다시 등록하지 않습니다.</p>
</li>
<li><p>아래의 사진에서 상태값은 아래와 같이 관리됩니다.</p>
<ul>
<li>점수 : method</li>
<li>이름 : computed</li>
</ul>
</li>
<li><p>따라서 점수가 올라갈 경우 이름은 캐싱되어 렌더링 되지 않지만, 이름이 변경될 경우 이름, 점수 모두 렌더링 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/6b2f4c3b-86a9-4b7f-a2e9-8ca4f0426b0d/image.jpg" alt=""></p>
</li>
</ul>
<blockquote>
<p>따라서 특별한 이유가 따로 있지 않다면 computed를 사용하는 것이 성능적인 측면에서 더 좋습니다. </p>
</blockquote>
<h3 id="특별한-경우">특별한 경우</h3>
<ul>
<li>그럼 특별한 경우는 뭐가 있을까요?(주관적인 생각)</li>
</ul>
<ol>
<li>캐싱을 원하지 않는 상황</li>
<li>인자를 받아서 처리하는 상황</li>
<li>반환값이 없는 경우</li>
</ol>
<h3 id="캐싱을-원하지-않는-상황">캐싱을 원하지 않는 상황</h3>
<ul>
<li>사실 이런 경우가 있지 않을까 라는 생각을 하지만, 정확히 어떤 상황인진 잘 모르겠습니다.</li>
</ul>
<h3 id="인자를-받아서-처리하는-상황">인자를 받아서 처리하는 상황</h3>
<ul>
<li><p>아래와 같이 index값이 짝수인 경우만 나타내려고 합니다 &gt; 만약 computed에서 index를 인자로 받아서 처리하려고 하면 아래와 같이 에러가 발생합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/994f469a-9b90-4bda-a020-18390e3928a1/image.jpg" alt=""></p>
</li>
<li><p>따라서 아래와 같이 method로 처리해야 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/56030bc7-6fa5-4dd0-af66-afa0fa1ee104/image.jpg" alt=""></p>
</li>
</ul>
<h3 id="반환값이-없는-경우">반환값이 없는 경우</h3>
<ul>
<li>아래와 같이 event Handler의 경우 반환값이 없고, data값을 변경하는 경우 computed로 사용하면 많은 에러를 마주칩니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/77c4c97f-3406-48e2-ae27-41d7f4e3df3d/image.jpg" alt=""></p>
<ul>
<li>따라서 computed가 아닌 method를 사용해야 합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/b2567339-b6a9-4e4c-b8db-e4a0feca396a/image.jpg" alt=""></li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<p><a href="#https://v2.ko.vuejs.org/v2/guide/computed.html#computed-%EC%86%8D%EC%84%B1%EC%9D%98-%EC%BA%90%EC%8B%B1-vs-%EB%A9%94%EC%86%8C%EB%93%9C">vue 공식문서</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[고민해보기 - 팝업창 재활용]]></title>
            <link>https://velog.io/@rlaclghks123/%EA%B3%A0%EB%AF%BC%ED%95%B4%EB%B3%B4%EA%B8%B0-%ED%8C%9D%EC%97%85%EC%B0%BD-%EC%9E%AC%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@rlaclghks123/%EA%B3%A0%EB%AF%BC%ED%95%B4%EB%B3%B4%EA%B8%B0-%ED%8C%9D%EC%97%85%EC%B0%BD-%EC%9E%AC%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Sun, 23 Feb 2025 10:32:34 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#%EA%B3%A0%EB%AF%BC%ED%95%B4%EB%B3%B4%EA%B8%B0">고민해보기</a>
<a href="#%EC%BD%94%EB%93%9C-%EC%9E%AC%ED%99%9C%EC%9A%A9">코드 재활용</a></p>
<h1 id="고민해보기">고민해보기</h1>
<ul>
<li><p>개발자마다 좋은 코드의 기준은 다를 수 있지만, 현재 제 생각으로 좋은 코드란 <code>변경하기 쉬운 코드</code>라고 생각합니다. 물론 이 기준이 언제 어떻게 바뀔지는 모르겠지만, <code>변경하기 쉬운 코드</code>가 나의 야근을 줄여주고, 나의 스트레스를 줄여주고, 나의 귀찮음을 줄여주기 때문입니다. </p>
</li>
<li><p>그래서 오늘은 변경하기 쉬운 코드를 잘 작성하기 위해 한 단계 성장하기 위해 고민해 본 부분을 적어보려고 합니다. </p>
</li>
<li><p>지금부터 작성하는 코드는 정말 좋은 코드가 맞는지, 굳이 이렇게? 혹은 잘못된 방향으로 작성됐을 수 있습니다. 혹시 이 글을 보신다면 피드백 적극 찬성입니다. </p>
</li>
</ul>
<hr>
<h1 id="코드-재활용">코드 재활용</h1>
<ul>
<li><p>똑같지는 않지만 같은 기능을 하고, 비슷한 UI를 나타내는 부분을 어떻게 재활용할 수 있을까? 고민해 보고 적용해 보려고 합니다.</p>
</li>
<li><p>아래의 사진과 같이 비슷하지만, 똑같지는 않은 3개의 팝업이 존재합니다. </p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/f164e2b9-382a-4757-8e6b-74e20f3b7db5/image.png" alt=""></p>
<h3 id="공통점">공통점</h3>
<ol>
<li>팝업창 열기</li>
<li>x버튼 클릭시 팝업창 닫기</li>
</ol>
<h3 id="차이점">차이점</h3>
<ol>
<li>빨간색 팝업 : title이 없음, contents 내용이 다름</li>
<li>초록색 팝업 : title 밑에 실선이 존재, contents 내용이 다름</li>
<li>파란색 팝업 : title 밑에 점선이 존재, contents 내용이 다름</li>
</ol>
<h3 id="코드-작성">코드 작성</h3>
<ul>
<li>공통으로 적용할 컴포넌트에서는 아래와 같이 구성합니다.<ol>
<li>title : 선택적으로 props로 받아서 처리</li>
<li>contents : 필수적으로 props로 받아서 처리</li>
<li>x버튼 : ui 및 기능 고정</li>
</ol>
</li>
</ul>
<blockquote>
<p>저는 vue2를 통해 코드를 작성했습니다. 
만약 react로 작성한다면 slot 부분은 children을 사용, emit 부분은 props로 setter를 받거나, 전역 상태로 팝업창 상태로 관리하면 될 것 같습니다. </p>
</blockquote>
<h3 id="공통-컴포넌트">공통 컴포넌트</h3>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/61ad2197-1fd4-4d41-80ee-6d12c99bb31a/image.png" alt=""></p>
<h3 id="적용-코드">적용 코드</h3>
<ul>
<li>title 부분은 css(className)과 title명을 다르게 전달했습니다.</li>
<li>contents 부분은 너무 길어서 접어놨지만, 내용이 다릅니다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/a7c06430-1449-4bb0-b86c-444830ff112e/image.png" alt=""></p>
<h3 id="결과적으로">결과적으로</h3>
<ul>
<li><p>만약 자료실, 자료검색, 자료탐색, 자료..1, 자료...2, 자료..30 총 30개의 팝업을 만들었고, 닫기버튼의 css를 수정해주세요! 라는 요구사항이 추가된다면 30개의 팝업을 다 수정해야하는 문제가 발생할 수 있습니다.</p>
</li>
<li><p>물론 엄청 대단한 코드를 작성하진 않았지만 위 코드는 최소한 공통적으로 사용되는 버튼에 관련된 부분을 수정하거나, title 및 contents 분에 공통적으로 수정해야 할 부분이 발생한다면 팝업이 30개든, 300개든, 30000개든 한 번만 수정하면 되기 때문에 많은 시간을 줄여줄 수 있을 것 같습니다.<img src="https://velog.velcdn.com/images/rlaclghks123/post/d612fa0a-1535-49b1-acb2-135458425555/image.png" alt=""></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript - package.json과 package-lock.json 차이]]></title>
            <link>https://velog.io/@rlaclghks123/Javascript-package.json%EA%B3%BC-package-lock.json-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@rlaclghks123/Javascript-package.json%EA%B3%BC-package-lock.json-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Fri, 21 Feb 2025 12:30:53 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#packagejson%EC%9D%B4%EB%9E%80">package.json이란</a>
<a href="#package-lockjson%EC%9D%B4%EB%9E%80">package-lock.json이란</a>
<a href="#packagejson%EA%B3%BC-package-lockjson%EC%9D%98-%EC%B0%A8%EC%9D%B4">package.json과 package-lock.json의 차이</a>
<a href="#%EC%B0%B8%EA%B3%A0">참고</a></p>
<hr>
<p>오늘 지인 중 한 명이 package.json이랑 package-lock.json 차이가 뭔지 아시나요? 라고 물어보길래 <code>버전 관리를 다르게 하는 것으로 알고 있습니다.</code>  라고 답은 했지만, 확신이 없었습니다. 
뭔가 면접 준비하면서 공부했던 것 같은데 기억이 나질 않아 오늘은 이 둘의 차이에 대해 공부해 보고자 합니다. </p>
<h1 id="packagejson이란">package.json이란</h1>
<ul>
<li><p>package.json이란
<img src="https://velog.velcdn.com/images/rlaclghks123/post/78b84510-710e-47e6-8f62-44970fa278a7/image.png" alt=""></p>
</li>
<li><p>깨알 영어공부를 위해 해석해보자면 </p>
<pre><code>  당신의 패키지에 package.json 파일을 추가하면 다른 사람들이 쉽게 관리하고 설치할 수 있습니다. registry(패키지 저장소)에 등록되는 패키지는 반드시 package.json 파일을 포함해야 합니다

  - 프로젝트가 의존하는 패키지 목록을 작성
  - 시맨틱 버전 규칙을 사용하여 당신의 프로젝트 패키지의 구체적인 버전을 명시
  - build를 reproduceible(재현 가능) 하도록 다른 개발자에게 쉽게 공유</code></pre></li>
<li><p>즉 <code>package.json이란 다른 사람(협업자)들이 배포한 사람이 올린 코드를 쉽게 관리하고 설치할 수 있도록 사용되는 문서</code>입니다. </p>
</li>
<li><p>위 글에서 <code>시맨틱 버전 규칙을 사용</code> 하여 구체적인 버전을 명시하라고 했는데, 이게 무슨 의미일까요?</p>
</li>
</ul>
<h2 id="시맨틱-버전-규칙">시맨틱 버전 규칙</h2>
<ul>
<li><p>시멘틱 버저닝 이란 패키지의 일반적인 버전의 표현 방식을 의미합니다. </p>
</li>
<li><p><code>{MAJOR}.{MINOR}.{PATCH}</code> 형식으로 표기합니다. ex) 1.3.0 </p>
<ol>
<li><p>MAJOR: 하위호환성이 보장되지 않는 변경사항 발생시 ⇒ 매우 큰 변화, 새로운 버전급 변화 ⇒ 큰 변화가 있으므로 <code>내 코드도 수정해야함</code> </p>
</li>
<li><p>MINOR: 하위호환성 보장 하면서 기능추가 ⇒ 새로운 기능 등 추가되는 경우 예를들어 react hook, class로도 사용 가능하지만 hook이 등장 ⇒ 하지만 현재 내 코드가 망가지진 않음 </p>
</li>
<li><p>PATCH: 하위호환성 보장 하면서 버그수정 → 그냥 버그 수정</p>
</li>
</ol>
</li>
</ul>
<h3 id="tilde">tilde(~)</h3>
<ul>
<li>PATCH 버전 내에서 버전이 업데이트 되는 방식을 말합니다.<pre><code>  ~1.3.0: &gt;= 1.3.0 &lt; 1.4.0
  ~1.5.2: &gt;= 1.5.2 &lt; 1.6.0
  ~2.2: &gt;= 2.2 &lt; 2.3</code></pre></li>
</ul>
<h3 id="caret">caret(^)</h3>
<ul>
<li>마이너 버전 내에서 버전이 업데이트 되는 방식</li>
<li>최신 마이너 버전으로 설치</li>
</ul>
<pre><code>    ^1.0.2 : &gt;=1.0.2 &lt;2.0
    ^1.0 : &gt;=1.0.0 &lt;2.0
    ^1 : &gt;=1.0.0 &lt;2.0</code></pre><h3 id="packagejson-확인해보기">package.json 확인해보기</h3>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/f7ef2c31-b705-424e-9575-eaea8b39d030/image.png" alt=""></p>
<ul>
<li><p>package.json은 위 사진과 같이 구성돼있습니다. </p>
</li>
<li><p>보라색 글씨(key) 내부에 { 노란색 글씨 + 버전} 형태로 구성돼있습니다. </p>
</li>
<li><p>간단하게 구성을 살펴보겠습니다.</p>
<ul>
<li><p>name : 프로젝트 이름</p>
</li>
<li><p>version : 프로젝트 버전 정보</p>
</li>
<li><p>script : npm으로 실행할 수 있는 명령어 모음</p>
</li>
<li><p>dependencies : 프로젝트에서 필수로 필요한 패키지 목록</p>
</li>
<li><p>devDependencies : 프로젝트에 필수는 아니지만 개발에 도움이 되는 패키지 목록</p>
</li>
<li><p>더 많은 내용은 공식문서 참고해주세요. <a href="https://docs.npmjs.com/cli/v6/configuring-npm/package-json">npm docs</a></p>
</li>
</ul>
</li>
</ul>
<hr>
<h1 id="package-lockjson이란">package-lock.json이란</h1>
<ul>
<li><p>공식문서에 아래와 같이 나타나있습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/b7bf6523-0522-4631-8332-0592159fbcd6/image.png" alt=""></p>
</li>
<li><p>너무 길어서 번역기의 도움을 좀 받아보겠습니다. </p>
</li>
</ul>
<pre><code>    package-lock.json 파일은 npm이 node_modules 트리를 수정하거나 package.json을 변경하는 모든 작업에서 자동으로 생성됩니다. 
  이 파일은 생성된 정확한 의존성 트리를 기록하여, 이후 설치 시 중간 의존성 업데이트와 관계없이 동일한 트리를 재현할 수 있도록 합니다.

    이 파일은 소스 코드 저장소에 커밋하는 것이 권장되며, 다음과 같은 목적을 가집니다:

    팀원, 배포 환경, CI(Continuous Integration)에서 동일한 의존성을 설치하도록 보장합니다.
    node_modules 디렉터리를 직접 커밋하지 않고도 이전 상태로 되돌아갈 수 있도록 합니다.
    읽기 쉬운 소스 컨트롤(diff)을 통해 의존성 트리 변경 사항을 쉽게 확인할 수 있도록 합니다.
    이전에 설치된 패키지에 대한 메타데이터 확인을 건너뛰어 설치 프로세스를 최적화합니다.
    package-lock.json 파일의 중요한 특징 중 하나는 배포(publish)할 수 없다는 점입니다. 즉, 최상위 패키지 이외의 위치에서는 무시됩니다.
    이 파일은 npm-shrinkwrap.json과 동일한 형식을 가지며, npm-shrinkwrap.json은 배포가 가능하다는 차이점이 있습니다.
    그러나 npm-shrinkwrap.json은 CLI 도구 배포 또는 프로덕션 패키지 배포와 같은 특정한 경우에만 사용하는 것이 좋습니다.

    만약 루트 디렉터리에 package-lock.json과 npm-shrinkwrap.json이 둘 다 존재하는 경우, package-lock.json은 완전히 무시됩니다.</code></pre><ul>
<li>위 글을 정리해보겠습니다.</li>
</ul>
<ol>
<li><p>package-lock.json 파일은 아래의 2가지 경우에 <code>자동으로 생성</code>됩니다. </p>
<pre><code>- node_modules 트리를 수정하는 경우
- package.json을 변경하는 경우</code></pre></li>
<li><p>정확한 의존성 트리를 기록하여, 이후 설치 시 중간 의존성 업데이트와 관계없이 동일한 트리를 재현 -&gt; 즉 <code>구체적으로 정확한 버전을 가지고 있다. 예를들어 3.5~ 3.9버전이 아닌, 3.5.2 버전</code></p>
</li>
</ol>
<ul>
<li>정리해보면 <code>package-lock.json은 협업하는 개발자들 간의 의존성 버전 충돌을 방지하기 위해 설치된 패키지의 정확한 버전 및 의존성을 기록하는 파일</code> 입니다.</li>
</ul>
<hr>
<h1 id="packagejson과-package-lockjson의-차이">package.json과 package-lock.json의 차이</h1>
<ul>
<li><p>이론은 이해했고, 실제 파일이 어떻게 구성돼있는지 확인해보겠습니다.</p>
</li>
<li><p>다시 정리하자면 아래와 같습니다.</p>
</li>
<li><p>package.json : <code>다른 사람(협업자)들이 배포한 사람이 올린 코드를 쉽게 관리하고 설치할 수 있도록 사용되는 문서</code></p>
</li>
<li><p>package-lock.json : <code>협업하는 개발자들 간의 의존성 버전 충돌을 방지하기 위해 설치된 패키지의 정확한 버전 및 의존성을 기록하는 파일</code></p>
</li>
<li><p>아래의 사진과 같이 package-lock.json은 구체적인 2.7.16버전으로 기록되지만, 
package.json은 ^2.6.14 와 같이 범위로 기록된 걸 확인 할 수 있습니다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/7b0c616d-06e5-4447-a07a-a092fd7a3fe8/image.png" alt=""></p>
<h3 id="의문">의문</h3>
<ul>
<li>그럼 왜 이렇게 관리를 하는건가??? 특정 버전으로 고정시키던지, 범위만 지정하면 되지 왜 2개로 관리를 하는걸까??</li>
</ul>
<blockquote>
<p>이유는 -&gt;  유연한 의존성 관리와 일관된 환경 보장이라는 두 가지 목적을 동시에 달성하기 위한 구조입니다.</p>
</blockquote>
<ul>
<li>유연한 의존성 관리 의미</li>
</ul>
<pre><code>1. A가 eslint를 최신 버전으로 다운 받습니다. ex) package.json - ^3.2.0, package-lock.json - 3.2.0
2. eslint에서 3.5.0으로 업그레이드 됐습니다.
3. npm i을 진행하게 되면 같은 ^3.2.0으로 관리하지만, 실제로는 3.2.0 -&gt; 3.5.0 버전이 업그레이드 됩니다. ex) package.json - ^3.2.0, package-lock.json - 3.5.0

- 즉 npm i을 하게 되면 최신 버전을 가져올 수 있습니다.</code></pre><ul>
<li>일관된 환경 보장의 의미 -&gt; package-lock.json의 존재 이유</li>
</ul>
<blockquote>
<p>만약 package-lock.json이 존재하지 않는다면 아래의 문제가 발생</p>
</blockquote>
<pre><code>1. A, B모두 eslint ^3.2.0 버전으로 관리 
2. eslint가 업데이트가 돼서 3.4.0 버전으로 업그레이드 됨
3. A가 코딩 중 npm i을 진행하게 됐고, 3.4.0 버전으로 사용
4. eslint가 업데이트가 돼서 3.5.0 버전으로 업그레이드 됨
5. B가 코딩 중 npm i을 진행하게 됐고, 3.5.0 버전으로 사용

A는 3.4.0버전
B는 3.5.0버전으로 서로 다른 버전으로 사용하게 된다 -&gt; 일관적이지 않은 환경 발생
</code></pre><blockquote>
<p>따라서 반드시 package-lock.json이 수정되면 코드저장소에 commit을 해줘야합니다.</p>
</blockquote>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://chatgpt.com">chatGPT</a></li>
<li><a href="https://docs.npmjs.com/cli/v6/configuring-npm/package-json#scripts">npm docs</a></li>
<li><a href="https://dev-ellachoi.tistory.com/65">dev_ella</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue2 - 인스턴스]]></title>
            <link>https://velog.io/@rlaclghks123/Vue2-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4</link>
            <guid>https://velog.io/@rlaclghks123/Vue2-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4</guid>
            <pubDate>Sun, 16 Feb 2025 13:58:01 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#vue-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4">Vue 인스턴스</a>
<a href="#%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EB%9D%BC%EC%9D%B4%ED%94%84%EC%82%AC%EC%9D%B4%ED%81%B4-%ED%9B%85">인스턴스 라이프사이클 훅</a>
<a href="#%EC%B0%B8%EA%B3%A0-%EC%9E%90%EB%A3%8C">참고 자료</a></p>
<h1 id="vue-인스턴스">Vue 인스턴스</h1>
<ul>
<li><p>모든 Vue 앱은 Vue 함수로 새 Vue 인스턴스를 만드는 것부터 시작합니다.</p>
</li>
<li><p>Vue 인스턴스를 생성할 때는 options 객체를 전달해야 합니다. 전체 옵션 목록은 <a href="https://v2.ko.vuejs.org/v2/api/#propsData">API reference</a>에서 확인할 수 있습니다.</p>
</li>
</ul>
<h3 id="mainjs">main.js</h3>
<ul>
<li>Cli로 프로젝트를 만든 경우 main.js를 확인해보겠습니다.<ul>
<li><code>new Vue({})</code> 안에 들어가는 객체를 options 객체라고 합니다.</li>
<li>아래의 사진의 경우 render api를 활용하여 App 컴포넌트를 렌더링 하도록 구현
<img src="https://velog.velcdn.com/images/rlaclghks123/post/a80cf8ac-0122-42da-afcf-8f7efe004101/image.png" alt=""></li>
</ul>
</li>
</ul>
<h3 id="appvue">App.vue</h3>
<ul>
<li>위 사진에서 연결한 App 컴포넌트를 살펴보겠습니다.<ul>
<li>Vue에서는 크게 3가지 태그로 구성합니다.</li>
</ul>
<ol>
<li><code>template</code> 태그로 감싼 부분에 HTML 코드를 작성합니다.</li>
<li><code>script</code> 태그로 들어간 부분에 JS 혹은 vue 코드를 작성합니다.</li>
<li><code>style</code> 태그로 들어간 부분에 style(css) 코드를 작성합니다.</li>
</ol>
</li>
<li>main에서 App 컴포넌트를 호출한 것처럼 HelloWorld 라는 컴포넌트를 호출해서 사용합니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/38f4b66f-becf-4a17-9d63-6c456a450cbe/image.png" alt=""></li>
</ul>
<h3 id="helloworldvue">HelloWorld.vue</h3>
<ul>
<li>App.vue 컴포넌트와 마찬가지로 template, script, style 3가지 태그를 사용하여 나타냅니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/5165ab0a-5408-434e-a3cd-a7d69159fb08/image.png" alt=""></li>
</ul>
<h3 id="vue-인스턴스-구성">Vue 인스턴스 구성</h3>
<ul>
<li><p>Vue 앱은 new Vue를 통해 만들어진 루트 Vue 인스턴스로 구성되며 선택적으로 중첩이 가능하고 재사용 가능한 컴포넌트 트리로 구성됩니다.</p>
</li>
<li><p>만약 ToDoList를 구성하게 된다면 아래의 사진처럼 트리를 구성할 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/e6432e29-8db4-4804-afc9-d095486f6324/image.png" alt=""></p>
</li>
</ul>
<hr>
<h1 id="인스턴스-라이프사이클-훅">인스턴스 라이프사이클 훅</h1>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/d910c618-3054-4243-81e1-b40265ccb04a/image.png" alt=""></p>
<ul>
<li>위 사진은 공식문서에 나타난 인스턴스 라이프사이클에 대한 다이어그램입니다.</li>
<li>위에 나타난 라이프사이클 훅은 아래와 같습니다.<ul>
<li>beforeCreate</li>
<li>created</li>
<li>beforeMount</li>
<li>mounted</li>
<li>updated</li>
<li>beforeDestroy</li>
<li>destroyed</li>
</ul>
</li>
<li>하나씩 알아보도록 하겠습니다.   </li>
</ul>
<h3 id="beforecreate">beforeCreate</h3>
<ul>
<li>컴포넌트가 생성되기 직전 (data, props, computed, methods가 아직 설정되지 않음)</li>
<li><code>주로 사용하지 않음</code> (대부분 created에서 처리 가능)<h3 id="created">created</h3>
</li>
<li>컴포넌트가 생성된 직후 (data, props, computed, methods가 설정됨)</li>
<li>비동기 데이터 가져오기 (API 호출 등), 초기 데이터 설정, 이벤트 리스너 등록</li>
<li><code>주로 사용하는 곳</code><ul>
<li>API 요청 (fetch, axios)</li>
<li>데이터 초기화</li>
<li>이벤트 리스너 등록 (window.addEventListener)</li>
</ul>
</li>
</ul>
<h3 id="beforemount">beforeMount</h3>
<ul>
<li>템플릿이 렌더링되기 직전 (DOM에 연결되기 전)</li>
<li><code>일반적으로 잘 사용되지 않음</code> (mounted에서 처리 가능)<h3 id="mounted">mounted</h3>
</li>
<li>컴포넌트가 DOM에 마운트된 후 (화면에 렌더링 완료됨)</li>
<li>DOM 접근이 필요할 때 (ex. querySelector), 외부 라이브러리 연동</li>
<li><code>주로 사용하는 곳</code><ul>
<li>DOM 조작 (document.querySelector, this.$refs)</li>
<li>외부 라이브러리 초기화 (예: 차트, 슬라이더)</li>
<li>setTimeout, setInterval 같은 타이머 설정<h3 id="updated">updated</h3>
</li>
</ul>
</li>
<li>반응형 데이터가 변경된 후 DOM이 다시 렌더링될 때</li>
<li>데이터 변경 후 추가적인 작업이 필요할 때 사용</li>
<li><code>주로 사용하는 곳</code><ul>
<li>데이터 변경 후 특정 DOM을 조작할 때</li>
<li>변경된 데이터를 기반으로 UI를 업데이트할 때</li>
</ul>
</li>
<li>🚨 <code>주의</code> : updated에서 데이터를 변경하면 무한 루프에 빠질 수 있음 → watch를 활용하는 것이 좋음</li>
</ul>
<h3 id="beforedestroy">beforeDestroy</h3>
<ul>
<li>컴포넌트가 소멸되기 직전</li>
<li>이벤트 리스너 제거, 타이머 정리, 웹소켓 연결 해제 등</li>
<li><code>주로 사용하는 곳</code><ul>
<li>setInterval, setTimeout 해제</li>
<li>window.addEventListener 제거</li>
<li>WebSocket 연결 해제<h3 id="destroyed">destroyed</h3>
</li>
</ul>
</li>
<li>컴포넌트가 소멸된 후</li>
<li>beforeDestroy에서 정리를 못 한 경우 최종 정리</li>
<li>보통 beforeDestroy에서 처리 가능하므로 잘 사용하지 않음</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/550983a9-d496-445e-a03c-f343aeafd303/image.png" alt=""></p>
<h3 id="결론">결론</h3>
<ul>
<li>크게 4가지를 주로 사용할 수 있다.<ul>
<li>데이터 초기화 &amp; API 요청 → created</li>
<li>DOM 접근 &amp; 외부 라이브러리 연동 → mounted</li>
<li>데이터 변경 후 UI 업데이트 → updated</li>
<li>이벤트 리스너 정리 &amp; 타이머 해제 → beforeDestroy</li>
</ul>
</li>
</ul>
<h3 id="vue-라이프-사이클-직접-사용해보기">vue 라이프 사이클 직접 사용해보기</h3>
<ul>
<li><p>크게 created, mounted, beforeDestroy 3가지만 사용해보겠습니다. </p>
</li>
<li><p>아래와 같이 script 태그 내부에서 사용할 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/bd945c6a-c60c-4310-8edf-0f2287dab58a/image.png" alt=""></p>
</li>
<li><p>그렇다면 출력은 어떻게 될까요?</p>
<ul>
<li>create -&gt; mounted -&gt; beforeDestroy 순서로 출력이 예상됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/0248560d-8945-456b-a853-1f6dfe24899b/image.png" alt=""></li>
</ul>
</li>
<li><p>beforeDestroy는 화면에 나타나지 않습니다. 컴포넌트가 소멸되기 직전에 실행되기 때문일까요?</p>
</li>
<li><p>그러면 한번 더 확인해보겠습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/3729eb42-37df-4403-b53d-b46a921820b5/image.png" alt=""></p>
</li>
<li><p>created -&gt; mounted -&gt; <code>beforeDestroy -&gt; created</code> -&gt; mounted의 순서가 아닌 created -&gt; mounted -&gt; <code>created -&gt; beforeDestroy</code> -&gt; mounted 순서로 나타납니다. </p>
</li>
<li><p>GPT에게 물어본 결과 <code>비동기 렌더링</code> 또는 <code>최적화된 DOM 패치 방식</code> 때문이라고 합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/fdca929b-822f-4ff6-803a-7ace89634f2f/image.png" alt=""></p>
</li>
</ul>
<hr>
<h1 id="참고-자료">참고 자료</h1>
<ul>
<li><a href="https://velog.io/@rlaclghks123/Vue-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0">vue 공식문서</a></li>
<li><a href="https://chatgpt.com/">chat GPT</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue - 시작하기]]></title>
            <link>https://velog.io/@rlaclghks123/Vue-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@rlaclghks123/Vue-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 12 Feb 2025 12:27:12 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<p><a href="#vue-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0">Vue 시작하기</a>
<a href="#cli%EC%99%80-npm-%EC%B0%A8%EC%9D%B4">CLI와 Npm 차이</a>
<a href="#cli%EC%9D%98-packagejson-%EA%B5%AC%EC%84%B1">CLI의 package.json 구성</a></p>
<h1 id="vue-시작하기">Vue 시작하기</h1>
<h3 id="vue란">Vue란</h3>
<ul>
<li>공식문서에 따르면 아래와 같습니다.<blockquote>
<p>Vue(/vjuː/ 로 발음, view 와 발음이 같습니다.)는 사용자 인터페이스를 만들기 위한 프로그레시브 프레임워크 입니다. 다른 단일형 프레임워크와 달리 Vue는 점진적으로 채택할 수 있도록 설계하였습니다. 핵심 라이브러리는 뷰 레이어만 초점을 맞추어 다른 라이브러리나 기존 프로젝트와의 통합이 매우 쉽습니다.</p>
</blockquote>
</li>
</ul>
<h2 id="vue-사용하는-방법-3가지">vue 사용하는 방법 3가지</h2>
<ul>
<li>시작하기 전에 vscode, npm, nodeJs는 다운로드 받아주세요.<ul>
<li><a href="https://code.visualstudio.com">vscode</a></li>
<li><a href="https://nodejs.org/ko/">NodeJs</a></li>
</ul>
</li>
<li>vue를 사용하는 방법은 크게 3가지가 존재합니다.</li>
</ul>
<ol>
<li>CDN에서 Vue 사용</li>
<li>NPM 사용</li>
<li>Vue CLI</li>
</ol>
<h3 id="1-cdn에서-vue-사용">1. CDN에서 Vue 사용</h3>
<ul>
<li><p>CDN이란 Content Delivery Network의 약자로서 지리적인 제약 없이 전 세계 사용자에게 빠르고 안전하게 컨텐츠 전송을 할 수 있는 기술</p>
</li>
<li><p>script 태그를 통해 Vue를 사용할 수 있습니다. </p>
</li>
<li><p><code>CDN 사용시 장점</code>은 CDN에서 Vue를 사용할 때는 &quot;빌드 단계&quot;가 없습니다. 이렇게 하면 설정이 훨씬 간단해지고 정적 HTML을 향상시키거나 백엔드 프레임워크와 통합하는 데 적합합니다.</p>
</li>
<li><p><code>CDN 사용시 단점</code>은 SFC(Single-File Component) 구문을 사용할 수 없습니다. 즉 코드를 파일별로 분리할 수 없습니다. </p>
</li>
<li><p>따라서 단순히 테스트 용도가 아닌 프로젝트를 구성하기 위해서는 CDN 보다는 다른 방법을 사용하는게 더 효율적으로 코드를 관리할 수 있습니다.</p>
</li>
</ul>
<h4 id="cdn-사용방법">CDN 사용방법</h4>
<ol>
<li>HTML 파일을 만들어 줍니다.</li>
<li>CDN script 코드를 추가해줍니다.</li>
<li>vue를 사용합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/a3c40654-d764-45a4-a545-26345edc4bd4/image.png" alt=""></li>
</ol>
<hr>
<h2 id="2-npm-사용">2. NPM 사용</h2>
<ul>
<li>npm으로 vue를 다운받을 경우 CDN과 달리 단일 파일 구성 요소(SFC)를 사용할 수 있습니다.</li>
</ul>
<h3 id="npm-사용-방법">NPM 사용 방법</h3>
<ol>
<li>npm으로 vue를 최신 버전을 다운받는다.</li>
<li>여러가지 질문에 답을 하여 프로젝트를 만든다.</li>
<li>프로젝트로 경로를 이동 후 실행한다.</li>
</ol>
<ul>
<li>명령어 순서 </li>
</ul>
<ol>
<li>npm create vue@latest</li>
<li>cd <code>your-project-name</code></li>
<li>npm install</li>
<li>npm run dev
<img src="https://velog.velcdn.com/images/rlaclghks123/post/5d5f4c63-c29a-4548-8586-bd31da36c07d/image.png" alt=""></li>
</ol>
<h2 id="3-vue-cli">3. Vue CLI</h2>
<ul>
<li><p>아마 대부분의 프로젝트는 CLI를 통해 프로젝트를 만들고 실행 할 것입니다.</p>
</li>
<li><p>왜냐하면 CLI를 통해 프로젝트를 생성하면 webpack 기반의 빌드 도구, 종속성, 플러그인, 프로젝트 파일 구조 등 초기 설정에 필요한 많은 부분을 미리 제공해주기 때문입니다. </p>
</li>
<li><p>만약 webpack이 아닌 Vite를 사용하는 등 따로 설정하는게 귀찮다. CLI로 설정된 부분으로 사용해도 큰 문제가 없다 라고 한다면 CLI를 사용해봐도 좋을 것 같습니다.</p>
</li>
</ul>
<h4 id="프로젝트-생성">프로젝트 생성</h4>
<ol>
<li>cli를 다운받는다.</li>
<li>project를 생성한다.</li>
</ol>
<ul>
<li>명령어 순서 </li>
</ul>
<ol>
<li>npm install -g @vue/cli </li>
<li>vue create [프로젝트명] </li>
<li>생성한 프로젝트로 이동 후 실행</li>
</ol>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/5e8d68d8-81f4-48a0-9072-bc4e02ced8b0/image.png" alt=""></p>
<hr>
<h1 id="cli와-npm-차이">CLI와 NPM 차이</h1>
<ul>
<li>설치 하고 보니 NPM으로 다운 받는 것과 CLI의 큰 차이가 없는 것 같다는 생각이 듭니다.</li>
<li>아래의 vue-project는 npm방법이고, vue-projectt는 CLI입니다. </li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/d8c5edaf-a579-49be-a7d7-06c6f182db6f/image.png" alt=""></p>
<blockquote>
<p>....? 뭐야 비슷한데? 라고 생각하여 좀 더 찾아봤습니다.</p>
</blockquote>
<h3 id="packagejson">package.json</h3>
<ul>
<li>coreJs 및 eslint, template-compiler 등 몇 가지가 더 설치돼있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/be2380c1-a66b-4ec7-b879-681c8ba1e548/image.png" alt=""></li>
</ul>
<blockquote>
<p>뭐야 webpack이 설치가 안돼있는데? </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/18346c10-9aca-4574-89e4-4818fbb807f5/image.png" alt=""></p>
<ul>
<li><p>공식 문서에는 분명 webpack이 설치돼있다는데 왜 없지?? -&gt; 그래서 node_modules 폴더를 찾아봤습니다. </p>
<blockquote>
<p> node_modules 폴더란 프로젝트에서 사용하는 외부 라이브러리 및 패키지, 그리고 해당 패키지의 모든 종속성을 저장하는 디렉터리입니다. - 출처 : Chat GPT</p>
</blockquote>
</li>
<li><p>아래와 같이 node_modules안에 존재하고 있습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/a078950b-cc06-42ae-8760-1db5df60d8ad/image.png" alt=""></p>
</li>
<li><p>webpack 뿐 아니라 CLI로 설치할 경우 babel plugin, eslint, postCSS 등 훨씬 많은 폴더들이 존재합니다. </p>
</li>
</ul>
<hr>
<h1 id="cli의-packagejson-구성">CLI의 packagejson 구성</h1>
<ul>
<li><p>NPM 혹은 CLI로 폴더를 다운받으면 아래의 사진과 같이 Vue를 사용할 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/d052a5b4-43b2-439d-b04f-aca58096e24b/image.png" alt=""></p>
</li>
<li><p>Vue를 시작하기에 앞서 package.json에 뭐가 설치돼있는지 확인해보겠습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/08e5cb4c-3c18-498b-8602-d6046e8abeee/image.png" alt=""></p>
</li>
<li><p><code>core-js</code> : Core-js는 여러 버전에 걸쳐 브라우저 호환성을 제공하는 JavaScript 라이브러리 입니다. </p>
</li>
<li><p><code>babel</code> : Babel은 ECMAScript 2015+ 코드를 이전 JavaScript 엔진에서 실행할 수 있는 이전 버전과 호환되는 JavaScript 코드로 변환하는 데 주로 사용되는 무료 오픈 소스 JavaScript 트랜스컴파일러입니다. </p>
</li>
<li><p><code>eslint</code> : 코드 품질을 개선하고 런타임에 버그가 발생하지 않도록 사전에 버그를 수정하는 데 도움이 되는 linter입니다.</p>
</li>
<li><p><code>vue-template-compiler</code> : Vue.js의 템플릿을 JavaScript 렌더링 함수로 변환하는 컴파일러입니다.</p>
</li>
</ul>
<ul>
<li><p><code>eslintConfig</code> :  eslint 설정을 하는 코드입니다. package.json 내부 보다는 .eslintrc.js 또는 .eslintrc.json 파일로 분리해서 작성 하는 게 더 적절할 것 같습니다. </p>
</li>
<li><p><code>browserslist</code> : 프로젝트에서 지원할 브라우저의 범위를 정의하는 설정입니다. Babel, Autoprefixer, PostCSS, ESLint, Webpack, Vue CLI, React 등의 도구에서 사용되어 브라우저 호환성을 자동으로 관리하는 데 도움을 줍니다. 이 코드도 따로 .browserslistrc 파일로 분리하면 좋을 것 같습니다. </p>
<ul>
<li><p><code>&quot;&gt; 1%&quot;</code> :  세계에서 사용 비율이 1% 이상인 브라우저를 지원합니다.</p>
</li>
<li><p><code>&quot;last 2 versions&quot;</code> : 각 브라우저의 최신 2개 버전을 지원합니다. 예를들어 크롬 최신 버전이 120이면 120, 119가 지원됨</p>
</li>
<li><p><code>&quot;not dead&quot;</code> : 공식적으로 지원이 중단된(Dead) 브라우저는 제외합니다.
여기서 Dead의 기준은 아래의 2가지입니다.</p>
<ol>
<li>2년 이상 업데이트가 없는 브라우저</li>
<li>사용 비율이 0.5% 미만인 IE 10, BlackBerry, Baidu 등은 제외됨</li>
</ol>
</li>
</ul>
</li>
</ul>
<hr>
<h1 id="참고-자료">참고 자료</h1>
<ul>
<li><a href="https://v2.ko.vuejs.org/v2/guide/index.html">vue 공식문서</a></li>
<li><a href="https://chatgpt.com/g/g-FvT4UOsoA-caesgpt">Chat GPT</a></li>
<li><a href="https://github.com/zloirock/core-js">corejs</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[git - stash]]></title>
            <link>https://velog.io/@rlaclghks123/git-stash</link>
            <guid>https://velog.io/@rlaclghks123/git-stash</guid>
            <pubDate>Sun, 09 Feb 2025 08:30:16 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#git-stash%EB%9E%80">git stash란</a></li>
<li><a href="#%EC%82%AC%EC%9A%A9-%EC%9D%B4%EC%9C%A0"><img src="https://velog.velcdn.com/images/rlaclghks123/post/b8a14188-c52c-43b3-aa39-e27e5ed4028c/image.jpg" alt="">
사용 이유</a></li>
<li><a href="#git-stash-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AA%A8%EC%9D%8C">git stash 명령어 모음</a></li>
<li><a href="#git-stash-%EC%A3%BC%EC%9D%98-%EC%82%AC%ED%95%AD">git stash 주의 사항</a></li>
<li><a href="#%EC%B0%B8%EA%B3%A0">참고</a></li>
</ul>
<h1 id="git-stash란">git stash란</h1>
<ul>
<li><p>git stash는 <code>작업 복사본에 적용한 변경 사항을 일시적으로 저장(또는 스태시)하여 다른 작업을 하다가 다시 돌아와서 나중에 변경 사항을 다시 적용할 수 있도록 합니다</code>. 스태시는 컨텍스트를 빠르게 전환하고 다른 작업을 수행해야 하지만, 코드 변경을 진행하고 있고 커밋할 준비는 되지 않은 경우 편리합니다.<a href="https://www.atlassian.com/ko/git/tutorials/saving-changes/git-stash">출처 ATLASSIAN</a></p>
</li>
<li><p><code>쉽게 말하면 현재 작업중인 코드를 일시적으로 저장하는 방법 중 하나.</code></p>
</li>
</ul>
<hr>
<h1 id="사용-이유">사용 이유</h1>
<ul>
<li>stash의 사용 이유는 <code>컨텍스트를 빠르게 전환하고 다른 작업을 수행해야 하지만, 코드 변경을 진행하고 있고 커밋할 준비는 되지 않은 경우 편리합니다.</code> 입니다.</li>
<li>말이 너무 어려운 것 같은데, 크게 2가지 상황에 자주 사용합니다.</li>
</ul>
<ol>
<li>현재 작업중인 경우 다른 사람의 branch로 checkout 할 경우</li>
<li>현재 작업중인 경우 이전 log로 checkout 할 경우</li>
</ol>
<h3 id="stash-사용-예시">stash 사용 예시</h3>
<ol>
<li>현재 코드를 작성중입니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/4a5b10bf-75d6-4451-9974-fb721018db3e/image.png" alt=""></li>
</ol>
<ol start="2">
<li><p>현재 코드 작성 중 다른 사람의 PR 혹은 여러가지 이유로 다른 브랜치로 이동하려고 하면 아래와 같은 문구가 나타납니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/a5b7956d-f6b5-4331-9d66-d1c72d97bbc3/image.png" alt=""></p>
</li>
<li><p>commit을 하기에는 현재 작성중인 코드가 완성되지 않았기에 임시 저장 용도로 stash를 사용합니다. </p>
</li>
</ol>
<ul>
<li>stash 저장 명령어 : <code>git stash save &#39;stash message&#39;</code></li>
<li>stash 저장 list 확인 명령어 : <code>git stash list</code> </li>
</ul>
<ol start="4">
<li><p>저장 후 다른 branch로 이동 가능합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/920c2a35-ca3d-463b-a0da-c4a94ec74f01/image.jpg" alt=""></p>
</li>
<li><p>다시 stash 저장된 코드 불러오는 방법 </p>
</li>
</ol>
<ul>
<li>stash 코드 불러오는 명령어 : <code>git stash apply</code>
<img src="https://velog.velcdn.com/images/rlaclghks123/post/c8553974-013c-4a57-9fa6-0cedb9abb641/image.png" alt=""></li>
</ul>
<hr>
<h1 id="git-stash-명령어-모음">git stash 명령어 모음</h1>
<ul>
<li>stash에 저장되는 코드는 <code>stack 자료구조로 가장 마지막에 저장된 코드가 가장 최신으로 저장됩니다.</code> </li>
<li>아래와 같이 1, 2, 3 순서로 저장했지만, stack 자료구조로 세번째 저장된 stash 코드가 가장 최신으로 들어갑니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/d6785d82-1320-40f1-b462-a74e540a7097/image.png" alt=""></li>
</ul>
<ul>
<li>명령어 모음 <ul>
<li>git stash list : stash된 list 목록 확인</li>
<li>git stash show : stash 된 코드 미리보기</li>
<li>git stash pop : 가장 최근 stash 불러오기 &amp;&amp; stash에서 제거</li>
<li>git stash apply : 가장 최근 stash 불러오기 &amp;&amp; stash에 저장</li>
<li>git stash save : stash에 코드 저장</li>
<li>git stash clear : stash에 저장된 코드들 모두 제거</li>
</ul>
</li>
</ul>
<h3 id="git-stash-list">git stash list</h3>
<ul>
<li><code>git stash list</code> : stash된 list 목록 확인</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/d6785d82-1320-40f1-b462-a74e540a7097/image.png" alt=""></p>
<h3 id="git-stash-show">git stash show</h3>
<ul>
<li>가장 최신 코드만 볼 수 있습니다.</li>
<li><code>git stash show</code> : stash 된 코드 미리보기
<img src="https://velog.velcdn.com/images/rlaclghks123/post/362e7e60-09db-42df-82d7-16925e7c07fd/image.png" alt=""></li>
<li><code>git stash show -p</code> : 좀 더 구체적으로 보려면 -p 옵션을 추가해줍니다.<br><img src="https://velog.velcdn.com/images/rlaclghks123/post/1d6e5c59-7214-47c8-9ddf-46600a8fb106/image.jpg" alt=""></li>
</ul>
<h3 id="git-stash-pop">git stash pop</h3>
<ul>
<li><code>git stash pop</code> : 가장 최근 stash 불러오기 &amp;&amp; stash에서 제거
<img src="https://velog.velcdn.com/images/rlaclghks123/post/7ae85bac-12ff-4108-bd02-be27ea80d9be/image.png" alt=""></li>
</ul>
<h3 id="git-stash-apply">git stash apply</h3>
<ul>
<li><code>git stash apply</code> : 가장 최근 stash 불러오기 &amp;&amp; stash에 저장
<img src="https://velog.velcdn.com/images/rlaclghks123/post/edc9bfe1-511f-4a5f-8107-4689660cd9f7/image.png" alt=""></li>
</ul>
<h3 id="git-stash-save">git stash save</h3>
<ul>
<li><code>git stash save</code> : stash에 코드 저장
<img src="https://velog.velcdn.com/images/rlaclghks123/post/1c0c0a81-862d-48bf-b30c-c5bbf223988f/image.png" alt=""></li>
</ul>
<h3 id="git-stash-clear">git stash clear</h3>
<ul>
<li><code>git stash clear</code> : stash에 저장된 코드들 모두 제거
<img src="https://velog.velcdn.com/images/rlaclghks123/post/ebc61c51-5aab-4b5d-9e76-2730b93046cd/image.png" alt=""></li>
</ul>
<hr>
<h1 id="git-stash-주의-사항">git stash 주의 사항</h1>
<ul>
<li><p>stash를 사용할 때만 해당되는 내용은 아니지만, 실제로 stash 한 뒤 코드를 불러왔는데, 작업중인 코드가 사라진 경우가 있었습니다. 😭😭😭😭😭😭😭😭</p>
</li>
<li><p><code>그 문제는 바로 저장하지 않은 뒤 stash를 한 경우 입니다.</code></p>
</li>
</ul>
<h3 id="저장하지-않은-코드-stash-해버리기코드-날려먹기">저장하지 않은 코드 stash 해버리기(코드 날려먹기)</h3>
<ol>
<li><p>코드를 작성합니다. </p>
</li>
<li><p><code>git add .</code> 명령어를 통해 stage area로 이동합니다.</p>
</li>
<li><p><code>git stash save &#39;중요한 코드 저장&#39;</code> 명령어를 통해 stash에 저장합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/1918ab98-70d2-429b-ae31-b45dfde44da2/image.png" alt=""></p>
</li>
<li><p><code>git stash apply</code> 명령어를 통해 stash에 저장한 코드를 불러옵니다.</p>
</li>
<li><p><code>아래와 같이 파일은 있는데 코드가 사라지는 아주 큰 문제가 발생할 수 있으니 stash 하기 전 반드시 저장했는지 여러번 확인 해야합니다.🚨</code>
<img src="https://velog.velcdn.com/images/rlaclghks123/post/da71cd11-1fc3-46a5-83ae-c1de71e548dd/image.png" alt=""></p>
</li>
</ol>
<h1 id="참고">참고</h1>
<ul>
<li><a href="#https://www.atlassian.com/ko/git/tutorials/saving-changes/git-stash">atlassian git tutorials</a></li>
<li><a href="#https://git-scm.com/docs/git-stash">git 공식문서</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - JSX에서 자바스크립트 사용]]></title>
            <link>https://velog.io/@rlaclghks123/React-JSX%EC%97%90%EC%84%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@rlaclghks123/React-JSX%EC%97%90%EC%84%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Sun, 10 Nov 2024 03:14:48 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#jsx%EB%9E%80">JSX란</a></li>
<li><a href="#%EB%B0%94%EB%B2%A8%EC%9D%B4%EB%9E%80">바벨이란</a></li>
<li><a href="#jsx%EC%97%90%EC%84%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%82%AC%EC%9A%A9">JSX에서 자바스크립트 사용</a></li>
<li><a href="#jsx-%EB%B3%80%ED%99%98-%EC%9B%90%EB%A6%AC">JSX 변환 원리</a></li>
</ul>
<h1 id="jsx란">JSX란</h1>
<ul>
<li>JSX에 대해 자세히 알 고 싶다면 여기서 확인할 수 있습니다 -&gt; <a href="https://velog.io/@rlaclghks123/React-JSX">JSX</a></li>
<li>JSX란 간단히 정리하자면 <code>JSX는 XML과 유사한 내장형 구문이며, 자바스크립트의 확장 문법이지만 자바스크립트 표준 문법 x</code></li>
<li>자바스크립트 표준 문법이 아니기 때문에 Babel과 같은 트랜스파일러로 변환을 해줘야 동작합니다.</li>
</ul>
<h1 id="바벨이란">바벨이란</h1>
<ul>
<li><a href="https://babeljs.io">바벨 공식문서</a></li>
</ul>
<blockquote>
<p>Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments. Here are the main things Babel can do for you:</p>
</blockquote>
<blockquote>
<p>Babel은 주로 ECMAScript 2015+ 코드를 현재 및 구형 브라우저 또는 환경에서 호환 가능한 JavaScript 버전으로 변환하기 위해 사용되는 도구 체인입니다. Babel이 할 수 있는 주요 작업은 다음과 같습니다:</p>
</blockquote>
<ul>
<li><p><code>간단히 요약하면 최신 JS코드를 구형 JS코드로 변환해주는 컴파일러입니다.</code></p>
</li>
<li><p>또한 Babel은 JSX 구문을 변환할 수 있습니다</p>
</li>
<li><p><a href="https://babeljs.io/repl">Babel 변환 코드 사이트</a></p>
</li>
<li><p>아래와 같이 변환됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/3960847b-b3bb-417e-a923-c9e5ac242731/image.jpg" alt=""></p>
</li>
</ul>
<hr>
<h1 id="jsx에서-자바스크립트-사용">jsx에서 자바스크립트 사용</h1>
<ul>
<li><p>우선 JSX에서는 중괄호({})를 작성하고 안에 자바스크립트 문법을 사용할 수 있습니다. </p>
</li>
<li><p>하지만 자바스크립트 문법중에서도 표현식만 사용할 수 있습니다.</p>
</li>
<li><p>표현식이란 값으로 평가될 수 있는 문입니다. </p>
</li>
<li><p>표현식 예시</p>
</li>
</ul>
<pre><code class="language-javascript">      // 숫자, 문자열 등 값 자체 표현식
      5;           // 숫자 리터럴 (값: 5)
      &quot;Hello&quot;;     // 문자열 리터럴 (값: &quot;Hello&quot;)

      // 연산을 통해 값을 생성하는 표현식
      5 + 3;       // 산술 연산 표현식 (값: 8)
      a * 2;       // 변수와 연산자를 통한 표현식 (값: a의 값에 따라 달라짐)
      true &amp;&amp; false; // 논리 연산 표현식 (값: false)

      // 함수 호출 표현식
      Math.max(1, 2); // 함수 호출 표현식 (값: 2)

      // 객체나 배열도 표현식으로 간주됩니다
      [1, 2, 3];      // 배열 리터럴 (값: 배열)
      { x: 1, y: 2 }; // 객체 리터럴 (값: 객체)</code></pre>
<ul>
<li>아래와 같이 표현식의 경우 변환 됩니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/398e981d-4b8b-4c8a-abfd-33c742697dab/image.jpg" alt=""></li>
</ul>
<ul>
<li>표현식이 아닌 경우 예시 </li>
</ul>
<pre><code class="language-javascript">      // 변수 선언은 표현식이 아닙니다
      let x = 10;        // 변수 선언문 (값이 아닌 선언)

      // 조건문과 반복문도 표현식이 아닙니다
      if (x &gt; 5) {       // 조건문 (값을 생성하지 않음)
        console.log(x);
      }

      for (let i = 0; i &lt; 5; i++) {  // 반복문 (값을 생성하지 않음)
        console.log(i);
      }

      // 함수 선언도 표현식이 아닙니다 (함수 선언문)
      function greet() { // 함수 선언문 (값을 생성하지 않음)
        return &quot;Hello!&quot;;
      }</code></pre>
<ul>
<li>아래와 같이 표현식이 아닌경우 에러가 발생합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/5004b63b-a9fa-4e05-b353-bc225e09c2ac/image.jpg" alt=""></li>
</ul>
<hr>
<h1 id="jsx-변환-원리">JSX 변환 원리</h1>
<ul>
<li>표현식을 사용해야 하는 이유는 위 사진에 나와 있습니다.</li>
<li>변환된 코드에서 <code>children의 key에 대한 value 위치에 중괄호{}로 감싼 코드가 JavaScript 객체의 value로 들어가기 때문</code>에, JavaScript 객체에서는 값이 아닌 다른 것은 value로 사용할 수 없습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/48c7d376-0cf4-4bb4-8669-2c3145b7debc/image.jpg" alt=""></li>
</ul>
<hr>
<ul>
<li>예전에는 그냥 JSX문법이니까 중괄호로 감싸서 사용했었는데, 이런 원리를 알게 되니 기본기가 중요하다는 생각이 들었고, 오늘도 조금은 기본기가 튼튼해진 것 같습니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 제어 컴포넌트와 비제어 컴포넌트]]></title>
            <link>https://velog.io/@rlaclghks123/React-%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%99%80-%EB%B9%84%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-oxg3efa9</link>
            <guid>https://velog.io/@rlaclghks123/React-%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%99%80-%EB%B9%84%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-oxg3efa9</guid>
            <pubDate>Mon, 30 Sep 2024 03:18:28 GMT</pubDate>
            <description><![CDATA[<h1 id="목차">목차</h1>
<ul>
<li><a href="#%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%9E%80">제어 컴포넌트란</a></li>
<li><a href="#%EB%B9%84%EC%A0%9C%EC%96%B4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%9E%80">비제어 컴포넌트란</a></li>
<li><a href="#%EC%B0%B8%EA%B3%A0">참고</a></li>
</ul>
<h1 id="제어-컴포넌트란">제어 컴포넌트란</h1>
<ul>
<li>제어 컴포넌트란 우선 리액트 공식페이지를 살펴보겠습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/c7970440-0ca5-48a6-90a4-614e2200e169/image.jpg" alt=""></li>
</ul>
<h3 id="form-tag-elements">Form Tag Elements</h3>
<ul>
<li><p>form tag Elements(input, textarea)는 일반적으로 <code>사용자의 입력을 기반으로 자신의 state를 관리하고 업데이트합니다.</code> =&gt; form tag Elements는 value attribute를 통해 자체적으로 data를 갖습니다. </p>
</li>
<li><p>여러 form tag Elements 중 input을 예로들어 보겠습니다.</p>
</li>
<li><p>아래의 사진과 같이 t, te, tes, test를 입력하면 <code>각 입력값에 따른 상태값을 관리하고 업데이트</code> 합니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/c7421858-955e-47ae-b411-4b8af3b4ad69/image.jpg" alt=""></p>
</li>
<li><p>사용자가 입력한 값을 value attribute에 저장 
=&gt; value attribute는 Dom에 존재 
=&gt; 즉 Input을 통해 사용자의 입력값(state)는 Dom에 저장됩니다. </p>
</li>
</ul>
<h3 id="신뢰-가능한-단일-출처">신뢰 가능한 단일 출처</h3>
<ul>
<li><p>리액트 공식 문서에 나와있는 <code>React state를 “신뢰 가능한 단일 출처 (single source of truth)“로 만들어 두 요소를 결합</code> 이라는 말이 참 어렵습니다.</p>
</li>
<li><p>신뢰 가능한 단일 출처란 <code>하나의 상태는 한 곳에서만 존재해야 한다.</code> 라는 의미입니다. </p>
</li>
<li><p>즉 어떤 state가 여러 컴포넌트에서 사용 될 경우에도 한곳에서만 존재해야 합니다.
=&gt; 한곳에서 관리하고 props로 전달 or 전역상태로 관리(redux, recoil...)</p>
</li>
<li><p>그래도 어렵다구요? 코드로 예시를 보겠습니다. 아래의 코드는 리액트에서 useState로 input값을 관리하는 일반적인 방법입니다. </p>
</li>
</ul>
<ul>
<li>신뢰 가능한 단일 출처에 대해 알아보겠습니다.  <ul>
<li>아래의 코드는 inputValue라는 <code>useState와 e.target.value를 동기화(?)</code> 시켜줌으로서 한곳에서만 관리하도록 합니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/16b253a5-0df3-4f2e-af05-e9e104f018e2/image.jpg" alt=""></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li>하지만 아래의 경우 input의 value attribute와 inputValue라는 변수, 두 곳에서 관리가 되기 때문에 신뢰 불가능한 2개의 출처 라고 할 수 있습니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/4c33a597-1216-4c0b-b0e2-405effe7cd8a/image.jpg" alt=""></li>
</ul>
<hr>
<h3 id="react가-관리하는-제어-컴포넌트">React가 관리하는 제어 컴포넌트</h3>
<ul>
<li><p>따라서 다시 React 공식문서를 보면 <code>React에서는 변경할 수 있는 state가 일반적으로 컴포넌트의 state 속성에 유지되며 setState()에 의해 업데이트됩니다</code></p>
</li>
<li><p>input의 value attribute값과 setState()를 통해 <code>값을 통일시켜 항상 최신의 값으로 일치가 보장</code>됩니다. </p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/rlaclghks123/post/16b253a5-0df3-4f2e-af05-e9e104f018e2/image.jpg" alt=""></p>
<h3 id="제어-컴포넌트의-장단점">제어 컴포넌트의 장단점</h3>
<ul>
<li>매번 최신화 된 상태값을 관리할 수 있다는 장점이 있지만 상태값이 변경됨에 따라 re-rendering이 발생하므로 비용이 많이드는 단점이 있습니다.</li>
</ul>
<hr>
<h1 id="비제어-컴포넌트란">비제어 컴포넌트란</h1>
<ul>
<li><p>비제어 컴포넌트 또한 리액트 공식페이지를 살펴보겠습니다. 
<img src="https://velog.velcdn.com/images/rlaclghks123/post/b4c9c334-c16e-46a4-b0e4-b27ed4c7394e/image.jpg" alt=""></p>
</li>
<li><p>공식 페이지에서 말했듯이 ref를 사용해서 관리하는게 일반적인 형태입니다.
<img src="https://velog.velcdn.com/images/rlaclghks123/post/0b4b20b1-025e-41bc-aacf-5946ce2938a9/image.jpg" alt=""></p>
</li>
<li><p>ref를 통해 Dom 자체에서 폼 데이터가 다루어집니다. </p>
</li>
<li><p>ref의 경우 순수 javascript 객체이고, React의 마운트 시점에 ref의 current에 element를 담고, current 값이 바뀌어도 리렌더링을 하지 않는 특성이 있습니다. </p>
</li>
<li><p>즉 React가 Form의 입력값을 제어하지 않고, 값이 항상 일치함을 보장하지 않습니다.</p>
</li>
</ul>
<h1 id="제어-컴포넌트와-비제어-컴포넌트-비교">제어 컴포넌트와 비제어 컴포넌트 비교</h1>
<ul>
<li>아래의 표를 참고하여 상황에 맞게 적절하게 사용하면 될 것 같습니다.</li>
<li>한 가지를 예로들면 input에 값을 입력 하는 것과 동시에 유효성을 나타내고 싶으면 제어컴포넌트, 제출된 후 유효성을 나타내고 싶다면 비제어 컴포넌트를 사용하면 될 것 같습니다. </li>
<li>참고로 React-Hook-Form을 사용하면 제출 전엔 비제어컴포넌트 처럼 유효성 검사를 하지 않다가 제출 이후로 제어컴포넌트 처럼 입력값에 따라 실시간으로 바뀝니다.</li>
</ul>
<table>
<thead>
<tr>
<th>기능</th>
<th>비제어 컴포넌트</th>
<th>제어 컴포넌트</th>
</tr>
</thead>
<tbody><tr>
<td>submit과 같은 일회성 정보 검색 (예: )</td>
<td>✅</td>
<td>✅</td>
</tr>
<tr>
<td>submit(제출)시 유효성 검사</td>
<td>✅</td>
<td>✅</td>
</tr>
<tr>
<td>즉각적인 필드 유효성 검사</td>
<td>❌</td>
<td>✅</td>
</tr>
<tr>
<td>submit(제출) 버튼 조건부 비활성화</td>
<td>❌</td>
<td>✅</td>
</tr>
<tr>
<td>특정 입력 형식 강제</td>
<td>❌</td>
<td>✅</td>
</tr>
<tr>
<td>하나의 데이터에 대한 여러 입력</td>
<td>❌</td>
<td>✅</td>
</tr>
<tr>
<td>동적 입력</td>
<td>❌</td>
<td>✅</td>
</tr>
</tbody></table>
<hr>
<h1 id="정리">정리</h1>
<ul>
<li><p>제어 컴포넌트 </p>
<ul>
<li>리액트가 값을 관리합니다. =&gt; React에 의해 제어됩니다.</li>
<li>사용자의 입력이 항상 state로 push됩니다.</li>
<li>리액트가 값이 항상 일치함을 보장합니다.</li>
<li>Re-rendering이 발생합니다.</li>
</ul>
</li>
<li><p>비제어 컴포넌트  </p>
<ul>
<li>DOM이 값을 저장합니다. =&gt; React가 제어하지 않습니다.</li>
<li>입력 값이 필요할 때, element에서 pull</li>
<li>값이 항상 일치함을 보장하지 않음</li>
<li>Re-rendering이 발생하지 않음</li>
</ul>
</li>
</ul>
<hr>
<h1 id="참고">참고</h1>
<ul>
<li><a href="https://www.youtube.com/watch?v=LD1LyvCCbCg">후이의 테코톡</a></li>
<li><a href="https://www.youtube.com/watch?v=PBgQKK6nelo">세인의 테코톡</a></li>
<li><a href="https://goshacmd.com/controlled-vs-uncontrolled-inputs-react/">goshacmd</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>