<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dev_sheep.log</title>
        <link>https://velog.io/</link>
        <description>기록과 공유</description>
        <lastBuildDate>Sun, 13 Jul 2025 12:36:47 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dev_sheep.log</title>
            <url>https://images.velog.io/images/dev_sheep/profile/6fb03cb6-6ff7-48b9-a9bf-bfa73976adb2/s18_img05.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dev_sheep.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_sheep" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[SQL] PostgreSQL substring]]></title>
            <link>https://velog.io/@dev_sheep/SQL-PostgreSQL-substring</link>
            <guid>https://velog.io/@dev_sheep/SQL-PostgreSQL-substring</guid>
            <pubDate>Sun, 13 Jul 2025 12:36:47 GMT</pubDate>
            <description><![CDATA[<ul>
<li>업무를 하다가 substring에 대해서 사용할 일이 있는데 sql로 문자열을 다루는 방법을 알아보자</li>
</ul>
<h2 id="1-substring">1. substring</h2>
<ul>
<li>사용 방법은 여러 형태가 있다.</li>
</ul>
<pre><code class="language-sql"># 1
SELECT substring(&#39;abcdefg&#39; FROM 2 FOR 3);  -- 결과: &#39;bcd&#39;

# 2
SELECT substring(&#39;abc123def&#39; FROM &#39;[0-9]+&#39;);  -- 결과: &#39;123&#39;

# 3
SELECT substring(&#39;abcdefg&#39;, 2, 3);  -- 결과: &#39;bcd&#39;

# 4
SELECT substring(&#39;abcdefg&#39;, length(&#39;abcdefg&#39;) - 3 + 1, 2); -- 결과: &#39;ef&#39;

# 5
SELECT substring(&#39;abcdefg&#39;, length(&#39;abcdefg&#39;) - 3); -- 결과: &#39;defg&#39;
</code></pre>
<ul>
<li>start : 시작 위치(인덱스가 1부터 시작)</li>
<li>length : 추출할 문자의 수
즉, 몇 번째 부터 몇 번째가 아니라, start지점부터 문자의 수를 나타낸다</li>
</ul>
<h2 id="2-substr">2. substr</h2>
<p>substr도 동일한 기능을 하지만, substring의 경우가 더 많은 기능을 제공한다.
다만, 성능 면에서는 큰 차이가 없기에 그냥 편한걸로 사용하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Javascript ] Spread, Rest 문법]]></title>
            <link>https://velog.io/@dev_sheep/Javascript-Spread-Rest-%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@dev_sheep/Javascript-Spread-Rest-%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Sun, 29 Jun 2025 14:00:34 GMT</pubDate>
            <description><![CDATA[<ul>
<li>Spread와 Rest 문법 모두 <code>...</code>처럼 생김새는 같으나 용도와 동작 방식이 다르다. </li>
</ul>
<h3 id="1-spread-문법">1. Spread 문법(...)</h3>
<ul>
<li>펼친다는 의미이며, 배열 또는 객체를 <code>개별 요소로 분해</code>해서 사용한다. </li>
<li><code>iterable</code> 객체에서 사용할 수 있기에 배열, 객체, Map, Set 또한 확장해서 사용이 가능하다.</li>
</ul>
<pre><code class="language-js">// 배열에서 사용
const arr = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;]
const arr2 = [...arr] // 배열의 얕은 복사.
const arr3 = [...arr, &quot;e&quot;] // 요소 추가.

// 객체에서 사용
const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 };  // { a: 1, b: 2, c: 3 }

// 함수 호출에 사용
function sum(a, b, c) {
  return a + b + c;
}

const nums = [1, 2, 3];
sum(...nums); // 6</code></pre>
<h3 id="2-rest-문법">2. Rest 문법(...)</h3>
<ul>
<li>나머지를 모은다는 의미로 함수의 인자나 객체/배열 구조 분해 시 <code>남은 요소들을</code> 하나의 변수로 수집한다. </li>
</ul>
<pre><code class="language-js">// 배열 구조 분해에서 사용
const [first, ...rest] = [10, 20, 30, 40];
// first: 10
// rest: [20, 30, 40]

// 객체 구조 분해에서 사용
const { a, ...rest } = { a: 1, b: 2, c: 3 };
// a: 1
// rest: { b: 2, c: 3 }

function foo(a, ...rest) {
  console.log(rest) // [&quot;a&quot;,&quot;b&quot;,&quot;c&quot;]
}
foo(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;)

const obj = { a: 1, b: 2, c: 3 }
const { c, ...obj2 } = obj
console.log(c, obj2) // 3 {a: 1, b: 2}</code></pre>
<ul>
<li>조금 헷갈리긴 한데, 변수 할당 코드 줄이 있을 때 왼쪽에 <code>...</code>이라면 Rest, 오른쪽이라면 펼치는 형태기 때문에 Spread라고 보면 괜찮지 않을까 싶다...? 의도가 더 중요해보이긴 한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] 인수 vs 매개변수]]></title>
            <link>https://velog.io/@dev_sheep/Javascript-%EC%9D%B8%EC%88%98-vs-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@dev_sheep/Javascript-%EC%9D%B8%EC%88%98-vs-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98</guid>
            <pubDate>Sun, 22 Jun 2025 14:05:14 GMT</pubDate>
            <description><![CDATA[<ul>
<li>매개변수로 통일해서 보통 쓰는 것 같은데, 인수라는 말도 있기에 이에 대해 헷갈리는 부분을 정리해보고자 한다.</li>
</ul>
<h2 id="메서드-호출">메서드 호출</h2>
<pre><code>1) 메서드 정의
int call(String str, int age)

2) 호출
call(&quot;hello&quot;, 30)</code></pre><h3 id="인수argument">인수(Argument)</h3>
<ul>
<li>여기서 &quot;hello&quot;, 30처럼 <code>넘기는 값</code>을 영어로 Argument라고 하며 한글로는 인수 또는 인자라고 한다.</li>
</ul>
<h3 id="매개변수parameter">매개변수(parameter)</h3>
<ul>
<li>메서드 정의에서 String str, int age를 매개변수, 파라미터라고 한다.
메서드를 호출할 때 인수를 넘기면, 그 인수가 <code>매개변수</code>에 대입된다.</li>
</ul>
<h3 id="정리">정리</h3>
<ul>
<li>인수는 메서드 내부로 들어가는 값을 의미</li>
<li>매개변수는 메서드 호출부와 메서드 내부 사이에서 값을 전달하는 역할을 하는 변수<ul>
<li>str = &quot;hello&quot;, age = 30이며 인수가 매개변수로 되는 과정이라고 보면 될 것 같다</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL] postgreSQL EXISTS]]></title>
            <link>https://velog.io/@dev_sheep/SQL-postgreSQL-EXISTS</link>
            <guid>https://velog.io/@dev_sheep/SQL-postgreSQL-EXISTS</guid>
            <pubDate>Sun, 15 Jun 2025 13:53:52 GMT</pubDate>
            <description><![CDATA[<ul>
<li>쿼리의 문법 중에 <code>EXISTS</code>가 존재한다. 이에 대해 <code>IN</code>과 함께 비교하면서 알아보자 </li>
</ul>
<h3 id="exists">EXISTS</h3>
<ul>
<li><p>말 그대로 서브쿼리에서 반환하는 값이 존재하는지에 대한 여부를 판단해주는 역할을 한다.</p>
<ul>
<li>특정 조건의 일치 여부에 대해 <code>true/false</code>를 반환</li>
</ul>
</li>
<li><p>주로 EXISTS를 사용하는 것이 성능이 좋다.</p>
<ul>
<li>찾는 조건이 하나라도 있으면 true 반환</li>
</ul>
</li>
<li><p>종종 SELECT 1을 해주는데, 이유는 무슨 값을 넣어주던 상관 없기에 <code>형식 상</code> 1을 넣어준다</p>
</li>
</ul>
<h3 id="exists-vs-in-동작">EXISTS vs IN 동작</h3>
<ul>
<li>존재하는 여부에 대해서 IN과 비교</li>
</ul>
<pre><code class="language-sql">[ EXISTS ]

SELECT *
FROM customers c
WHERE EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.id
);

[ IN ]
SELECT *
FROM customers
WHERE id IN (
    SELECT customer_id
    FROM orders
);</code></pre>
<ul>
<li>여기서 EXISTS가 IN보다 성능이 좋은 이유를 나열해보자<ul>
<li>IN은 내부 쿼리를 <code>먼저 모두 수행</code>하고 나서 리스트로 만들고, 이후 외부 쿼리의 각 행이 포함되는지 비교한다.</li>
<li><code>SELECT customer_id FROM orders</code> 에서 예를 들어 {1, 2, 5, 7}이 나왔다면</li>
<li>외부 쿼리 ⇒ <code>customers.id IN {1, 3, 4, 5, ...}</code> 에서 고객들이 포함됐는지, 안됐는지 비교해서 반환을 해준다.</li>
<li>반면, EXISTS는 외부쿼리에서 내부쿼리로 하나씩 검사한다.<ul>
<li>각 행마다 하위 쿼리를 실행해서 만족하는 행이 있는지 확인한다.</li>
<li>외부 쿼리를 돌면서 customers의 n번 고객이 하위 쿼리에서 있다면 포함한다.</li>
<li>그래서 이러한 동작형태에 따라 <code>존재 여부</code> 만 보기 때문에 보다 효율적이라고 한다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="exists-vs-in-null">EXISTS vs IN NULL</h3>
<ul>
<li>IN의 경우 NULL이 포함되면 원하지 않는 결과가 나올 수 있다</li>
<li></li>
</ul>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>score</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>abc</td>
<td>100</td>
</tr>
<tr>
<td>2</td>
<td>def</td>
<td>null</td>
</tr>
<tr>
<td>3</td>
<td>ghi</td>
<td>null</td>
</tr>
<tr>
<td>- 여기서 쿼리가 <code>SELECT * FROM students WHERE score IN (100, null)</code></td>
<td></td>
<td></td>
</tr>
<tr>
<td>- 위와 같이 되면 결과는 모두 나올 것이라는 예상과는 다르게 첫 번째 행인 name에 abc와 score가 100인 행만이 반환된다.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>- NULL은 값이 아니기 때문에 포함여부나 비교 등에서 <code>UNKNOWN</code> 으로 보아서 값 반환이 없는 것으로 보인다.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>- 그래서 IN을 할 때는 IS NULL, IS NOT NULL 등을 활용하는 것이 오류 방지에 좋다.</td>
<td></td>
<td></td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] undefined와 비교연산]]></title>
            <link>https://velog.io/@dev_sheep/Javascript-undefined%EC%99%80-%EB%B9%84%EA%B5%90%EC%97%B0%EC%82%B0</link>
            <guid>https://velog.io/@dev_sheep/Javascript-undefined%EC%99%80-%EB%B9%84%EA%B5%90%EC%97%B0%EC%82%B0</guid>
            <pubDate>Sat, 07 Jun 2025 12:59:49 GMT</pubDate>
            <description><![CDATA[<p>undefined일 때 비교연산이 되는 경우가 있었다. 이에 대한 경우와 동작을 살펴본다.</p>
<h3 id="1-와-의-비교">1. ==와 ===의 비교</h3>
<ul>
<li><code>==</code>는 타입을 <code>자동으로 변환</code>한 후에 비교한다.</li>
</ul>
<pre><code class="language-js">undefined == 0 // false
undefined == 1 // false
undefined == NaN // false
undefined == null // true</code></pre>
<ul>
<li><code>===</code>는 타입도 같고 값도 같아야 <code>true</code>를 반환한다.<pre><code class="language-js">undefined === 0 // false
undefined === 1 // false
undefined === undefined // true</code></pre>
</li>
</ul>
<h3 id="2-비교연산자---">2. 비교연산자(&lt;, &gt;, &lt;=, &gt;=)</h3>
<ul>
<li>이 경우에는 <code>숫자로 변환</code>되어 비교된다.<h4 id="-undefined는-숫자로-변환되면-nan이-된다">* undefined는 숫자로 변환되면 <code>NaN</code>이 된다</h4>
</li>
<li><blockquote>
<p>Number(undefined) =&gt; <code>NaN</code>, NaN은 어떤 수와도 비교할 수 없다.</p>
</blockquote>
</li>
</ul>
<pre><code class="language-js">undefined &gt; 0        // false
undefined &lt; 0        // false
undefined &gt;= 0       // false
undefined &lt;= 0       // false

Number(undefined)    // NaN
NaN &gt; 0              // false
NaN &lt; 0              // false
NaN == NaN           // false</code></pre>
<h3 id="3-isnan-numberisnan">3. isNaN(), Number.isNaN()</h3>
<ul>
<li><p>Number.isNaN()은 정확하게 <code>NaN</code>인 값만 true를 반환한다.
undefined는 타입이 <code>undefined</code>이고, 숫자도 아니며 자기 자신과 같다. 그리고 NaN이 아니라 <code>false</code>를 반환한다.</p>
</li>
<li><p>그렇기에 Number.isNaN(undefined) // false</p>
</li>
<li><p>isNaN(undefined) // true</p>
</li>
<li><p>왜 true냐면, isNaN()는 <code>타입을 먼저 숫자로 변환</code>하기 때문이다.</p>
<ol>
<li>Number(undefined) // NaN</li>
<li>isNaN(NaN) // true</li>
</ol>
</li>
<li><p>위와 같은 프로세스를 거치기 때문에 true가 나오는 것이다. </p>
</li>
</ul>
<h3 id="4-추가-궁금증">4. 추가 궁금증</h3>
<pre><code class="language-js">NaN == NaN       // false
NaN === NaN      // false
undefined == null     // true
undefined === null    // false</code></pre>
<ul>
<li><p>동등 연산자(==, ===)에서 NaN을 각각 할 때 왜 false냐면, NaN은 <code>자기 자신과도 같지 않다</code>라는 성질을 가지고 있기에 비교 시에는 전용 함수(Number.isNaN, isNaN)을 활용해야한다.</p>
</li>
<li><p>undefined와 null의 <code>==</code>비교는 자바스크립트에서 <code>예외적으로</code> true를 반환해준다.
다만, undefined === null은 엄격하게 판단한다.</p>
</li>
<li><p>undefined의 타입은 undefined, null의 타입은 object여서 타입이 다르기 때문에 false이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] flex 기억 안나는 것들 정리]]></title>
            <link>https://velog.io/@dev_sheep/CSS-flex-%EA%B8%B0%EC%96%B5-%EC%95%88%EB%82%98%EB%8A%94-%EA%B2%83%EB%93%A4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@dev_sheep/CSS-flex-%EA%B8%B0%EC%96%B5-%EC%95%88%EB%82%98%EB%8A%94-%EA%B2%83%EB%93%A4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 25 May 2025 11:45:56 GMT</pubDate>
            <description><![CDATA[<ul>
<li>tailwindcss를 사용하면서 flex-grow, shrink 등 사용하지만 막상 어떤 것인지 생각나지 않아서 이 기회에 한 번 정리해보고자 한다. </li>
</ul>
<h3 id="flex-grow">flex-grow</h3>
<ul>
<li>grow는 해당 요소가 Flexbox 레이아웃 안에서 <code>남는 공간</code>을 차지하게 만든다.</li>
</ul>
<pre><code class="language-css">flex-grow: 1; // grow 요소가 가능한 한 남는 공간을 차지함
flex-grow: 0; // grow-0 요소가 남는 공간을 전혀 차지하지 않음(default)</code></pre>
<p><strong>[ grow - 남는 공간 차지할 때 ]</strong></p>
<pre><code class="language-html">&lt;div class=&quot;flex&quot;&gt;
  &lt;div class=&quot;bg-red-500&quot;&gt;고정 너비&lt;/div&gt;
  &lt;div class=&quot;grow bg-green-500&quot;&gt;남는 공간을 채움&lt;/div&gt;
&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/c9eb309e-2e2b-4680-bd3c-dd0768706174/image.png" alt=""></p>
<p><strong>[ grow-0 - 남는 공간 차지하지 않을 때 ]</strong></p>
<pre><code class="language-html">&lt;div class=&quot;flex&quot;&gt;
  &lt;div class=&quot;bg-red-500&quot;&gt;고정 너비&lt;/div&gt;
  &lt;div class=&quot;grow-0 bg-green-500&quot;&gt;남는 공간을 채움&lt;/div&gt;
&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/ad48e7fb-86fd-4dcf-a3c8-3fc2d59111ef/image.png" alt=""></p>
<h3 id="flex-shrink">flex-shrink</h3>
<ul>
<li>컨테이너 공간이 부족할 때 항목이 줄어드는 비율을 설정한다.</li>
<li>default : 1(공간이 부족하면 줄어들 수 있음)</li>
<li>0 : 줄어들지 않음(항상 원래 너비 유지)</li>
</ul>
<pre><code class="language-html">&lt;div class=&quot;flex w-40&quot;&gt;
  &lt;div class=&quot;shrink-0 w-32 bg-red-500&quot;&gt;A&lt;/div&gt;
  &lt;div class=&quot;w-32 bg-blue-500&quot;&gt;B&lt;/div&gt;
&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/a8da6f75-ff3f-4913-baef-490de602e5b3/image.png" alt=""></p>
<ul>
<li>w-40 : 160px인데, 각 두 요소가 128px이나 사진 상으로는 A는 줄지 않고, B는 줄어든다.</li>
</ul>
<h3 id="flex-basis">flex-basis</h3>
<ul>
<li>Flex 항목의 초기 크기(기본 크기)를 설정. Flexbox 내부에서만 작동</li>
</ul>
<pre><code class="language-html">&lt;div class=&quot;flex&quot;&gt;
  &lt;div class=&quot;basis-1/3 bg-green-500&quot;&gt;33%&lt;/div&gt;
  &lt;div class=&quot;basis-2/3 bg-yellow-500&quot;&gt;66%&lt;/div&gt;
&lt;/div&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/cd430383-a27e-4f61-bffe-3dac1e45940a/image.png" alt=""></p>
<h3 id="이외">이외</h3>
<ul>
<li><p>번외로 gap은 Flexbox나 Grid 레이아웃에서 <code>자식 요소 간의 간격</code>을 설정할 때 사용한다.</p>
</li>
<li><p>CSS를 직접 쓰는 경우
<code>flex: [flex-grow] [flex-shrink] [flex-basis];</code></p>
<pre><code class="language-css">flex: 1 1 0%;  /* grow: 1, shrink: 1, basis: 0% */</code></pre>
</li>
<li><p>여러가지 필요한 경우가 있으면 gpt와 함께 찾아보자</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javascript] Promise.all과 Promise.allSettled]]></title>
            <link>https://velog.io/@dev_sheep/Javascript-Promise.all%EA%B3%BC-Promise.allSettled</link>
            <guid>https://velog.io/@dev_sheep/Javascript-Promise.all%EA%B3%BC-Promise.allSettled</guid>
            <pubDate>Wed, 14 May 2025 14:57:01 GMT</pubDate>
            <description><![CDATA[<ul>
<li>개발하는 도중 다수의 API 호출을 받고 나서 다음 로직을 진행해야 했다. 그런 경우에는 Promise.all을 사용하는데, 해당 내용을 정리할 겸 비교도할 수 있는 Promise.allSettled에 대해서도 한 번 간략하게 알아보고자 한다.</li>
</ul>
<h3 id="promiseall">Promise.all</h3>
<ul>
<li><code>모든 프로미스가 성공</code>해야 결과를 반환한다.</li>
<li>하나라도 실패하면 <code>reject</code></li>
</ul>
<pre><code class="language-js">// [ 성공 예시 ]
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);

Promise.all([p1, p2, p3])
  .then(results =&gt; {
    console.log(&#39;All success:&#39;, results); // [1, 2, 3]
  })
  .catch(err =&gt; {
    console.error(&#39;One failed:&#39;, err);
  });

// [ 실패 예시 ]
const p1 = Promise.resolve(1);
const p2 = Promise.reject(&#39;Error!&#39;);
const p3 = Promise.resolve(3);

Promise.all([p1, p2, p3])
  .then(results =&gt; {
    console.log(&#39;All success:&#39;, results);
  })
  .catch(err =&gt; {
    console.error(&#39;One failed:&#39;, err); // &#39;Error!&#39;
  });
</code></pre>
<h3 id="promiseallsettled">Promise.allSettled</h3>
<ul>
<li>모든 프로미스의 <code>성공/실패 여부와 관계없이</code> 결과를 수집<pre><code class="language-js">const p1 = Promise.resolve(1);
const p2 = Promise.reject(&#39;Failed&#39;);
const p3 = Promise.resolve(3);
</code></pre>
</li>
</ul>
<p>Promise.allSettled([p1, p2, p3])
  .then(results =&gt; {
    console.log(results);
    /*
    [
      { status: &#39;fulfilled&#39;, value: 1 },
      { status: &#39;rejected&#39;, reason: &#39;Failed&#39; },
      { status: &#39;fulfilled&#39;, value: 3 }
    ]
    */
  });</p>
<p>```</p>
<ul>
<li>개발하고 싶은 로직에 따라 원하는 것을 택해서 사용하면 된다</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Javascript ] some과 every]]></title>
            <link>https://velog.io/@dev_sheep/Javascript-some%EA%B3%BC-every</link>
            <guid>https://velog.io/@dev_sheep/Javascript-some%EA%B3%BC-every</guid>
            <pubDate>Sun, 04 May 2025 04:37:15 GMT</pubDate>
            <description><![CDATA[<p>forEach문을 사용하다보면 우리가 break, return, continue 등을 활용할 수 없다.
순회하다보면 굳이 전부 안돌아도 되는 경우가 있는데 이를 자바스크립트에서는 <code>some</code>, <code>every</code> 메서드가 있다. </p>
<h3 id="some">some()</h3>
<ul>
<li>하나라도 조건을 <code>만족하면</code> <code>true</code>를 반환한다.</li>
</ul>
<pre><code class="language-js">const numbers = [1, 3, 5, 8, 11];

const hasEven = numbers.some(num =&gt; num % 2 === 0);

console.log(hasEven); // ✅ true (8이 짝수이므로)</code></pre>
<ul>
<li>그러면 8에서 끝나고 반환해준다.</li>
</ul>
<h3 id="every">every()</h3>
<ul>
<li>하나라도 조건을 <code>만족하지 않으면</code> 즉시 중단 후 <code>false</code> 반환</li>
</ul>
<pre><code class="language-js">// 1번째 예시
const numbers = [1, 2, 3, 4];

const allPositive = numbers.every(num =&gt; num &gt; 0);

console.log(allPositive); // ✅ true

// 2번째 예시
const hasNegative = [1, -2, 3].every(num =&gt; num &gt; 0);
console.log(hasNegative); // ❌ false (-2 때문에 중단)</code></pre>
<ul>
<li>1번째는 전부 순회하나 2번째는 -2에서 중단된다.</li>
</ul>
<h3 id="비교">비교</h3>
<ul>
<li>둘 다 Boolean형태로 값을 반환한다.</li>
</ul>
<table>
<thead>
<tr>
<th>항목</th>
<th><code>some()</code></th>
<th><code>every()</code></th>
</tr>
</thead>
<tbody><tr>
<td><strong>기본 개념</strong></td>
<td><strong>하나라도</strong> 조건을 만족하면 <code>true</code> 반환</td>
<td><strong>모두가</strong> 조건을 만족해야 <code>true</code> 반환</td>
</tr>
<tr>
<td><strong>조기 종료</strong></td>
<td>조건 만족 시 즉시 종료 (<code>true</code>)</td>
<td>조건 불만족 시 즉시 종료 (<code>false</code>)</td>
</tr>
<tr>
<td><strong>리턴값</strong></td>
<td><code>true</code> / <code>false</code></td>
<td><code>true</code> / <code>false</code></td>
</tr>
<tr>
<td><strong>루프 중단</strong></td>
<td><code>return true</code>로 중단 가능</td>
<td><code>return false</code>로 중단 가능</td>
</tr>
<tr>
<td><strong>원본 변경 여부</strong></td>
<td>❌ 없음</td>
<td>❌ 없음</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Promise] catch가 여러 개인 경우 어떻게될까?]]></title>
            <link>https://velog.io/@dev_sheep/Promise-catch%EA%B0%80-%EC%97%AC%EB%9F%AC-%EA%B0%9C%EC%9D%B8-%EA%B2%BD%EC%9A%B0-%EC%96%B4%EB%96%BB%EA%B2%8C%EB%90%A0%EA%B9%8C</link>
            <guid>https://velog.io/@dev_sheep/Promise-catch%EA%B0%80-%EC%97%AC%EB%9F%AC-%EA%B0%9C%EC%9D%B8-%EA%B2%BD%EC%9A%B0-%EC%96%B4%EB%96%BB%EA%B2%8C%EB%90%A0%EA%B9%8C</guid>
            <pubDate>Sun, 27 Apr 2025 13:24:30 GMT</pubDate>
            <description><![CDATA[<ul>
<li>then, catch가 중첩되면 어떻게 될지 판단해보자.</li>
<li>Promise(비동기처리를 간편하게 해주는 객체)</li>
</ul>
<p>GPT 예시를 참고한다. </p>
<h3 id="-연속해서-then-catch쓴-경우-">[ 연속해서 then, catch쓴 경우 ]</h3>
<pre><code class="language-js">Promise.resolve(&#39;start&#39;)
  .then((r1) =&gt; {
    console.log(&#39;1단계:&#39;, r1);
    return &#39;2단계 데이터&#39;;
  })
  .then((r2) =&gt; {
    console.log(&#39;2단계:&#39;, r2);
    // 여기서 에러 발생
    throw new Error(&#39;2단계 에러!&#39;);
    return &#39;3단계 데이터&#39;;
  })
  .then((r3) =&gt; {
    console.log(&#39;3단계:&#39;, r3);
  .catch((err) =&gt; {
    console.error(&#39;잡은 에러:&#39;, err.message);
  });</code></pre>
<ul>
<li>위의 경우 2단계에서 에러가 났으니 catch문으로 이동하여 에러를 발생시킨다.</li>
<li>그 이후 3단계 데이터는 진행하지 않는다. </li>
</ul>
<h3 id="-중첩되는-경우-">[ 중첩되는 경우 ]</h3>
<pre><code class="language-js">Promise.resolve(&#39;시작&#39;)
  .then((result1) =&gt; {
    console.log(&#39;1단계:&#39;, result1);
    return Promise.resolve(&#39;2단계 데이터&#39;);
  })
  .then((result2) =&gt; {
    console.log(&#39;2단계:&#39;, result2);
    return Promise.resolve(&#39;3단계 데이터&#39;)
      .then((innerResult) =&gt; {
        console.log(&#39;3단계(안쪽):&#39;, innerResult);
        // 여기서 에러를 발생시켜볼게
        throw new Error(&#39;3단계에서 문제 발생!&#39;);
      });
  })
  .then((result3) =&gt; {
    console.log(&#39;4단계:&#39;, result3);
    return &#39;4단계 완료&#39;;
  })
  .catch((err) =&gt; {
    console.error(&#39;에러를 잡았다!&#39;, err.message);
  });</code></pre>
<ul>
<li><p>이 경우에는 <code>throw new Error(&#39;3단계에서 문제 발생!&#39;);</code>에서 발생이 되는데, 여기서 가까운 <code>catch문</code>으로 이동하여 &quot;에러를 잡았다! 3단계에서 문제 발생!&quot; 출력</p>
</li>
<li><p>마찬가지로 4단계 then은 실행을 안한다. </p>
</li>
<li><p>추가적으로 return을 안해주면 then이 이어지면서 진행은 되나 매개변수에 전달되는 값은 <code>undefined</code>로 처리된다.</p>
</li>
</ul>
<pre><code class="language-js">  .then((result2) =&gt; {
    console.log(&#39;2단계:&#39;, result2);
    return Promise.resolve(&#39;3단계 데이터&#39;)
      .then((innerResult) =&gt; {
        console.log(&#39;3단계(안쪽):&#39;, innerResult);
        throw new Error(&#39;3단계에서 문제 발생!&#39;);
      })
      .catch(() =&gt; {  // &lt;&lt;&lt; 3단계 catch
        console.log(&#39;error!&#39;);
      });
  })</code></pre>
<p>이렇게 중첩된 내부 안에서도 catch가 있으면 그 이후 4단계도 진행한다.
다만, 4단계에서 매개변수로 받는 <code>result3</code>는 <code>undefined</code>가 나온다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[build] 사용하지 않는 import도 번들링에 포함이 될까?]]></title>
            <link>https://velog.io/@dev_sheep/build-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94-import%EB%8F%84-%EB%B2%88%EB%93%A4%EB%A7%81%EC%97%90-%ED%8F%AC%ED%95%A8%EC%9D%B4-%EB%90%A0%EA%B9%8C</link>
            <guid>https://velog.io/@dev_sheep/build-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EB%8A%94-import%EB%8F%84-%EB%B2%88%EB%93%A4%EB%A7%81%EC%97%90-%ED%8F%AC%ED%95%A8%EC%9D%B4-%EB%90%A0%EA%B9%8C</guid>
            <pubDate>Sat, 12 Apr 2025 08:10:39 GMT</pubDate>
            <description><![CDATA[<p>프로젝트의 최적화를 위해서 번들링 사이즈를 줄이고자 하였다. 그런데 한 파일에서 import는 되어있으나 사용하지 않는 경우도 빌드 시 번들링에 포함되었었다. 그래서 이 부분에 대해서 한 번 지피티와 대화하였다. </p>
<ul>
<li>해당 패키지는 typescript였다.</li>
</ul>
<h3 id="typescript는-commonjs패키지">typescript는 CommonJS패키지</h3>
<ul>
<li>typescript는 CommonJS패키지인데, CommonJS는 트리쉐이킹(Tree-shaking)이 거의 안된다.</li>
</ul>
<pre><code class="language-ts">import { isConstructorDeclaration } from &#39;typescript&#39;</code></pre>
<p>이와 같이 선언하고 사용을 안해도 빌드 시에는 포함되어서 사이즈가 늘어난다는 것이다. </p>
<h3 id="esm-vs-commonjs">ESM vs CommonJS</h3>
<ul>
<li><p>Tree-shaking의 경우에는 안쓰는 코드를 제거해서 번들 사이즈를 줄이는데, ESM은 잘된다.</p>
</li>
<li><p>ESM(ES Modules)은 태생적으로 <code>정적(static) 구조</code> 이기 때문이다.</p>
<pre><code class="language-js">import { foo } from &#39;./utils.js&#39;</code></pre>
</li>
<li><p>util.js를 불러오기 전에 어떤 export를 사용할지 정하고, 나머지는 필요없다고 번들러가 미리 계산하여 제거를 할 수 있기에 Tree-shaking이 잘 된다.</p>
</li>
</ul>
<p>CommonJS는 반대로 <code>동적(Dynamic)</code>이라 분석이 어렵다</p>
<pre><code class="language-js">const utils = require(&#39;./utils&#39;)</code></pre>
<ul>
<li>utils안에는 뭐가 있고 어떻게 쓸지를 번들러가 알 수 없다.</li>
<li>그렇기에 번들러는 안전하게 다 포함시키게 되는 것이다.</li>
</ul>
<p>그래서 또다른 예시로 <code>lodash</code>가 있는데, lodash-es 패키지를 활용해서 트리쉐이킹에 사용하기도 한다.</p>
<p>정적 : 미리 읽고 계획을 세울 수 있음
동적 : 실행해보기 전에는 뭘 쓸지 모른다.</p>
<p>엄청 와닿지는 않을 수 있지만, 프로젝트 개발을 하면서 안쓰는 것은 지우고, 모듈시스템에서 패키지들을 잘 관리하여 필요한 것들만 번들링할 수 있도록 점검하는 것이 좋을 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue] key활용 리렌더링]]></title>
            <link>https://velog.io/@dev_sheep/Vue-key%ED%99%9C%EC%9A%A9-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@dev_sheep/Vue-key%ED%99%9C%EC%9A%A9-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Sat, 05 Apr 2025 07:57:02 GMT</pubDate>
            <description><![CDATA[<ul>
<li>개발을 하다가 apexcharts를 진행하는 도중 간헐적으로 차트에 대한 렌더링이 의도치 않게 진행이 되었다. </li>
<li>기존의 데이터가 완전히 삭제되지 않아서 초기화했다고 생각했던 부분이 제대로 되지 않은 것이다.</li>
<li>apexcharts에서 제공하는 destory(), updateSeries(), updateChartOptions()등이 적용이 되지 않아 key를 활용해서 리렌더링 하고자 하였다. </li>
<li>key가 하는 일, 장단점을 알아보자 </li>
</ul>
<h3 id="1-vue에서-key가-하는-일">1. Vue에서 key가 하는 일</h3>
<ul>
<li><p>Vue는 내부적으로 Virtual DOM을 사용해서 변경된 부분만 효율적으로 업데이트한다. </p>
</li>
<li><p>예를 들어 <code>v-for</code>를 사용하면 <code>:key</code>를 적용하는데, 리스트의 데이터가 변경되면 어떤 항목이 추가, 삭제 등이 되었는지 파악하여 최소한 DOM조작으로 업데이트를 한다.</p>
</li>
<li><p>그 외에 특정 컴포넌트를 강제로 리렌더링할 때 key를 사용하는데, 컴포넌트의 key값을 변경하면 Vue는 이를 <code>새로운 컴포넌트 인스턴스</code>로 인식하여 기존 컴포넌트를 <code>제거</code>한 다음 새로운 컴포넌트를 생성한다.</p>
<ul>
<li>즉, <code>unmount</code> 후 새로운 인스턴스를 생성<code>(mount)</code></li>
</ul>
</li>
<li><p>key가 없다면 <code>위치</code> 기준으로 요소를 비교하기에 리렌더링 오류가 생길 수 있다. </p>
</li>
</ul>
<pre><code class="language-javascript">
&lt;apexchart :key=&quot;chartKey&quot; :options=&quot;chartOptions&quot; :series=&quot;series&quot; type=&quot;area&quot; height=&quot;350&quot; /&gt;

const forceRerender = () =&gt; {
  chartKey.value += 1; // key 변경 → 새로운 apexchart 컴포넌트 생성
};</code></pre>
<ul>
<li>key값으로는 고유한 문자열이나 숫자를 사용하는게 좋다. </li>
</ul>
<p><strong>[ 단점 ]</strong></p>
<ul>
<li>리렌더링 비용이 증가한다. 새롭게 만들기 때문이다.</li>
</ul>
<h3 id="2-정리">2. 정리</h3>
<ul>
<li>Vue의 Virtual DOM알고리즘은 위치와 컴포넌트 타입이 같으면 재사용을 한다.</li>
<li>즉, 앞서 key를 적용안해도 바뀐다고 생각했지만 이전의 값이 남아있었던 것이 컴포넌트 위치는 동일하기 때문이지 않을까 싶다.</li>
<li>그래서 강제 리렌더링을 위해 key를 사용해서 새로운 컴포넌트로 만드는 과정을 거친다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL] COALESCE]]></title>
            <link>https://velog.io/@dev_sheep/SQL-COALESCE</link>
            <guid>https://velog.io/@dev_sheep/SQL-COALESCE</guid>
            <pubDate>Sun, 30 Mar 2025 08:26:48 GMT</pubDate>
            <description><![CDATA[<ul>
<li>쿼리를 보다가 COALESCE라는 것이 있어 정리해본다 </li>
</ul>
<h3 id="coalesce-개념">COALESCE 개념</h3>
<ul>
<li>COALESCE는 병합한다는 의미를 가지고 있다. <pre><code class="language-sql">COALESCE(value1, value2, ..., valueN)</code></pre>
=&gt; 왼쪽부터 차례로 NULL이 아닌 첫 번째 값을 반환</li>
</ul>
<h3 id="예시">예시</h3>
<pre><code class="language-sql">SELECT COALESCE(NULL, NULL, &#39;Hello&#39;, &#39;World&#39;); -- 결과: &#39;Hello&#39;</code></pre>
<pre><code class="language-sql">SELECT COALESCE(NULL, 100, 200); -- 결과: 100</code></pre>
<pre><code class="language-sql">SELECT COALESCE(column_name, &#39;Default Value&#39;) FROM table_name;
-- column_name이 NULL이면 &#39;Default Value&#39;를 사용</code></pre>
<ul>
<li>어떤 값이 NULL일 때 다음 파라미터에 설정한 값을 반환하도록 할 수 있다.</li>
</ul>
<p>NULL 방지를 할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL] WHERE 1=1?]]></title>
            <link>https://velog.io/@dev_sheep/SQL-WHERE-11</link>
            <guid>https://velog.io/@dev_sheep/SQL-WHERE-11</guid>
            <pubDate>Sun, 23 Mar 2025 13:01:35 GMT</pubDate>
            <description><![CDATA[<p>쿼리가 짜여있는 것들을 보는 중에 <code>WHERE 1=1</code>이 있는 것을 보았다. 음 일단 유추해보기에는 무조건 참인 것을 뜻하는데 (Python에서 While True처럼) 왜 이것을 사용하는걸까?</p>
<h3 id="왜-사용하는가">왜 사용하는가?</h3>
<ul>
<li>조건을 동적으로 붙이기 쉽게 하기 위함이다. <code>편의성</code>을 위함<pre><code class="language-sql">SELECT * FROM users
WHERE 1=1
AND age &gt; 20
AND gender = &#39;M&#39;
AND status = &#39;active&#39;</code></pre>
조건이 있든 없든 쉽게 추가하거나 뺄 수 있다.</li>
</ul>
<p>예를 들어 안쓴다면 아래처럼</p>
<pre><code class="language-sql">SELECT * FROM users
WHERE age &gt; 20 AND gender = &#39;M&#39; AND status = &#39;active&#39;</code></pre>
<p>사용하게 되니까 가독성? 측면에서는 위 예시가 더 낫다.</p>
<p>또한 동적 쿼리를 쓸 때도 유용하다고 하니 참고로 알아두자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Ag-Grid] getAllGridColumns와 getAllColumns의 차이]]></title>
            <link>https://velog.io/@dev_sheep/Ag-Grid-getAllGridColumns%EC%99%80-getAllColumns%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dev_sheep/Ag-Grid-getAllGridColumns%EC%99%80-getAllColumns%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 27 Feb 2025 15:18:33 GMT</pubDate>
            <description><![CDATA[<p>Ag-Grid에서 엑셀 내보내기를 할 때 컬럼들을 모두 가져왔어야했다. 근데 순서가 달라지는 경우가 있어 컬럼들을 가져오는 메서드들에 대한 차이를 알아보고자 한다.</p>
<h3 id="getallcolumns---31버전부터는-getcolumns">getAllColumns() -&gt; 31버전부터는 getColumns()</h3>
<ul>
<li>컬럼에 정의된 <code>모든 컬럼</code>을 반환한다.<ul>
<li>숨겨진 컬럼도 포함한다.</li>
</ul>
</li>
<li>내용은 같지만 31버전부터는 <code>getColumns()</code>, <del><code>getAllColumns()</code></del> deprecated!</li>
</ul>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/979b822e-e007-410d-a47d-28d874f4f6e5/image.png" alt=""></p>
<h3 id="getallgridcolumns">getAllGridColumns()</h3>
<ul>
<li>현재 <code>그리드에 표시된</code> 모든 컬럼을 반환한다.<ul>
<li>숨겨진 컬럼은 포함하지 <code>않는다.</code></li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/edbe8117-646d-444c-8012-f87859fe93e5/image.png" alt=""></p>
<h3 id="📌-정리">📌 정리</h3>
<table>
<thead>
<tr>
<th>메서드</th>
<th>반환대상</th>
<th>숨겨진 컬럼 포함 여부</th>
</tr>
</thead>
<tbody><tr>
<td>getAllGridColumns()</td>
<td>현재 표시된 컬럼만</td>
<td>❌ 포함되지 않음</td>
</tr>
<tr>
<td>getAllColumns()</td>
<td>전체 컬럼 모델</td>
<td>✅ 포함됨</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AG-grid] valueFormatter와 valueGetter의 차이]]></title>
            <link>https://velog.io/@dev_sheep/AG-grid-valueFormatter%EC%99%80-valueGetter%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dev_sheep/AG-grid-valueFormatter%EC%99%80-valueGetter%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 23 Feb 2025 08:55:14 GMT</pubDate>
            <description><![CDATA[<ul>
<li>Ag-grid를 사용하면서 개발을 했을 때 그리드에 숫자를 예를 들어, 소수점 3번째까지로 표현하고 싶다고 할 때 valueFormatter와 valueGetter 등을 활용했는데 그에 대한 차이점을 정리해보고자 한다</li>
</ul>
<h3 id="--valueformatter">- valueFormatter</h3>
<ul>
<li>UI에 출력되는 <code>값만</code> 변경할 때 사용된다.</li>
<li>원본 데이터는 변경 되지 않으며 <code>단순하게</code> 보여지는 값만 포매팅 된다.</li>
<li>예를 들면 YYYYMMDD 날짜를 YYYY-MM-DD형태로보여주나 원본 값은 YYYYMMDD 그대로이다.</li>
</ul>
<pre><code class="language-javascript">const columnDefs = [
  {
    headerName: &quot;Price&quot;,
    field: &quot;price&quot;,
    valueFormatter: (params) =&gt; {
      return `${params.value.toFixed(2)}`; // 100 → &quot;100.00&quot;
    },
  }
];</code></pre>
<h3 id="--valuegetter">- valueGetter</h3>
<ul>
<li>컬럼에 표시될 값 자체를 <code>동적으로 생성</code>한다.</li>
<li>반환된 값이 해당 컬럼의 데이터 값으로 적용된다.</li>
<li>그래서 엑셀에도 내보내기할 때 그리드 변경된 값으로 할 시 valueGetter가 좋다.</li>
</ul>
<pre><code class="language-javascript">const columnDefs = [
  {
    headerName: &quot;Full Name&quot;,
    valueGetter: (params) =&gt; {
      return `${params.data.firstName} ${params.data.lastName}`;
    },
  }
];
</code></pre>
<h3 id="--valueformatter-vs-valuegetter">- valueFormatter vs valueGetter</h3>
<table>
<thead>
<tr>
<th>기능</th>
<th>valueFormatter</th>
<th>valueGetter</th>
</tr>
</thead>
<tbody><tr>
<td>원본 데이터 변경 여부</td>
<td>변경하지 않음❌</td>
<td>변경하지 않음❌</td>
</tr>
<tr>
<td>실행 목적</td>
<td>출력 형식을 변경 (UI에서만 표시 형태 수정)</td>
<td>새로운 값을 생성 (원본 데이터에 없는 값도 표시 가능)</td>
</tr>
<tr>
<td>실행 시점</td>
<td>UI에 값이 표시될 때 실행됨</td>
<td>데이터 로딩 시점에 실행됨</td>
</tr>
<tr>
<td>반환 값이 적용되는 곳</td>
<td>UI에만 적용됨 (내부 값은 유지)</td>
<td>UI + 내부 값으로 활용 가능</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[[버전 관리] package.json에서 ^와 ~의 차이]]></title>
            <link>https://velog.io/@dev_sheep/%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC-package.json%EC%97%90%EC%84%9C-%EC%99%80-%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dev_sheep/%EB%B2%84%EC%A0%84-%EA%B4%80%EB%A6%AC-package.json%EC%97%90%EC%84%9C-%EC%99%80-%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 02 Feb 2025 10:33:13 GMT</pubDate>
            <description><![CDATA[<p>package.json을 보면 우리가 설치한 라이브러리 등을 보았을 때 버전이 적혀있다.</p>
<p>근데 이 중에서 <code>~</code> 혹은 <code>^</code>이 붙어 있는 거를 보면서 어떤 의미를 알아보려 한다.</p>
<h3 id="1-caret">1. <code>^</code>(Caret)</h3>
<ul>
<li><p>메이저 버전인 가장 왼쪽의 숫자를 기준으로 <code>마이너 버전까지만</code> 업데이트 허용</p>
<ul>
<li>메이저 버전이 0이면 안정적이지 않다고 간주하여 패치 버전만 업데이트 가능하다.</li>
</ul>
</li>
<li><p>예시</p>
<ul>
<li><code>&quot;vue&quot;: &quot;^3.2.0&quot;</code> -&gt; <code>3.x.x</code> 버전에서 <code>3.2.0</code> 이상, <code>4.0.0</code> 미만까지 허용</li>
<li><code>&quot;axios&quot;: &quot;^0.21.0&quot;</code> -&gt; <code>0.21.x</code> 버전에서 <code>0.21.0</code> 이상, <code>0.22.0</code> 미만까지 허용</li>
</ul>
</li>
<li><p>즉, 0을 제외하고 마이너 버전까지 업데이트를 한다.</p>
</li>
</ul>
<h3 id="2-tilde">2. <code>~</code>(Tilde)</h3>
<ul>
<li><p>주어진 마이너 버전 내에서만 변경을 허용한다.</p>
</li>
<li><p>예시</p>
<ul>
<li><code>&quot;express&quot;: &quot;~4.17.0&quot;</code> → <code>4.17.x</code> 버전에서 <code>4.17.0</code> 이상, <code>4.18.0</code> 미만까지 허용</li>
<li><code>&quot;lodash&quot;: &quot;~0.21.3&quot;</code> → <code>0.21.x</code> 버전에서 <code>0.21.3</code> 이상, <code>0.22.0</code> 미만까지 허용</li>
</ul>
</li>
</ul>
<h3 id="3-차이">3. 차이</h3>
<ul>
<li><p>안정성을 위한다면 <code>~</code>를 사용하여 보수적으로 관리하고, 최신 기능 반영 등에 신경쓴다면 <code>^</code>를 사용한다.</p>
</li>
<li><p>이외에도 단순 버전 고정으로 유지를 할 수 있다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue] v-for와 v-if의 동시활용이 안되는 이유]]></title>
            <link>https://velog.io/@dev_sheep/Vue-v-for%EC%99%80-v-if%EC%9D%98-%EB%8F%99%EC%8B%9C%ED%99%9C%EC%9A%A9%EC%9D%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@dev_sheep/Vue-v-for%EC%99%80-v-if%EC%9D%98-%EB%8F%99%EC%8B%9C%ED%99%9C%EC%9A%A9%EC%9D%B4-%EC%95%88%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Sun, 26 Jan 2025 12:31:24 GMT</pubDate>
            <description><![CDATA[<p>gpt형님과 함께 알아갑니다. </p>
<p>개발을 하다보면 머릿속으로 &quot;아 이렇게 짜면 될 거 같다&quot;하면서 써내려가지만 막상 배열과 객체 등을 사용할 때 <code>v-for</code>와 <code>v-if</code>를 같이 활용할 때가 가끔 있습니다.</p>
<p>그러면 흐음.. 어떻게 바꿀까 하는 생각과 함께 왜 안될까 라는 생각이 들었습니다.</p>
<blockquote>
<p>태생적으로 v-for가 우선순위를 가집니다.</p>
</blockquote>
<p>즉, v-for로 먼저 렌더링이 되고 나서 v-if를 통해 필터링을 합니다.</p>
<p>그렇게 되면 불필요한 렌더링이 발생하여 <code>성능 상 저하</code>가 일어납니다.</p>
<h3 id="예시">예시</h3>
<pre><code class="language-vue">&lt;template&gt;
  &lt;ul&gt;
    &lt;li v-for=&quot;item in activeItems&quot; :key=&quot;item.id&quot;&gt;{{ item.name }}&lt;/li&gt;
  &lt;/ul&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  data() {
    return {
      items: [
        { id: 1, name: &#39;Item 1&#39;, isActive: true },
        { id: 2, name: &#39;Item 2&#39;, isActive: false },
        { id: 3, name: &#39;Item 3&#39;, isActive: true },
      ],
    };
  },
  computed: {
    activeItems() {
      return this.items.filter(item =&gt; item.isActive);
    },
  },
};
&lt;/script&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/dev_sheep/post/340f67f8-8935-46b1-aed4-b6c30a1f155a/image.png" alt=""></p>
<p>결과가 생각한대로 나오지만 내부적으로는 아래와 같이 흘러갑니다.</p>
<blockquote>
<ol>
<li>v-for로 items를 모두 렌더링</li>
<li>각 항목에 대해 v-if 조건이 평가</li>
</ol>
</blockquote>
<p>그렇기에 데이터의 형식이나 v-for, v-if를 같은 선상에서 쓰지 않는 등의 과정을 통해 이것도 나름의 최적화를 하도록 해야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Typescript] shims-vue.d.ts와 env.d.ts 차이]]></title>
            <link>https://velog.io/@dev_sheep/Typescript-shims-vue.d.ts%EC%99%80-env.d.ts-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dev_sheep/Typescript-shims-vue.d.ts%EC%99%80-env.d.ts-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 19 Jan 2025 09:39:18 GMT</pubDate>
            <description><![CDATA[<h2 id="shims-vuedts와-envdts의-차이">shims-vue.d.ts와 env.d.ts의 차이</h2>
<h3 id="dts는-무엇인가">d.ts는 무엇인가?</h3>
<ul>
<li>type declare에서 따온 것으로 생각하면 되며 type을 정의하기 위해 존재하는 파일이다.<ul>
<li>즉, JS코드의 타입 정보를 이해할 수 있도록 도와준다.</li>
</ul>
</li>
<li>TS환경에서 타입 체킹이 필요한 타입들을 불러서 체크해야되기 때문에 @types로 시작되는 라이브러리들이 있는 이유이다.</li>
</ul>
<h3 id="shims-vuedts">shims-vue.d.ts</h3>
<ul>
<li><p>Vue 파일을 Typescript 환경에서 인식할 수 있도록 도와주는 파일이다.</p>
<ul>
<li><p>Typescript는 <code>.vue</code> 파일을 모듈로 인식하지 못하기 때문에 이를 해결하고자 위의 파일을 활용한다.</p>
<pre><code class="language-jsx">// shims-vue.d.ts 예시
declare module &#39;*.vue&#39; {
import { DefineComponent } from &#39;vue&#39;;
const component: DefineComponent&lt;{}, {}, any&gt;;
export default component;
}</code></pre>
</li>
<li><p>내용을 간략하게 보자면, DefineComponent는 Vue3에서 컴포넌트를 타입으로 정의하며 .vue 파일을 컴포넌트로 봤을 때 타입을</p>
</li>
</ul>
</li>
</ul>
<h3 id="envdts">env.d.ts</h3>
<ul>
<li>환경 변수(process.env, import.meta.env) 타입을 정의하는 파일</li>
<li>vite, next 등 타입 선언, 환경 설정, 커스텀 타입 등에 활용된다.<ul>
<li>.env파일과 env.d.ts의 연결을 진행</li>
</ul>
</li>
</ul>
<h3 id="shims-vuedts-vs-envdts">shims-vue.d.ts vs env.d.ts</h3>
<ul>
<li>사실 둘의 비교를 통해 차이점을 알기는 어렵지만, <code>.d.ts</code> 파일이 뭔지, 파일이 존재하지만 어떤 역할을 하는지 알고자 글을 작성하였다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Setting] dependencies와 devDependencies의 차이 ]]></title>
            <link>https://velog.io/@dev_sheep/Setting-dependencies%EC%99%80-devDependencies%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dev_sheep/Setting-dependencies%EC%99%80-devDependencies%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 12 Jan 2025 13:46:15 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>package.json에서 <code>dependencies</code> 와 <code>devDependencies</code> 속성이 존재한다.</p>
<ul>
<li><p>차이를 구분할 때 기준점을 패키지의 종류와 설치 목적에 따라 갈라진다.</p>
<h3 id="간략-차이점">간략 차이점</h3>
</li>
<li><p>dependencies : 실행될 때 <code>반드시</code> 필요한 패키지</p>
<ul>
<li>vue, express …</li>
</ul>
</li>
<li><p>devDependencies : <code>개발 과정</code> 에서만 필요한 패키지</p>
<ul>
<li>typescript, eslint …</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="dependencies">dependencies</h3>
<ul>
<li>프로젝트가 실행될 때 반드시 필요한 패키지들이 들어가는 곳</li>
<li><code>배포 후</code> 에도 해당 패키지들이 필요함</li>
</ul>
<pre><code class="language-jsx">{
  &quot;dependencies&quot;: {
    &quot;vue&quot;: &quot;^3.2.0&quot;,
    &quot;axios&quot;: &quot;^1.5.0&quot;
  }
}
</code></pre>
<h3 id="devdependencies">devDependencies</h3>
<ul>
<li>프로젝트를 <code>개발할 때만</code> 필요한 패키지들이 들어가는 곳</li>
<li>배포 시에는 필요하지 <code>않기</code> 때문에, 프로덕션 빌드에서는 제외</li>
</ul>
<pre><code class="language-jsx">{
  &quot;devDependencies&quot;: {
    &quot;typescript&quot;: &quot;^5.2.0&quot;,
    &quot;eslint&quot;: &quot;^8.50.0&quot;,
    &quot;vite&quot;: &quot;^4.3.0&quot;
  }
}</code></pre>
<h3 id="typescript는-왜-devdependencies">Typescript는 왜 devDependencies?</h3>
<ul>
<li>Typescript는  <code>빌드(컴파일)</code> 때만 필요하기 때문이다.</li>
<li>즉, 배포에는 컴파일된 <code>Javascript</code> 만 배포되기 때문</li>
</ul>
<h3 id="그러나">그러나</h3>
<p>무조건적으로 어떤 패키지는 dependencies나 devDependencies에 속하지는 않는다.</p>
<p>통상적으로는 목적과 분류에 따라 다르겠지만, 예를 들어 Typescript를 런타임 때까지 필요한 어떤 프로젝트를 진행할 때 필요할 수도 있다.</p>
<p>그렇기에 패키지 관리를할 때  구분하여 정리하는 것이 필요해 보인다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NPM] NPM과 NPX 차이]]></title>
            <link>https://velog.io/@dev_sheep/NPM-NPM%EA%B3%BC-NPX-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@dev_sheep/NPM-NPM%EA%B3%BC-NPX-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Sun, 05 Jan 2025 10:29:33 GMT</pubDate>
            <description><![CDATA[<h2 id="1-npm과-npx의-차이점">1. npm과 npx의 차이점</h2>
<p>대표적으로 react 설치 시 cli(command line interface, 글자를 입력해 컴퓨터에 명령을 내리는 방식)를 npx로 활용하여 설치한다.
<code>npx create-react-app my-app</code></p>
<p>근데 여기서 왜 npm을 하지 않고 npx를 사용하는 것인가 ?</p>
<ul>
<li>npm<ul>
<li>노드 패키지 관리자이며 설치, 관리, 실행에 사용된다.</li>
<li>npm install 명령어로 로컬 또는 글로벌 패키지를 설치한다.</li>
<li>npm install -g lodash형태로 하면 -g 옵션이 글로벌 즉 시스템 전역에 패키지를 설치한다.</li>
<li>반면 npm install의 경우 로컬 설치를 한다.</li>
</ul>
</li>
<li>npx<ul>
<li>5.2.0 npm 버전 이상에 포함된다.</li>
<li>패키지 실행에 최적화가 된 도구이며 실행 편의성에 따라 글로벌 혹은 패키지를 설치하지 않고 바로 직접 호출을 해준다.</li>
</ul>
</li>
</ul>
<h2 id="2-명령어-비교">2. 명령어 비교</h2>
<ul>
<li>물론 둘 다의 명령어를 통해서 설치할 수 있다.</li>
</ul>
<h3 id="-npm-"><strong>[ npm ]</strong></h3>
<pre><code>npm install create-react-app
npx create-react-app my-app
</code></pre><ul>
<li>npm install은 프로젝트 디렉토리에 <code>로컬로 설치</code>된다.</li>
<li>node_moudules 폴더에 저장, package.json에 기록된다.</li>
<li>create-react-app을 로컬에 설치하고 나서 바로 실행시켜야 하는 번거로움과 불필요한 파일이 쌓이게 된다.</li>
<li>글로벌 설치인 경우에는 버전 관리가 필요하고, 별도로 삭제하지 않으면 계속 남아 있다.</li>
</ul>
<h3 id="-npx-"><strong>[ npx ]</strong></h3>
<ul>
<li>로컬, 글로벌 설치가 필요 없으며 최신 버전을 실행한다.</li>
</ul>
<pre><code>npx create-react-app my-app
</code></pre><ul>
<li>그래서 위와 같이 프로젝트 초기 세팅에서 사용된다.</li>
</ul>
<p>현재는 boilerplate를 만들고 있는데, Vue 기준으로 npx를 통해 만들게 되면 소개해보고자 한다.</p>
]]></description>
        </item>
    </channel>
</rss>