<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jenna.log</title>
        <link>https://velog.io/</link>
        <description>Frontend Dev.</description>
        <lastBuildDate>Fri, 12 Sep 2025 07:51:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jenna.log</title>
            <url>https://velog.velcdn.com/images/dev_ming/profile/84f0026d-66f3-4beb-9d1f-8746322cc94b/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jenna.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_ming" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[✨간지나게 주석 쓰는 법 (feat.cursor)]]></title>
            <link>https://velog.io/@dev_ming/%EA%B0%84%EC%A7%80%EB%82%98%EA%B2%8C-%EC%A3%BC%EC%84%9D-%EC%93%B0%EB%8A%94-%EB%B2%95-feat.cursor</link>
            <guid>https://velog.io/@dev_ming/%EA%B0%84%EC%A7%80%EB%82%98%EA%B2%8C-%EC%A3%BC%EC%84%9D-%EC%93%B0%EB%8A%94-%EB%B2%95-feat.cursor</guid>
            <pubDate>Fri, 12 Sep 2025 07:51:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><em>프론트엔드 개발자를 위한 JSDoc 기반 주석 가이드</em></p>
</blockquote>
<hr>
<h2 id="왜-주석이-중요한가">왜 주석이 중요한가?</h2>
<p>&quot;좋은 코드에는 주석이 필요 없다&quot;는 말이 있지만, <strong>실무에선 그렇지 않다</strong>.
나도 주석을 잘 안쓰는 편이긴 한데 이 글 쓰다보니 다시 써야겠음 ㅎㅎ;</p>
<p>주석은 팀원, 미래의 나, 그리고 협업자에게 <em>“이 코드가 왜 존재하는지”</em> 설명하는 <strong>가장 강력한 도구</strong></p>
<p>프론트엔드 개발에선 특히,</p>
<ul>
<li>UI 흐름</li>
<li>API 요청</li>
<li>사용자 이벤트</li>
<li>컴포넌트 상태 변화</li>
</ul>
<p>등 복잡한 맥락이 얽히기 때문에, 주석이 <strong>문서 이상의 역할</strong>을 한다.</p>
<hr>
<h2 id="주석의-조건">주석의 조건</h2>
<table>
<thead>
<tr>
<th>조건</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>명확성</strong></td>
<td>누가 봐도 쉽게 이해 가능한 설명</td>
</tr>
<tr>
<td><strong>간결성</strong></td>
<td>핵심만 간단하게 전달</td>
</tr>
<tr>
<td><strong>일관성</strong></td>
<td>팀의 주석 스타일 유지</td>
</tr>
<tr>
<td><strong>문서화 가능성</strong></td>
<td>자동 문서화 도구가 읽을 수 있는 형식 사용</td>
</tr>
</tbody></table>
<blockquote>
<p>💡 팁: &quot;무엇&quot;보다 &quot;왜&quot;를 설명하라</p>
</blockquote>
<hr>
<h2 id="jsdoc-기본-문법">JSDoc 기본 문법</h2>
<blockquote>
<p><strong>JSDoc이란?</strong></p>
</blockquote>
<p>JSDoc은 자바스크립트랑 타입스크립트에서 <strong>주석으로 코드를 문서화할 수 있게 해주는 도구</strong>
그냥 주석을 다는 게 아니라, 정해진 규칙(@param, @returns 등)을 따라 쓰면<br>자동으로 API 문서도 만들 수 있고, 에디터에서 타입 힌트도 주고, 코드 이해가 더 쉬워진다</p>
<pre><code class="language-ts">/**
 * 사용자 이름을 포맷팅합니다.
 * @param {string} firstName - 이름
 * @param {string} lastName - 성
 * @returns {string} &quot;성, 이름&quot; 형식의 포맷된 문자열
 */
function formatUserName(firstName, lastName) {
  return `${lastName}, ${firstName}`;
}</code></pre>
<h3 id="자주-쓰는-태그">자주 쓰는 태그</h3>
<table>
<thead>
<tr>
<th>태그</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@param</code></td>
<td>파라미터 설명</td>
</tr>
<tr>
<td><code>@returns</code></td>
<td>반환값 설명</td>
</tr>
<tr>
<td><code>@example</code></td>
<td>사용 예시</td>
</tr>
<tr>
<td><code>@typedef</code></td>
<td>커스텀 타입 정의</td>
</tr>
<tr>
<td><code>@property</code></td>
<td>객체 속성 설명</td>
</tr>
<tr>
<td><code>@deprecated</code></td>
<td>더 이상 사용하지 말아야 할 함수 표시</td>
</tr>
</tbody></table>
<hr>
<h2 id="react-컴포넌트에-주석-달기">React 컴포넌트에 주석 달기</h2>
<pre><code class="language-tsx">/**
 * 기본 버튼 컴포넌트입니다.
 *
 * @param {Object} props
 * @param {string} props.label - 버튼에 표시될 텍스트
 * @param {() =&gt; void} props.onClick - 클릭 시 실행될 함수
 * @param {boolean} [props.disabled=false] - 비활성화 여부
 * @returns {JSX.Element} 렌더링된 버튼 엘리먼트
 */
const Button = ({ label, onClick, disabled = false }) =&gt; (
  &lt;button onClick={onClick} disabled={disabled}&gt;
    {label}
  &lt;/button&gt;
);</code></pre>
<hr>
<h2 id="실전에서-주석-잘-쓰는-팁">실전에서 주석 잘 쓰는 팁</h2>
<ul>
<li>❌ <code>// 버튼 클릭 이벤트 처리</code> → 이건 코드만 봐도 앎 </li>
<li>❌ <code>// 사용자 데이터를 서버에 전송하는 이벤트</code> → 이건 여전히 &quot;무엇&quot;을 말하고 있음  </li>
<li>✅ <code>// 로그인 성공 시 사용자 정보를 저장해 다음 단계로 이동하기 위함</code> → <strong>왜 필요한지 설명하는 주석</strong></li>
<li>✅ 복잡한 조건문이나 API 호출 흐름엔 주석 필수</li>
<li>✅ 주석은 리팩토링 대상! 오래된 주석은 잘못된 정보가 될 수 있음</li>
</ul>
<hr>
<h2 id="🛠️-유용한-도구">🛠️ 유용한 도구</h2>
<table>
<thead>
<tr>
<th>도구</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>VS Code + TypeScript</code></td>
<td>타입 기반 자동완성 + 주석 힌트</td>
</tr>
<tr>
<td><code>JSDoc</code>, <code>Typedoc</code></td>
<td>문서 자동 생성 도구</td>
</tr>
<tr>
<td><code>eslint-plugin-jsdoc</code></td>
<td>JSDoc 누락/오류 체크 플러그인</td>
</tr>
</tbody></table>
<hr>
<h2 id="cursor에서-jsdoc-자동-주석-활용하기">Cursor에서 JSDoc 자동 주석 활용하기</h2>
<p>AI가 발전하는 상황에서 굳이 내가 주석을 일일히? 
요즘 내가 메인으로 사용하는 IDE인 Cursor는 AI 기반 코드 보조 툴이라서, JSDoc 스타일의 주석도 자동으로 달 수 있다.</p>
<h4 id="jsdoc-자동-생성">JSDoc 자동 생성</h4>
<p>함수, 컴포넌트 위에 /** 입력 후 Enter를 치면 → Cursor가 함수 시그니처를 읽고 자동으로 JSDoc 블록을 생성해 줌.</p>
<p>예를 들어:</p>
<pre><code>/**
 * 
 */
function add(a: number, b: number): number {
  return a + b;
}</code></pre><p>위 상태에서 Enter를 누르면 아래처럼 자동 완성:</p>
<pre><code>/**
 * 두 숫자를 더합니다.
 * @param {number} a - 첫 번째 숫자
 * @param {number} b - 두 번째 숫자
 * @returns {number} 합계
 */
function add(a: number, b: number): number {
  return a + b;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[read] 모자딥 - 06장. 데이터 타입]]></title>
            <link>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-06%EC%9E%A5.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-06%EC%9E%A5.-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</guid>
            <pubDate>Mon, 31 Mar 2025 17:26:29 GMT</pubDate>
            <description><![CDATA[<p>데이터 타입은 값의 종류를 말한다. 자바스크립트(ES6)는 7개의 데이터 타입을 제공한다.</p>
<table>
<thead>
<tr>
<th>구분</th>
<th>데이터 타입</th>
</tr>
</thead>
<tbody><tr>
<td>원시타입</td>
<td>숫자 타입 (number)</td>
</tr>
<tr>
<td></td>
<td>문자 타입 (string)</td>
</tr>
<tr>
<td></td>
<td>불리언 타입 (boolean)</td>
</tr>
<tr>
<td></td>
<td>undefined 타입</td>
</tr>
<tr>
<td></td>
<td>null 타입</td>
</tr>
<tr>
<td></td>
<td>심벌 타입 (symbol)</td>
</tr>
<tr>
<td>객체 타입</td>
<td>객체타입</td>
</tr>
</tbody></table>
<p>예를 들어, 숫자 1 과 문자열 &#39;1&#39;은 전혀 다른 값이다. 자바스크립트 엔진은 타입을 구별해서 값을 취급할 것이다.</p>
<h3 id="61-숫자-타입">6.1 숫자 타입</h3>
<ul>
<li>c나 자바의 경우는 int, long, float, double 등과 같은 다양한 숫자 타입을 제공하는 반면에, 자바스크립트는 독특하게 하나의 숫자 타입만 존재한다.</li>
<li>숫자 타입의 값은 배정밀도 64비트 부동소수점 형식을 따른다. 모든 수를 실수로 처리하며, 정수만 표현하기 위한 테이터 타입이 별도로 존재하지 않는다.<pre><code class="language-javascript">1 === 1.0 // true</code></pre>
</li>
<li>숫자 타입은 추가적으로 세 가지 특별한 값도 표현할 수 있다.<ul>
<li>Infinity, -Infinity, NaN(not-a-number)</li>
</ul>
</li>
</ul>
<h3 id="62-문자열-타입">6.2 문자열 타입</h3>
<ul>
<li>문자열 타입은 텍스트 데이터를 나타내는 데 사용한다. 작은따옴표, 큰따옴표, 백틱으로 텍스트를 감싼다. 자바스크립트에서 가장 일반적인 표기법은 작은따옴표(&#39;&#39;)를 사용한다.</li>
</ul>
<h3 id="63-템플릿-리터럴">6.3 템플릿 리터럴</h3>
<ul>
<li>멀티라인 문자열, 표현식 삽입, 태그드 템플릿 등 편리한 문자열 처리 기능을 제공하기 위한 기능이다.</li>
<li>백틱(``)을 사용해 표현한다.</li>
<li>표현식을 삽입하기 위해서는 ${}으로 표현식을 감싼다<pre><code class="language-javascript">console.log(`1+2 = ${1+2}`)</code></pre>
</li>
</ul>
<h3 id="64-불리언-타입">6.4 불리언 타입</h3>
<ul>
<li>논리적 참, 거짓을 나타내는 true, false</li>
</ul>
<h3 id="65-undefined-타입">6.5 undefined 타입</h3>
<ul>
<li>undefined 타입은 undefined가 유일</li>
<li>변수 초기화는 암묵적으로 undefined로 이루어진다. 개발자가 변수에 값이 없다는 것을 명시하고 싶을 땐 undefined보다 null을 사용해야한다.</li>
</ul>
<h3 id="66-null-타입">6.6 null 타입</h3>
<ul>
<li>null이 유일하다. 대소문자를 구분함.</li>
<li>의도적 부재를 명시할 때 사용한다. 변수에 null을 할당하는 것은 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미이다.</li>
</ul>
<h3 id="67-심벌-타입">6.7 심벌 타입</h3>
<ul>
<li>ES6에서 추가된 7번째 타입으로 변경 불가능한 원시의 타입이다. 다른 값과 중복되지 않는 유일무이한 값.</li>
</ul>
<h3 id="68-객체-타입">6.8 객체 타입</h3>
<ul>
<li>자바스크립트를 이루고 있는 거의 모든 것이 객체. 6가지 데이터 타입 이외의 값은 모두 객체타입이다.</li>
</ul>
<h3 id="69-데이터-타입의-필요성">6.9 데이터 타입의 필요성</h3>
<ul>
<li>데이터 타입에 의한 메모리 공간의 확보와 참조에 따른 필요성</li>
<li>데이터 타입에 의한 값의 해석에 따른 필요성<ul>
<li>0100 0001을 숫자로 해석하면 65, 문자열로 해석하면 &#39;A&#39;</li>
</ul>
</li>
</ul>
<h3 id="610-동적-타이핑">6.10 동적 타이핑</h3>
<ul>
<li>c나 자바 같은 정적 타입 언어는 변수를 선언할 때 데이터 타입을 사전에 선언함. 이를 명시적 타입 선언 이라고 한다. </li>
<li>정적 타입 언어는 컴파일 시점에 타입 체크를 수행한다.</li>
<li>자바스크립트는 정적 타입 언어와 다르게 변수를 선언할 때 타입을 선언하지 않음. var, let, const 키워드를 활용해 변수를 선언. 따라서 어떠한 데이터 타입의 값이라도 자유롭게 할당할 수 있다.</li>
<li>자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정된다. 재할당에 의해 변수의 타입은 언제든 동적으로 변할 수 있다. 이러한 특징을 <strong>동적 타이핑</strong>이라고 한다.</li>
<li>동적 타입 언어는 유연성은 높지만 신뢰성은 떨어진다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[read] 모자딥 - 05장. 표현식과 문]]></title>
            <link>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-05%EC%9E%A5.-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EB%AC%B8</link>
            <guid>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-05%EC%9E%A5.-%ED%91%9C%ED%98%84%EC%8B%9D%EA%B3%BC-%EB%AC%B8</guid>
            <pubDate>Mon, 31 Mar 2025 15:33:05 GMT</pubDate>
            <description><![CDATA[<h3 id="51-값">5.1 값</h3>
<ul>
<li>값은 식(표현식)이 평가되어 생성된 결과</li>
</ul>
<pre><code>10+20; // 값 30</code></pre><ul>
<li>모든 값은 데이터타입을 가지며 타입에 따라 다르게 해석된다. 
  <em>ex) 0100 0001 을 숫자로 해석하면 65, 문자로 해석하면 A</em></li>
<li>변수에 할당되는 것은 값</li>
</ul>
<h3 id="52-리터럴">5.2 리터럴</h3>
<ul>
<li>리터럴은 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법</li>
<li>3은 단순한 숫자가 아니라 숫자 리터럴임. js엔진이 해당 리터럴을 보고 메모리에 값을 생성한다.</li>
<li>리터럴을 사용하면 다양한 데이터 타입의 값을 생성할 수 있다.<pre><code class="language-javaScript">// example
</code></pre>
</li>
</ul>
<p>100 // 정수 리터럴
&#39;hello&#39; // 문자열 리터럴
true // 정수 리터럴
{ name: &#39;Lee&#39;, address: &#39;Seoul&#39;} // 객체 리터럴
function() {} // 함수 리터럴</p>
<pre><code>### 5.3 표현식
- 표현식은 값으로 평가될 수 있는 문. 즉, 표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다.
- 리터럴을 값으로 평가됨. 즉 리터럴도 표현식.
- 표현식과 표현식이 평가된 값이 동등한 관계는 동치이다.</code></pre><p>1+2 = 3 // 1+2와 3은 동치</p>
<pre><code>- 표현식은 다른 표현식의 일부가 되어 새로운 값을 생성할 수 있음
```javaScript
var x = 1+2;

x+3 = 6;</code></pre><h3 id="54-문">5.4 문</h3>
<ul>
<li>문(statement)은 프로그램을 구성하는 기본 단위이자 최소 실행 단위</li>
<li>문은 여러 토큰으로 구성된다. 토큰이란 문법적인 의미를 가지며, 문법적으로 더 이상 나눌 수 없는 코드의 기본 요소를 말한다.</li>
<li>문은 명령문, 즉 컴퓨터에 내리는 명령이다. 선언문, 할당문, 조건문, 반복문 등으로 구분된다.</li>
</ul>
<h3 id="55-세미콜론과-세미콜론-자동-삽입-기능">5.5 세미콜론과 세미콜론 자동 삽입 기능</h3>
<ul>
<li>세미콜론(;)은 문의 종료를 나타냄.</li>
<li>자바스크립트 엔진에는 세미콜론 자동 삽입 기능(ASI)가 암묵적으로 수행된다.</li>
</ul>
<h3 id="56-표현식인-문과-표현식이-아닌-문">5.6 표현식인 문과 표현식이 아닌 문</h3>
<ul>
<li>표현식은 문의 일부일 수도 있고 그 자체로 문이 될 수도 있다.</li>
<li>표현식인 문과 표현식이 아닌 문을 구별하는 가장 간단하고 명료한 방법은 변수에 할당해 보는 것<pre><code class="language-javascript">var x; // 변수 선언문은 값으로 평가될 수 없으므로 표현식이 아니다.
x = 100; // 할당문은 표현식인 완전한 문이다.</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[read] 모자딥 - 04장. 변수]]></title>
            <link>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-04%EC%9E%A5.-%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-04%EC%9E%A5.-%EB%B3%80%EC%88%98</guid>
            <pubDate>Tue, 18 Mar 2025 16:19:24 GMT</pubDate>
            <description><![CDATA[<h3 id="41-변수란-무엇인가-왜-필요한가">4.1 변수란 무엇인가? 왜 필요한가?</h3>
<ul>
<li>프로그래밍 언어에서 데이터를 관리하기 위한 핵심 개념.</li>
<li><strong>하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름</strong></li>
<li>컴퓨터는 cpu로 연산을 수행하고, 메모리를 사용해 데이터를 기억한다.</li>
<li>메모리는 데이터를 저장할 수 있는 메모리 셀의 집합체. 각 셀은 고유의 메모리 주소를 갖는다. 메모리 주소는 메모리 공간의 위치를 나타내며 0부터 메모리 크기만큼 정수로 표현된다.</li>
<li>메모리에 저장되는 데이터는 2진수로 처리된다.</li>
<li>처리된 데이터를 재사용 하고 싶을 때, 메모리 주소를 통해 메모리 공간에 직접 접근하는 것은 치명적인 오류를 발생시킬 가능성이 높기 때문에 자바스크립트는 직접적인 메모리 제어를 허용하지 않는다. 이에 따라 값의 위치를 가리키는 상징적인 이름으로 <strong>변수</strong>가 사용된다.<blockquote>
<p>✔ 변수 이름: 메모리 공간에 저장된 값을 식별할 수 있는 고유한 이름
✔ 변수 값: 변수에 저장된 값</p>
</blockquote>
</li>
</ul>
<p><em>변수 이름은 심사숙고해서 지어라!!</em></p>
<br />

<h3 id="42-식별자">4.2 식별자</h3>
<ul>
<li><strong>식별자는 어떤 값을 구별해서 식별할 수 있는 고유한 이름</strong></li>
<li>식별자는 값이 아니라 메모리 주소를 기억하고 있음 -&gt; 메모리 주소에 붙힌 이름</li>
<li>변수 이름에만 국한에서 사용하지 않고 변수, 함수, 클래스 등의 이름은 모두 식별자임</li>
<li>선언에 의해 자바스크립트 엔진에 식별자의 존재를 알린다.</li>
</ul>
<br />

<h3 id="43-변수-선언">4.3 변수 선언</h3>
<ul>
<li>변수를 생성하는 것 -&gt; 값을 저장하기 위한 메모리 공간을 확보하고 변수 이름과 확보된 메모리 공간의 주소를 연결해서 값을 저장할 수 있게 준비하는 것.</li>
<li>메모리 공간 확보 해제 전까지는 누구도 확보된 메모리 공간을 사용할 수 없도록 보호됨</li>
<li>변수를 사용하기 위해선 반드시 선언이 필요하다❗❗</li>
<li>확보된 메모리 공간에는 js에 의해 <code>undefined</code>라는 값이 암묵적으로 할당되어 초기화됨</li>
<li>자바스크립트 엔진은 다음 2단계에 거쳐 변수 선언을 수행함<ol>
<li>선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.<ol start="2">
<li>초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다. <em>초기화 단계를 거치지 않으면 쓰레기 값이 나올 수 있음</em></li>
</ol>
</li>
</ol>
</li>
<li>선언하지 않은 식별자에 접근하면 ReferenceError 발생</li>
</ul>
<br />

<h3 id="44-변수-선언의-실행-시점과-변수-호이스팅">4.4 변수 선언의 실행 시점과 변수 호이스팅</h3>
<ul>
<li>변수 선언은 런타임이 아니라 그 이전 단계에서 먼저 실행됨
  -&gt; 이에 따라 선언이 참조보다 뒤에 있어도 에러가 나지 않음</li>
<li>변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 <strong>변수 호이스팅</strong>이라고 함.</li>
</ul>
<br />

<h3 id="45-값의-할당">4.5 값의 할당</h3>
<ul>
<li>변수에 값을 할당할 떄는 할당 연산자 = 를 사용<pre><code class="language-javaScript">var score = 80;</code></pre>
</li>
<li>값의 할당은 소스코드가 순차적으로 실행되는 시점인 런타임에 실행됨</li>
</ul>
<br />

<h3 id="46-값의-재할당">4.6 값의 재할당</h3>
<ul>
<li>이미 값이 할당되어 있는 변수에 새로운 값을 또다시 할당하는 것</li>
<li>값을 재할당할 수 없어서 저장된 값을 변경할 수 없다면 변수가 아니라 상수</li>
</ul>
<h3 id="47-식별자-네이밍-규칙">4.7 식별자 네이밍 규칙</h3>
<ul>
<li>다음의 네이밍 규칙을 준수해야함
```</li>
<li>특수문자를 제외한 문자, 숫자, 언더스코어(_), 달러 기호($)를 포함할 수 있다.</li>
<li>단, 특수문자를 제외한 문자, 언더스코어(_), 달러 기호($)로 시작해야 한다. 숫자로 시작하는 것은 허용하지 않는다.</li>
<li>예약어는 식별자로 사용할 수 없다.<pre><code></code></pre></li>
</ul>
<blockquote>
<h4 id="네이밍-컨벤션">네이밍 컨벤션</h4>
<p>일반적으로 변수나 함수의 이름에는 카멜 케이스를 사용하고, 생성자 함수, 클래스의 이름에는 파스칼 케이스를 사용</p>
</blockquote>
<pre><code class="language-javaScript">// camelCase
var firstName;

// snake_case
var first_name;

// PascalCase
var FirstName;

// typeHungarianCase
var strFirstName; // type + identifier
var $elem = document.getElementById(&quot;myId&quot;); // DOM 노드
var observable$ = fromEvent(document, &#39;click&#39;); // RxJS 옵저버블</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[read] 모자딥 - 03장. 자바스크립트 개발 환경과 실행 방법]]></title>
            <link>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-03%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD%EA%B3%BC-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-03%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD%EA%B3%BC-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 12 Mar 2025 11:34:14 GMT</pubDate>
            <description><![CDATA[<h3 id="31-자바스크립트-실행-환경">3.1 자바스크립트 실행 환경</h3>
<ul>
<li>모든 브라우저와 Node.js는 js를 해석하고 실행할 수 있는 js 엔진을 내장하고 있음</li>
<li>브라우저와 Node.js는 용도가 다르다.
  ✔ 브라우저는 웹페이지를 브라우저 화면에 렌더링 하는 것이 주된 목적.
  ✔ Node.js는 브라우저 외부에서 js 실행 환경을 제공하는 것이 주된 목적.<pre><code>  ex) 브라우저는 DOM API 제공, Node.js는 파일 시스템 제공</code></pre></li>
</ul>
<br />

<h3 id="32-웹-브라우저">3.2 웹 브라우저</h3>
<p>크롬 기준으로 설명</p>
<h4 id="321-개발자-도구">3.2.1 개발자 도구</h4>
<ul>
<li>웹 애플리게이션 개발에 필수적인 도구. 크롬에 내장되어 있음</li>
<li>Elements, Console, Sources, Network, Application 과 같은 기능 내장<h4 id="322-콘솔">3.2.2 콘솔</h4>
</li>
<li>에러 발생시 우선 확인 해야 하는 곳</li>
<li><code>console.log(...)</code>를 사용하여 콘솔에 간편하게 출력 가능. 이를 사용해 디버깅을 대체하기도 함</li>
<li>프롬프트에 js코드 입력 시 다음 줄에 실행결과 표시 됨.<h4 id="323-브라우저에서-자바스크립트-실행">3.2.3 브라우저에서 자바스크립트 실행</h4>
</li>
<li>브라우저는 HTML 파일을 로드하면 script 태그에 포함된 자바스크립트 코드를 실행한다.<h4 id="324-디버깅">3.2.4 디버깅</h4>
</li>
<li>개발자 도구로 디버깅 가능 (Sources 패널)</li>
<li>에러가 발생한 코드 왼쪽의 라인번호에 브레이크포인트를 걸고 디버깅 모드로 들어감</li>
</ul>
<br />

<h3 id="33-nodejs">3.3 Node.js</h3>
<h4 id="331-nodejs와-npm-소개">3.3.1 Node.js와 npm 소개</h4>
<ul>
<li>2009년, 라이언 달이 발표. 크롬 V8 자바스크립트 엔진을 빌드된 자바스크립트 환경</li>
<li>npm(<em>node package manager</em>) : 자바스크립트 패키지 매니저
  Node.js에서 사용할 수 있는 모듈들을 패키지화 해서 모아둔 저장소 역할과 패키지 설치 및 관리를 위한 CLI 제공<h4 id="332-nodejs-설치">3.3.2 Node.js 설치</h4>
</li>
<li>node 홈페이지에서 설치 가능<pre><code class="language-cli">// 설치 확인
$ node -v
$ npm -v</code></pre>
<h4 id="333-nodejs-repl">3.3.3 Node.js REPL</h4>
</li>
<li>터미널에서 간단한 코드를 실행해 줄 수 있게 해주는 프로그램</li>
<li><code>$ node</code> 명령어 실행으로 js 코드 실행해볼 수 있음.</li>
</ul>
<br />

<h3 id="34-비주얼-스튜디오-코드">3.4 비주얼 스튜디오 코드</h3>
<h4 id="341-비주얼-스튜디오-코드-설치">3.4.1 비주얼 스튜디오 코드 설치</h4>
<ul>
<li>브라우저 콘솔과 REPL에서 모자른 부분을 해결하기 위해 코드 에디터를 사용<h4 id="342-내장-터미널">3.4.2 내장 터미널</h4>
</li>
<li>vs code에는 터미널이 내장되어 있음. node.js 명령어로 자바스크립트 파일 실행 가능<h4 id="343-code-runner-확장-플러그인">3.4.3 Code Runner 확장 플러그인</h4>
</li>
<li>vs code의 내장 터미널에서 단축키를 사용해 다양한 프로그래밍 언어로 구현된 소스코드를 간단히 실행할 수 있는 플러그인<h4 id="344-live-server-확장-플러그인">3.4.4 Live Server 확장 플러그인</h4>
</li>
<li>클라이언트 사이드 API를 실행하기 위해 브라우저에서 코드를 실행시켜주는 플러그인</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[read] 모자딥 - 02장. 자바스크립트란?]]></title>
            <link>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-02%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</link>
            <guid>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-02%EC%9E%A5.-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</guid>
            <pubDate>Tue, 04 Mar 2025 17:18:00 GMT</pubDate>
            <description><![CDATA[<h3 id="21-자바스크립트의-탄생">2.1 자바스크립트의 탄생</h3>
<ul>
<li>1995년, 넷스케이프 커뮤니케이션즈의 웹페이지 보조 기능 수행을 위한 경량 프로그래밍 언어 개발 = <strong>브렌던 아이크가 개발한 자바스크립트</strong></li>
<li>1996년 3월, 넷스케이프 네비게이터에 탑재, 당시의 이름 <strong>모카</strong>
  이후 9월 <strong>라이브스크립트</strong>로 이름 변경 후 12월에 <strong>자바스크립트</strong>로 최종 명명</li>
<li>탄생 뒤 얼마 지나지 않아 파생버전인 JScript 출시되어 위기를 맞음</li>
</ul>
<br />

<h3 id="22-자바스크립트의-표준화">2.2 자바스크립트의 표준화</h3>
<ul>
<li>1996년 8월, 마이크로소프트가 <strong>JScript</strong>를 인터넷 익스플로러 3.0에 탑재</li>
<li>JScript와 JS는 표준화 되지 못하고 자사 브라우저에만 적당히 호환됨. 이에 따라 자사 브라우저의 시장 점유율을 높이기 위해 베타적인 기능을 경쟁적으로 추가. 이에 따른 <strong>크로스 브라우징 이슈</strong> 발생</li>
<li>자바스크립트의 파편화 방지를 위해 ECMA에 자바스크립트 표준화 요청. 이후 1997년 7월, ECMA-262라 불리는 표준화된 자바스크립트 초판 완성. ECMAScript로 명명됨.</li>
</ul>
<br />

<h3 id="23-자바스크립트-성장의-역사">2.3 자바스크립트 성장의 역사</h3>
<ul>
<li>초창기는 웹서버의 SSR로 실행. JS는 보조적 기능 수행을 위한 한정적인 역할.<h4 id="231-ajax-asynchronous-javascript-and-xml">2.3.1 Ajax (Asynchronous JavaScript and XML)</h4>
</li>
<li>서버 &amp; 브라우저 비동기 방식 데이터 교환 통신기능 = XMLHttpRequest</li>
<li>기존의 변경할 필요가 없는 부분까지 포함된 HTML을 서버에서 받아서 렌더링 하는 방식에서 Ajax를 활용하여 서버에서 필요한 부분만 한정적으로 렌더링하는 방식으로 전환. 이로 인해 웹브라우저에서도 데스크톱 애플리케이션과 유사한 빠른 성능과 부드러운 화면 전환이 가능해짐.<h4 id="232-jquery">2.3.2 JQuery</h4>
</li>
<li>DOM의 쉬운 제어 가능, 크로스 브라우징 이슈 어느정도 해결.<h4 id="233-v8-자바스크립트-엔진">2.3.3 V8 자바스크립트 엔진</h4>
</li>
<li>빠른 성능 탑재.</li>
<li>데스크톱 애플리케이션과 유사한 사용자 경험을 제공할 수 있게 됨.<h4 id="234-nodejs">2.3.4 Node.js</h4>
</li>
<li>2009년, 라이언 딜이 발표한 자바스크립트 런타임 환경</li>
<li>브라우저에서만 동작 가능하던 자바스크립트를 브라우저 이외의 환경에서도 동작할 수 있도록 만들어줌. 이로 인해 프론트엔드와 백엔드에서 모두 자바스크립트를 사용할 수 있는 이점이 생김.</li>
<li>비동기를 지원하고 단일 스레드 이벤트 루프 기반으로 동작하여 요청 처리 성능이 좋음. SPA에 적합함.</li>
<li>노드의 등장으로 js는 서버 사이드 애플리케이션 개발에도 사용할 수 있는 범용 프로그래밍 언어가 됨. 이러한 이점으로 인해 크로스 플랫폼을 위한 가장 중요한 언어로 주목받게 됨.<h4 id="235-spa-프레임워크">2.3.5 SPA 프레임워크</h4>
</li>
<li>웹 애플리케이션의 발달로 인한 개발 규모와 복잡도 상승 -&gt; 프레임워크 등장</li>
<li>ex) Angular, React, Vue.js, Svelte등 다양한 SPA 프레임워크 등장</li>
</ul>
<br />

<h3 id="24-자바스크립트와-ecmascript">2.4 자바스크립트와 ECMAScript</h3>
<ul>
<li>ECMAScript -&gt; js 표준 사양인 ECMA-262</li>
<li>자바스크립트는 일반적으로 ECMAScript + 클라이언트 사이드 Web API</li>
</ul>
<br />

<h3 id="25-자바스크립트의-특징">2.5 자바스크립트의 특징</h3>
<ul>
<li>웹 브라우저에서 동작하는 유일한 프로그래밍 언어</li>
<li>인터프리터 언어 - 모던 자바스크립트 엔진들은 인터프리터와 컴파일러의 장점을 결합해 코드를 빠르게 실행 가능하게 만듦</li>
<li>명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어</li>
</ul>
<br />

<h3 id="26-es6-브라우저-지원-현황">2.6 ES6 브라우저 지원 현황</h3>
<ul>
<li>인터넷 익스플로러를 제외한 대부분의 모던 브라우저는 지원.</li>
<li>ES6를 지원하지 않는 구형 브라우저를 사용 할 떄는 바벨과 같은 트랜스파일러를 사용해 다운그레이드 하여서 사용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[read] 모자딥 - 01장.  프로그래밍]]></title>
            <link>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-01%EC%9E%A5.-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</link>
            <guid>https://velog.io/@dev_ming/read-%EB%AA%A8%EC%9E%90%EB%94%A5-01%EC%9E%A5.-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D</guid>
            <pubDate>Sat, 10 Feb 2024 15:58:38 GMT</pubDate>
            <description><![CDATA[<h3 id="01-프로그래밍">01. 프로그래밍</h3>
<p>기초중 기초. 수학의 정석 집합만 풀었던 느낌으로 이것만 몇번을 본지 모르겠다. 요약할 것도 별로 없고 아주 기초지만 그래도 적어보자고<del>! 가보자고</del></p>
<h4 id="11-프로그래밍이란">1.1 프로그래밍이란?</h4>
<ul>
<li>프로그래밍은 컴퓨터에게 실행을 요구하는 일종의 커뮤니케이션. 개발자랑 컴퓨터랑 얘기한다는 건 거짓말이 아님 진짜 소통함</li>
<li>컴퓨터에게 어떤 명령을 내릴 것 인지 제대로 정리하기 위해 요구사항을 명확히 이해하고 해결 방안을 정의해야 한다. 즉 <strong>문제해결능력</strong>을 요하게 됨.</li>
<li>알고리즘이 꼭 문제해결능력은 아니고, 하는데에 필요할 뿐, 문제를 명확히 이해하고 분석하고 구분하는 능력이 중요하다. </li>
<li>컴퓨터가 알아먹는건 0과 1밖에 없습니다. 그런애가 알아먹을 정도로 정확하고 상세하게 요구사항을 설명하는 것이 프로그래밍.
따라서 이와 같이 컴퓨터의 입장에서 보고 (컴퓨터 감수성..?) 설명하는 것이 <strong>컴퓨팅 사고</strong> 입니다~ 흔히 말하는 컴퓨팅사고 능력 키우기 어쩌고~ 는 다 이런 말이었다는 것</li>
</ul>
<h4 id="12-프로그래밍-언어">1.2 프로그래밍 언어</h4>
<ul>
<li>컴퓨터에서 명령을 전달할 때, 컴퓨터가 이해할 수 있는 언어로 전달을 해야한다. 이떄 필요한 것이 <strong>컴파일러 (compiler)</strong> 혹은 <strong>인터프리터 (interpreter)</strong>.
사람의 프로그래밍 언어를 기계가 이해할 수 있는 기계어로 변환해주는 일종의 번역기다.</li>
</ul>
<h4 id="13-구문과-의미">1.3 구문과 의미</h4>
<ul>
<li><p>문법적으로 틀린 것이 없어도 문맥에 따른, 의미를 가지고 있어야 언어의 역할을 수행할 수 있다. 이는 일반적 언어와 비슷하다. 언어의 의미는 문맥에 있는 것이지 문법에 있지 않다.</p>
</li>
<li><p>프로그래밍 언어도 마찬가지.</p>
<pre><code class="language-javascript">const number = &#39;string&#39;;
console.log(number * number); // NaN</code></pre>
<p>문법적으로는 전혀 틀리지 않은 자바스크립트 언어이지만 의미적으로 ..? 하게 만드는 예시.
...? 왜 저렇게 했지..? 하는 느낌 일듯
number 에 string 을 할당했기 때문인데 이것은 진짜 그냥 문맥적인 흐름에 따른 것이다. </p>
</li>
<li><p>결국 프로그래밍은 요구사항의 집합을 분석해 적절한 자료구조와 함수의 집합으로 변환한 후, 그 흐름을 제어하는 것이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[버르장머리 없는 도커 자식 혼쭐내기]]></title>
            <link>https://velog.io/@dev_ming/%EB%B2%84%EB%A5%B4%EC%9E%A5%EB%A8%B8%EB%A6%AC-%EC%97%86%EB%8A%94-%EB%8F%84%EC%BB%A4-%EC%9E%90%EC%8B%9D-%ED%98%BC%EC%AD%90%EB%82%B4%EA%B8%B0</link>
            <guid>https://velog.io/@dev_ming/%EB%B2%84%EB%A5%B4%EC%9E%A5%EB%A8%B8%EB%A6%AC-%EC%97%86%EB%8A%94-%EB%8F%84%EC%BB%A4-%EC%9E%90%EC%8B%9D-%ED%98%BC%EC%AD%90%EB%82%B4%EA%B8%B0</guid>
            <pubDate>Mon, 24 Jul 2023 10:50:11 GMT</pubDate>
            <description><![CDATA[<p>도커 때문에 열받아 죽을 것 같아서 쓰는 포스팅</p>
<p>요즘 윈도우 환경에서 개발을 하는데 도커는 리눅스 환경에서 돌아가다보니 최적화가 별루,,,
그래서 wsl환경에서 자주 사용을 한다.</p>
<p>하지만 문제는 wsl을 사용하면 컴퓨터가 아주 느려진다는것... 
그렇다고 도커를 끌 수도 없는 노릇이고,, 어떻게 해야할까?!</p>
<br>

<p>사실 이미 유명한 문제이긴 함</p>
<blockquote>
</blockquote>
<p><a href="https://stackoverflow.com/questions/62154016/docker-on-wsl2-very-slow">https://stackoverflow.com/questions/62154016/docker-on-wsl2-very-slow</a></p>
<p>해당 링크로 들어가보면 이미 많은 사람들이 고통받고 있음을 알 수 있다..</p>
<p>이럴때는 wsl이 사용하는 메모리를 제한을 걸어주면 된다.</p>
<h3 id="wsl2-메모리-최댓값-정해주기">WSL2 메모리 최댓값 정해주기</h3>
<p>일단 계속 메모리 과부하가 나는 이유는 윈도우와 다르게 리눅스는 메모리의 한계치까지 파일의 정보를 최대한 캐시로 보존하고, wsl2는 이에 따라 할당된 메모리가 부족해지면 추가적으로 메모리를 할당하기 때문. </p>
<p>그래서 메모리 최댓값을 루트 폴더에 들어가서</p>
<pre><code>[wsl2] 
memory=900MB    #Limits VM memory in WSL 2 to 900MB 
processors=1    #Makes the WSL 2 VM use one virtual processors</code></pre><p>다음과 같이 정해주면 정해준 메모리만큼까지만 할당하기 때문에 수월하게 도커를 돌릴 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTTP] HTTP 기본 정리]]></title>
            <link>https://velog.io/@dev_ming/HTTP-HTTP-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@dev_ming/HTTP-HTTP-%EA%B8%B0%EB%B3%B8-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 13 Jun 2023 05:32:42 GMT</pubDate>
            <description><![CDATA[<h2 id="http">HTTP</h2>
<p>HyperText Transfer Protocol의 약자로 웹에서 정보를 교환하기 위한 프로토콜(규약) 이다. 클라이언트와 서버 간에 데이터를 전송하는 법을 정의한다. </p>
<h3 id="✅stateless-protocol">✅Stateless Protocol</h3>
<p>HTTP는 <code>stateless protocol</code>, 즉 <strong>비상태 프로토콜</strong>이다. 이는 서버가 이전에 전송된 정보를 기억하지 않는다는 의미로, 각각의 요청이 별개로 처리되며 이전 요청과 다음 요청 사이에 연결고리가 없다. 이러한 특징으로 인해 서버는 세션과 같은 별도의 추가정보를 관리하지 않아도 되고, 다수의 요청 처리 및 서버의 부하를 줄일 수 있다는 이점을 가지게 된다. </p>
<h3 id="✅request--response">✅Request &amp; Response</h3>
<p>HTTP는 기본적으로 클라이언트-서버 모델을 따른다. 클라이언트는 HTTP 요청(request)을 생성하고, 서버는 요청된 정보에 대한 응답(response)을 제공한다. </p>
<br>

<h2 id="url">URL</h2>
<p>Uniform Resource Locator의 약자로, 서버의 자원 위치를 가리키는 표준적인 방식이다. 인터넷에서 웹페이지, 이미지 등을 특정 위치에 연결하거나 가져오는 데에 사용되는 주소다. 
<br></p>
<p>URL의 기본구조는 다음과 같다.</p>
<pre><code class="language-bash">protocol://hostname:port/path?query_string#fragment_id</code></pre>
<blockquote>
<ol>
<li><strong>protocol(프로토콜)</strong> : 자원에 접근하기 위해 사용되는 방법을 지정. HTTP, HTTPS, FTP 등이 있다.</li>
<li><strong>hostname(호스트이름)</strong> : 자원이 위치한 서버의 도메인 이름 또는 IP 주소</li>
<li><strong>port(포트)</strong> : 서버에서 자원에 접근하기 위해 특정 포트를 지정한다. 대부분의 HTTP 통신에서는 생략되며 기본적으로 HTTP는 80포트를 사용한다. </li>
<li><strong>path(경로)</strong> : 서버에서 자원의 특정 위치를 지정한다. 종종 폴더와 파일 구조를 통해 나타내진다. </li>
<li><strong>Query String(쿼리 문자열)</strong> : 웹 서버에 추가 정보를 제공하는 데 사용된다. 보통 <code>key=value</code> 쌍의 형태로 <code>&amp;</code> 기호로 구분된다. 쿼리 문자열은 <code>?</code> 기호로 시작한다. </li>
<li><strong>Fragment ID(프래그먼트 아이디)</strong> : 웹 페이지 내의 특정 부분을 가리키는 데 사용된다. <code>#</code> 기호로 시작한다. </li>
</ol>
</blockquote>
<br>

<h2 id="http-요청-메서드">HTTP 요청 메서드</h2>
<p>url을 사용하여 서버에 특정 데이터를 요청할 때 특정 동작을 수행하고 싶다면, HTTP 요청 메서드 (HTTP Request Methods)를 사용하면 된다. </p>
<h3 id="✅주요-메서드">✅주요 메서드</h3>
<ul>
<li><strong>GET</strong>(<strong>요청</strong>) : 서버로부터 정보를 조회하기 위해 사용되는 메서드 </li>
<li><strong>POST</strong>(<strong>생성</strong>) : 서버로 정보를 전송하기 위해 사용되는 메서드. 주로 서버의 상태를 변경하거나 데이터를 생성하는 데 사용된다. </li>
<li><strong>PUT</strong>(<strong>변경</strong>) : 서버의 리소스를 업데이트 하는데 사용되는 메서드. 리소스를 생성할 수도 있다.</li>
<li><strong>DELETE</strong>(<strong>삭제</strong>) : 서버의 특정 리소스를 삭제하는데 사용되는 메서드</li>
</ul>
<blockquote>
<h4 id="post-vs-put">POST vs PUT</h4>
<p><code>POST</code>와 <code>PUT</code>은 둘다 리소스를 생성하는데 사용될 수 있다. 그러나 둘의 리소스를 생성하는 방식과 의미는 서로 다르다. </p>
</blockquote>
<ol>
<li><strong>POST</strong> : POST를 이용하여 새 리소스를 생성하면, 서버는 새로운 리소스의 위치(URI)를 결정한다. 클라이언트는 생성할 데이터만 제공하고, 서버는 그 데이터를 사용하여 새로운 리소스를 만들고, 그 위치를 클라이언트에게 알려준다. </li>
<li><strong>PUT</strong> : PUT을 이용하여 새 리소스를 생성하면, 클라이언트는 새 리소스가 생성되어야 할 정확한 위치(URI)를 서버에 알려주어야 한다. 만약 그 위치에 이미 리소스가 존재한다면, 그 리소스는 클라이언트가 제공한 데이터로 교체된다. 아무것도 없다면, 새로운 리소스가 해당 위치에 생성된다. <blockquote>
</blockquote>
즉 &quot;생성&quot; 이라는 개념이 두 메서드에 모두 적용되지만, POST는 &quot;이 데이터를 가져가서 처리해주세요&quot; 와 같은 요청을 보내는 개념이고, PUT은 &quot;이 데이터를 이 특정 위치에 저장해주세요&quot; 와 같은 개념이다.</li>
</ol>
<br>

<h2 id="http-상태코드">HTTP 상태코드</h2>
<p>HTTP 상태코드(Status Code)는 요청을 받은 서버가 설정해주는 응답(response)정보이다. 코드는 3자리의 숫자로 서버가 클라이언트의 요청을 어떻게 처리했는지를 나타낸다. </p>
<h3 id="✅주요-상태코드">✅주요 상태코드</h3>
<ol>
<li><p><strong>1xx (정보 응답)</strong> : 요청을 받았고, 프로세스를 계속 진행 중임을 나타낸다.</p>
<ul>
<li>100 Continue: 서버가 요청의 초기 부분을 받았으며, 나머지 부분을 기다리고 있음을 나타낸다.</li>
</ul>
</li>
<li><p><strong>2xx (성공)</strong> : 요청이 성공적으로 수신, 이해, 수락되었음을 나타낸다. </p>
<ul>
<li>200 OK: 요청이 성공적으로 처리되었음을 나타낸다. GET, POST, PUT, DELETE 등 모든 메서드에 대한 가장 일반적인 성공 응답이다. </li>
<li>201 Created: 요청이 했으며, 그 결과로 새로운 리소스가 생성되었음을 나타낸다. 일반적으로 POST 나 일부 PUT의 요청의 응답으로 반환된다.</li>
</ul>
</li>
<li><p><strong>3xx (리다이렉션 완료)</strong> : 대부분 클라이언트가 이전 서버주소로 리소스를 요청할 때 나오는 코드이다. </p>
<ul>
<li>301 Moved Permanently: 요청한 url이 영구적으로 새로운 주소로 이전했음을 나타낸다. 서버는 해당 응답과 함께 새로운 url을 제공해야한다. </li>
</ul>
</li>
<li><p><strong>4xx (요청 오류)</strong> : 클라이언트에 오류가 있음을 나타낸다.</p>
<ul>
<li>400 Bad Request: 서버가 요청을 이해하지 못했음을 나타낸다. 일반적으로 요청의 크기, 구문, 라우팅 문제등으로 인해 발생한다. </li>
<li>401 Unauthorized: 권한이 없음을 나타낸다.</li>
<li>403 Forbidden: 서버에서 해당 자원에 대한 접근이 금지되었음을 나타낸다. </li>
<li>404 Not Found: 요청한 자원이 서버에 없음을 나타낸다. 일반적으로 서버에 존재하지 않는 페이지에 접근하려고 할 때 발생한다. </li>
</ul>
</li>
<li><p><strong>5xx (서버 오류)</strong> : 서버가 유효한 요청을 처리하는데 실패했음을 나타낸다. </p>
<ul>
<li>500 Internal Server Error: 서버에 오류가 발생하여 요청을 수행할 수 없음을 나타낸다. </li>
<li>502 Bad Gateway: 웹 서버가 게이트웨이 또는 프록시 역할을 수행하면서 상류 서버로 부터 잘못된 응답을 받았음을 나타냄.</li>
</ul>
</li>
</ol>
<br>
해당 코드들 외에도 HTTP 상태코드는 수백 가지가 있으며 각 코드는 특정 유형의 HTTP 응답을 나타낸다. 
]]></description>
        </item>
        <item>
            <title><![CDATA[node-gyp error find vs]]></title>
            <link>https://velog.io/@dev_ming/node-gyp-error-find-vs</link>
            <guid>https://velog.io/@dev_ming/node-gyp-error-find-vs</guid>
            <pubDate>Fri, 09 Jun 2023 05:44:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/dev_ming/post/79c90972-f5ad-47a3-9dcb-d3d43cec01ca/image.png" alt=""></p>
<pre><code>gyp ERR! find VS
gyp ERR! find VS msvs_version was set from command line or npm config
gyp ERR! find VS - looking for Visual Studio version 2022
gyp ERR! find VS VCINSTALLDIR not set, not running in VS Command Prompt
gyp ERR! find VS unknown version &quot;undefined&quot; found at &quot;C:\Program Files\Microsoft Visual Studio\2022\Community&quot;
...</code></pre><p>깃헙에서 코드를 받아서 돌리는데 계속 저런 에러가 났다.</p>
<p>Visual Studio를 안깔아서 그런가 하고 깔았다.
그냥 깔았을 때도 안되서 ㅜㅜ 뭔가 했는데</p>
<p>설치할 때
<img src="https://velog.velcdn.com/images/dev_ming/post/ea8695ad-f0ce-4ab6-9b56-fb213f2f2902/image.png" alt=""></p>
<p>C++을 사용한 데스트톱 개발을 설치해야한다고 해서 설치했다.</p>
<p>하지만 여전히 안됨 🤔</p>
<p>그래서 상단 탭의 개별구성요소에 들어가서 <code>Windows 10 SDK</code>랑 <code>최신 v143 빌드 도구용 c++ ATL</code>이랑 <code>MSVC v143 최신</code> 이 설치되었는지 확인하고 설치해줌</p>
<p>하지만 역시 같은 에러 ㅜㅜ,,,</p>
<p>그래서 계속 구글링하다가
<a href="https://stackoverflow.com/questions/70315519/node-gyp-error-could-not-find-any-visual-studio-installation-to-use">https://stackoverflow.com/questions/70315519/node-gyp-error-could-not-find-any-visual-studio-installation-to-use</a>
상위 링크 발견해서 봤더니 node 16버전이 문제가 있는거 같다고 다운그레이드해서 사용하면 된다길래 nvm 설치해서 14버전으로 바꿔서 돌려봤다.</p>
<p>그랬더니 성공...!</p>
<p>맥 쓰다가 윈도우로 프론트 하니까 터미널 명령어가 젤 힘든듯 ㅜ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Unity] 유니티에서  socket.io 사용하기]]></title>
            <link>https://velog.io/@dev_ming/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0%EC%97%90%EC%84%9C-socket.io-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_ming/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0%EC%97%90%EC%84%9C-socket.io-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 27 Apr 2023 08:20:49 GMT</pubDate>
            <description><![CDATA[<h2 id="기본-세팅">기본 세팅</h2>
<p><em>서버는 기본적으로 node.js 서버 사용</em></p>
<p>직접 설치해도 되지만 에셋스토어에서 구매하면 빠르기 때문에 에셋스토어에서 구매해서 import 해서 사용함
<img src="https://velog.velcdn.com/images/dev_ming/post/c03f34a7-04e8-4837-aa83-2f1f3ce160fe/image.png" alt=""></p>
<blockquote>
<p><a href="https://assetstore.unity.com/packages/tools/network/socket-io-v2-client-for-unity-standalone-webgl-186263">https://assetstore.unity.com/packages/tools/network/socket-io-v2-client-for-unity-standalone-webgl-186263</a></p>
</blockquote>
<p>socket.io 검색했을 때 나오는 두번째 버전으로 받았다.
예전에는 무료버전도 있었던거 같은데,,,</p>
<p>어쨌든 unity 켜서 window → package manager 열어서 import 해준다.
설치된 파일 중 <code>SocketIOCommunicator</code> 의 함수들을 사용할거다.</p>
<p>서버와 연결하는 스크립드에 다음과 같이 작성해준다</p>
<pre><code class="language-csharp">using Firesplash.UnityAssets.SocketIO;

public SocketIOCommunicator sioCom;

// 게임 실행 할 때 서버 연결
private void Start()
{
    sioCom = GetComponent&lt;SocketIOCommunicator&gt;();
    initSocket();
}</code></pre>
<p><code>sioCom</code>은 socketIOCommunicator를 줄인걸로 원하는대로 설정해주면 된다.</p>
<p><code>initSocket()</code> 함수는 다음과 같이 작성</p>
<pre><code class="language-csharp">void initSocket()
{
    sioCom.Instance.Connect();

    //연결
    sioCom.Instance.On(&quot;connect&quot;, (string jsondata) =&gt;
    {
        Debug.Log(&quot;== Connected ============&quot;);
    });
}</code></pre>
<p><code>sioCom.Instance.Connect();</code> 함수를 사용해 서버랑 연결해줌</p>
<br>

<p>연결하는 서버의 주소는
<img src="https://velog.velcdn.com/images/dev_ming/post/0226f8a6-e657-4dde-9aa0-f44101de46b4/image.png" alt="">
다음과 같이 서버 오브젝트에 (Server Manager 등) Socket IO Communicator 스크립트를 넣어 Address 부분에 서버 주소를 넣어주면 된다.</p>
<p>밑의 체크박스는 보안연결(HTTPS) 하는 경우와 시작할 때 오토 커넥션을 원하는 경우에 맞춰서 체크해주면 된다.</p>
<br>

<h2 id="json-데이터-사용">JSON 데이터 사용</h2>
<p>서버와 주고 받는 데이터는 JSON 데이터의 형식으로 사용할 것이다.</p>
<p>나같은 경우에는 직접 라이브러리를 받아서 사용했지만
<a href="https://github.com/mtschoen/JSONObject">https://github.com/mtschoen/JSONObject</a>
(JSON은 라이브러리가 워낙 많아서)</p>
<p>asset store에 검색해도 많이 나오기 때문에 원하는 것으로 다운받아서 적용하면 될 듯 하다.</p>
<br>

<p>기본적으로 JSONObject data 만드는 법</p>
<pre><code class="language-csharp">JSONObject data = new JSONObject(JSONObject.Type.OBJECT);
data.AddField(&quot;room_id&quot;, room_id);</code></pre>
<p>이런식으로 데이터를 만들고 원하는 데이터를 추가해주면 된다.</p>
<p><code>AddField()</code>의 경우 같은 역할을 하는 함수가 다를 수 있으니 라이브러리 참고해서 데이터 추가해주면 된다.
앞의 data 생성부분도 기본 포멧인 <code>JSONObject data = new JSONObject();</code> 는 같겠지만 파라미터에 아무것도 안 들어 갈 수도 있고 지금처럼 형식이 지정될 수도 있음.
참고로 Object 형식 뿐만 아니라 Array와 같은 형식도 있음.</p>
<br>

<h2 id="신호데이터-전송">신호(데이터) 전송</h2>
<p>서버상의 데이터 주고받는 함수들은 위에서 만들어 놓았던 <code>initSocket()</code> 안에서 호출하면 된다.</p>
<p>데이터를 서버에 전송하고 싶은 경우에는</p>
<pre><code class="language-csharp">JSONObject data = new JSONObject(JSONObject.Type.OBJECT);
data.AddField(&quot;id&quot;, id);
data.AddField(&quot;password&quot;, password);
sioCom.Instance.Emit(&quot;CheckLogin&quot;, data.Print());</code></pre>
<p>이런식으로 JSON 데이터 만들어서 신호 + 데이터의 형식으로 보내주면 된다.
신호를 보내는 함수는 <code>Emit()</code> 함수 사용
<code>Emit()</code>안의 인자로 신호랑 데이터를 넣어주면 서버로 전송됨</p>
<p>데이터 없이 신호만 보내는 것도 가능하다.</p>
<br>

<h2 id="신호데이터-수신">신호(데이터) 수신</h2>
<p>서버가 보내는 신호랑 데이터를 받아오려면</p>
<pre><code class="language-csharp">sioCom.Instance.On(&quot;CheckLogin&quot;, (string jsonData) =&gt;
{
    JSONObject data = new JSONObject(jsonData);
    if (data.GetField(&quot;success&quot;).b)
    {
        GoToPage(&quot;2_SelectChannel&quot;);
    }
});</code></pre>
<p>이런식으로 <code>On()</code> 함수를 사용해서 받아오는 신호, 데이터를 가져오면 된다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] 타입스크립트를 사용해야 하는 이유]]></title>
            <link>https://velog.io/@dev_ming/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@dev_ming/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%B4%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Mon, 24 Apr 2023 08:09:24 GMT</pubDate>
            <description><![CDATA[<p>모던 프론트 웹개발자로 살아남기 힘든 세상이 왔다.</p>
<p><img src="https://velog.velcdn.com/images/dev_ming/post/43d0ad40-39b3-44c2-bc69-c4048b628ce9/image.png" alt=""><em>출처: 코딩애플</em>
<em>이건 별개의 내용인데 벨로그는 이미지 캡션 기능이 없는게 너무 불편한 것 같다</em></p>
<br>
프론트 개발자로 살아남기 위해 위에 기술된 스택을 기본적으로 알고 있어야 하는 세상이다. 단순히 프론트 개발만 하는 것이 아닌, 백엔드 스킬도 어느 정도 알고 있어야 하는 것.

<p>나는 프론트 중심이긴하지만 풀스택으로 일해 왔고, 덕분에 백엔드에 대한 이해는 보유하고 있다.</p>
<p>하지만 문제는 너무 빠르게 변하는 프론트 시장,, 
요즘 많은 채용공고들을 보면 변화하는 시장에 맞춰서 프론트 개발자들에게 요구하는 스택이 많아졌다. 그 중에서도 대표적인 스택이 <strong>ES6, TypeScript, React, Vue, Next.js, Node.js, RESTful API</strong> 등등.. </p>
<p>그중 요새는 JS보다 TS를 자주 이용하고 TS가 가능한 사람을 채용하는 추세이다. 
따라서 난 살아남기 위해,, TypeScript를 공부하기 시작,, 흠냐..</p>
<p>React랑 Node.js, ES6는 자주 사용하기 때문에 이번에는 TS, Vue.js, Next.js를 사용해서 프로젝트를 하나 만들어 볼까 한다. 변화되는 시장에서 살아남기 위해서는 기업이 요구하는 기술스택을 어느 정도는 익히고 있어야 한다고 생각하기 때문이다. </p>
<br>

<h2 id="why-typescript">Why TypeScript?</h2>
<p>JavaScript의 장점을 꼽자면 누구나 편리함을 꼽을 것이다. JS는 기존의 웹 동적 프로그래밍의 기능을 넘어서서 현재는 Node.js, Deno와 같은 런타임 환경을 통해 서버도 개발할 수 있는, 많은 개발자들에게 사랑받는 언어 중 하나로 자리매김 했다.
간단하고 빠르게 개발할 수 있다는 장점이 있는 JS는 그러한 명성에 걸맞게 <strong>Dynamic Typing</strong>이라는 기능을 제공한다. 이는 데이터에 따로 타입을 지정해주지 않아도 컴퓨터가 알아서 인식을 해서 기능을 제공해 주는 것이다. </p>
<pre><code>int a = 1; // c와 같은 언어에서는 이런식으로 변수에 데이터 타입을 할당해주어야 한다. 

1 + 2 // JS에서는 알아서 숫자로 인식하여 계산을 수행해준다.</code></pre><br>

<p><em>그럼 이렇게 편리한데 왜 TypeScript씀?</em></p>
<p>JS는 자유도와 유연성이 높기 때문에 빠르게 프로젝트를 구성하고 만들 수 있지만, 이러한 높은 자유도는 오히려 프로젝트의 사이즈가 커질 수록 독이 된다. 
예를 들어 애를 너무 풀어두고 키우면 버르장머리가 없어지듯이 어느 정도의 규제는 필요하다는 것 ㅎ;
TS는 타입형에 따라서 수많은 세세한 에러들을 잡아주기 때문에 발생할 수 있는 에러를 미연에 방지할 수 있다는 장점이 있다. </p>
<p>TypeScript는 기본적으로 JavaScript와 같은 문법 체계를 지닌다. 즉 JS에 데이터 타입을 지정해줘서 Dynamic Typing에서 Static Typing으로 바꾼 언어라고 볼 수 있음</p>
<p><img src="https://velog.velcdn.com/images/dev_ming/post/b365663e-93e5-43cc-b25e-b4483a9067b2/image.png" alt=""></p>
<p>타입관련 에러들을 모두 잡아주기 때문에 코드 자체의 정확성이 올라간다. 
예를 들어, JS 코딩하다가 다들 한번씩 봤을 <code>&#39;undefined&#39; is not a function.</code> 이런거 안 볼 수 있다는 소리.</p>
<p><img src="https://velog.velcdn.com/images/dev_ming/post/aa43bdf1-cdb7-4450-8183-0d49041f77c3/image.png" alt=""></p>
<blockquote>
<p><a href="https://madnight.github.io/githut/#/pull_requests/2021/2">https://madnight.github.io/githut/#/pull_requests/2021/2</a></p>
</blockquote>
<p>TypeScript는 하락세를 보이는 JavaScript, PHP와는 다르게 지속적인 성장세를 보이고 있다. 웹 개발을 하기 위해서 선택이 아닌 필수가 되어간다는 말이다. </p>
<br>

<h2 id="typescript-사용법">TypeScript 사용법</h2>
<p>기본적으로 자바스크립트의 베이스 위에 변수의 타입을 지정해 주는 것이라고 보면 쉽게 익힐 수 있다.</p>
<pre><code class="language-typescript">const message: string = &#39;hello world&#39;;
console.log(message);</code></pre>
<p>이런식으로 <code>message</code>를 <code>string</code> 타입으로 지정해주면 <code>message</code>에 <code>string</code> 타입 외의 값을 넣으면 에러가 발생하게 된다.
<br></p>
<pre><code class="language-typescript">function my_sum(a: number, b: number) {
    return a + b;
    }

let a = 4; 
let b = &quot;5&quot;;

my_sum(a, b);</code></pre>
<p>다음과 같이 <code>a</code>와 <code>b</code>의 타입을 <code>number</code>로 설정해준 경우, <code>b</code>에 <code>string</code> 타입을 넣게 되면 <code>Argument of type &#39;string&#39; is not assignable to parameter of type &#39;number&#39;.</code>라는 에러를 제공하게 된다. </p>
<p>이런 식으로 자바스크립트에 타입을 지정하는 것이 기본이라고 보면 된다.
앞으로 타입스크립트를 사용해서 프로젝트를 진행하며 서술해 볼 예정.</p>
<br>

<hr>
<p><strong>참고</strong>
<a href="https://serokell.io/blog/why-typescript">https://serokell.io/blog/why-typescript</a>
<a href="https://www.youtube.com/watch?v=xkpcNolC270">https://www.youtube.com/watch?v=xkpcNolC270</a>
<a href="https://www.typescriptlang.org/docs/handbook/intro.html">https://www.typescriptlang.org/docs/handbook/intro.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 프로그래머스 - H-Index]]></title>
            <link>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-H-Index</link>
            <guid>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-H-Index</guid>
            <pubDate>Tue, 11 Apr 2023 08:22:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="h-index">H-Index</h3>
</blockquote>
<h4 id="문제-설명">문제 설명</h4>
<p>H-Index는 과학자의 생산성과 영향력을 나타내는 지표입니다. 어느 과학자의 H-Index를 나타내는 값인 h를 구하려고 합니다. 위키백과1에 따르면, H-Index는 다음과 같이 구합니다.</p>
<blockquote>
</blockquote>
<p>어떤 과학자가 발표한 논문 n편 중, h번 이상 인용된 논문이 h편 이상이고 나머지 논문이 h번 이하 인용되었다면 h의 최댓값이 이 과학자의 H-Index입니다.</p>
<blockquote>
</blockquote>
<p>어떤 과학자가 발표한 논문의 인용 횟수를 담은 배열 citations가 매개변수로 주어질 때, 이 과학자의 H-Index를 return 하도록 solution 함수를 작성해주세요.</p>
<h4 id="제한사항">제한사항</h4>
<ul>
<li>과학자가 발표한 논문의 수는 1편 이상 1,000편 이하입니다.</li>
<li>논문별 인용 횟수는 0회 이상 10,000회 이하입니다.<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>citations</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>[3, 0, 6, 1, 5]</td>
<td>3</td>
</tr>
<tr>
<td>#### 입출력 예 설명</td>
<td></td>
</tr>
<tr>
<td>이 과학자가 발표한 논문의 수는 5편이고, 그중 3편의 논문은 3회 이상 인용되었습니다. 그리고 나머지 2편의 논문은 3회 이하 인용되었기 때문에 이 과학자의 H-Index는 3입니다.</td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<br>

<h3 id="⭐처음에-구현한-코드">⭐처음에 구현한 코드</h3>
<pre><code class="language-python">def solution(citations):
    answer = 0
    citations.sort()
    for i in range(len(citations)):
        if citations[i] &lt;= len(citations[i:]) and len(citations[:i]) &lt;= citations[i]:
            answer = citations[i]
    return answer</code></pre>
<p>문제를 이해하기 너무 어려웠다,, 테스트케이스도 하나밖에 없고,, 결국에는 인용된 갯수가 인용된 횟수보다 크거나 같을 때 인용된 횟수를 정답으로 출력했다.
<br></p>
<h3 id="🤔오답노트">🤔오답노트</h3>
<p><img src="https://velog.velcdn.com/images/dev_ming/post/8d68c22a-7226-46f0-9859-40f17bd80fed/image.png" alt="">
근데 거하게 틀림.
뭐지? 뭐가 문제지?
그리고 나는 11번이랑 16번만 맞았는데 사람들은 11번이랑 16번 케이스만 틀린 사람들이 많다고 해서 더 멘붕이 왔다. 흐엥</p>
<br>

<h3 id="✔수정코드">✔수정코드</h3>
<pre><code class="language-python">def solution(citations):
    answer = 0
    citations.sort(reverse=True)
    for i in range(len(citations)):
        if citations[i] &gt;= i+1:
            answer = i+1

    return answer</code></pre>
<p>이런식으로 푸니까 통과되었다. 하지만 왜.. i+1이 답이 되는지 잘 모르겠음. h-index 자체가 어려운 듯 하다. 어쨌든 그냥 정렬보다는 reverse로 정렬해서 위에와 같이 돌렸는데 <code>citation[i]</code>로 하니까 답이 안됐는데 <code>i+1</code>로 하니까 답이 됐다고 나오네,,</p>
<p>ㅜㅜ.. 다른것보다 저렇게 문제 자체가 이해하기 어려운 문제는 좀 안나왔으면 좋겠다,,
<br></p>
<h3 id="🤓다른-코드">🤓다른 코드</h3>
<pre><code class="language-python">def solution(citations):
    citations.sort(reverse=True)
    answer = max(map(min, enumerate(citations, start=1)))
    return answer</code></pre>
<p>고인물 답변;;</p>
<p><code>enumerate()</code> 함수를 적극적으로 활용해야겠다. <code>index</code>와 <code>value</code>를 한번에 사용해서 <code>for</code>문을 돌리고 싶다면 까먹지 말기!!</p>
<p>저 코드의 풀이는</p>
<blockquote>
</blockquote>
<p>sort로 정렬해서 가장 큰값부터 작은값으로 정렬한후, enumerate로 (index, value)형태로 묶는다. 그리고 최댓값(start = 1)부터 각 value에 대해 최솟값 value의 값을 min으로 추출하고, 이 추출된 값은 enumerate가 끝나는 citations 리스트의 크기에 해당하는 갯수가 나온다. 이들을 map으로 묶으면, 한 value의 입장에서 보는 최솟값 value의 집합이 나온다. 즉 h값들의 집합이나온다. h값중 최대값을 max로 뽑아서 출력하면 된다.</p>
<blockquote>
<p>1)min(index,value) 부분은 가능할 수 있는 모든 h-index를 추출하는 부분 2) max(<del>) 값은 가능할 수 있는 모든 h-index 중 가장 큰 값을 추출하는 부분으로 생각하시면 됩니다. 예를들어 [6, 5, 4, 1, 0]의 경우에선 min</del> 부분은 min(1, 6), min(2, 5), min(3, 4), min(4, 1), min(5, 0), 즉 해당 인용수 이상의 논문개수와 해당 논문의 인용수 중 더 작은 숫자를 고르는 작업을 하고(h-index로 가능한 숫자 추출), max~부분은 앞에서 골라진 (1, 2, 3, 1, 0) 중 가장 큰 숫자를 뽑아 실제 h-index를 구하는 방법입니다.</p>
</blockquote>
<p>이렇다고 하네요.. 댓글에서 가져왔슴다.
어떻게 저런 방법을 생각하는지,,, 대단하다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React, Node.js] 버튼 중복 클릭 / 제출 방지하기]]></title>
            <link>https://velog.io/@dev_ming/React-Node.js-%EB%B2%84%ED%8A%BC-%EC%A4%91%EB%B3%B5-%ED%81%B4%EB%A6%AD-%EC%A0%9C%EC%B6%9C-%EB%B0%A9%EC%A7%80%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_ming/React-Node.js-%EB%B2%84%ED%8A%BC-%EC%A4%91%EB%B3%B5-%ED%81%B4%EB%A6%AD-%EC%A0%9C%EC%B6%9C-%EB%B0%A9%EC%A7%80%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 11 Apr 2023 03:15:51 GMT</pubDate>
            <description><![CDATA[<p>개발자들은 프로그램의 구조를 알기 때문에 버그가 날만한 행동은 무의식적으로 피하게 된다. 그러다보니 유저가 사용하는 경우에서 많은 버그에 맞닥뜨리게 되는데,,,</p>
<p>오늘의 버그는 버튼 중복 클릭으로 인한 중복 제출 버그입니다🐛</p>
<hr>
<h3 id="수정-전-상황">수정 전 상황</h3>
<p>해당 버튼을 클릭하게 되면 서버로 신호가 가고 다시 신호가 넘어오면 페이지가 넘어가는 식으로 개발한 케이스. 하지만 페이지가 넘어가기 전 짧은 순간에 버튼을 여러 번 누르는 경우가 있었다. 이에 따라 소켓 호출은 누른만큼 서버로 넘어가게 됨,, 😥 눈물만 줄줄</p>
<p>하지만 울어서 해결되는 것은 없으니 예외처리를 구현해보자.</p>
<br>

<h2 id="방법1-disable-the-submit-button-after-the-first-click">방법1. Disable the submit button after the first click</h2>
<p>해당 버튼을 제출을 한번 누르고 나면 disable 시키는 방법이다. 적절한 상황에서 사용하면 가장 간편하고 좋은 방법이지만 여러 케이스에서 단순히 버튼 클릭만 막는다고 해결되진 않는다.. 어쨌든</p>
<p>react hook을 사용하는 방법</p>
<p><strong>1. 버튼의 현재 상태를 저장하는 <code>useState()</code>를 선언한다.</strong></p>
<pre><code class="language-javascript">const [isSubmitting, setIsSubmitting] = useState(false);</code></pre>
<p><strong>2. 버튼의 <code>disabled</code> 속성을 위에서 선언한 상태로 설정해준다</strong></p>
<pre><code class="language-javascript">&lt;button type=&quot;submit&quot; disabled={isSubmitting}&gt;
  Submit
&lt;/button&gt;</code></pre>
<p><strong>3. submit handler에서 버튼을 누르면 <code>isSubmitting</code>의 값을 <code>true</code>로 바꾸게 구현해준다.</strong></p>
<pre><code class="language-javascript">const handleSubmit = async (event) =&gt; {
  event.preventDefault();
  setIsSubmitting(true);

  // Your form submission logic here

  // After form submission is complete, set `isSubmitting` back to `false`:
  setIsSubmitting(false);
};</code></pre>
<p>submit의 로직이 완료되면 다시 <code>false</code>로 설정되어서 버튼을 클릭 할 수 있게 되는 방법.</p>
<br>

<blockquote>
</blockquote>
<h4 id="🌿-handelsubmit-안에서-state-값에-따라서-return-하는-법">🌿 <code>handelSubmit</code> 안에서 <code>state</code> 값에 따라서 return 하는 법</h4>
<p><code>handleSubmit</code> 안에서 <code>isSubmitting</code> state 값이 <code>true</code>라면 바로 return을 해서 함수가 동작하지 않게 하는 방법도 있다.</p>
<pre><code class="language-javascript">const handleSubmit = async (event) =&gt; {
  event.preventDefault();

  if (isSubmitting) {
    return;
  }

  setIsSubmitting(true);

  // Your form submission logic here

  // After form submission is complete, set `isSubmitting` back to `false`:
  setIsSubmitting(false);
};</code></pre>
<p>이런식으로 코드를 짜면 한번 버튼을 누르고 해당 submit이 완료될 때 까지 다시 누르게 된다면 <code>handleSubmit()</code>이 실행되지 않고 바로 return됨</p>
<br>

<h2 id="방법2-token을-생성해서-사용자를-판단하고-서버에서-제출이-완료되었다면-error를-return하는-방식">방법2. token을 생성해서 사용자를 판단하고 서버에서 제출이 완료되었다면 error를 return하는 방식</h2>
<p>유저가 2명 이상이 같은 버튼을 눌러서 중복 제출이 발생 할 때 사용할 수 있는 방식이다. </p>
<br>

<blockquote>
<p><strong>🖥️ HTTP API 방식</strong></p>
</blockquote>
<h4 id="1-server-nodejs">1. Server (Node.js)</h4>
<pre><code class="language-javascript">const express = require(&#39;express&#39;);
const { v4: uuidv4 } = require(&#39;uuid&#39;);

const app = express();
const PORT = process.env.PORT || 3000;

// Middleware to parse JSON request bodies
app.use(express.json());

// In-memory store to keep track of tokens and form data
const formDataStore = {};

// Route to get a new form token
app.get(&#39;/api/form-token&#39;, (req, res) =&gt; {
  const newToken = uuidv4();
  formDataStore[newToken] = null; // Initialize the form data as null
  res.json({ token: newToken });
});

// Route to submit the form
app.post(&#39;/api/submit-form&#39;, (req, res) =&gt; {
  const { token, formData } = req.body;

  if (!formDataStore.hasOwnProperty(token)) {
    return res.status(400).json({ error: &#39;Invalid token&#39; });
  }

  if (formDataStore[token] !== null) {
    return res.status(409).json({ error: &#39;Form already submitted&#39; });
  }

  formDataStore[token] = formData; // Save the form data

  res.json({ message: &#39;Form submitted successfully&#39; });
});

app.listen(PORT, () =&gt; {
  console.log(`Server running on port ${PORT}`);
});</code></pre>
<p>2가지 API 루트를 만들어서 사용한다.</p>
<ul>
<li><code>/api/form-token</code>: form을 위한 새로운 token을 반환</li>
<li><code>/api/submit-form</code>: data와 token을 받고 토큰이 유효하고 이전에 사용된 적이 없는 경우에 제출을 처리</li>
</ul>
<p><code>formDataStore</code>에서 이미 해당 값이 존재한다면 이미 제출되었다는 에러를 발생시킨다. </p>
<h4 id="2-client-react-app">2. Client (react-app)</h4>
<pre><code class="language-javascript">import { useState, useEffect } from &#39;react&#39;;

const MyForm = () =&gt; {
  const [formToken, setFormToken] = useState(null);
  const [formData, setFormData] = useState({}); // Your form data here

  // Fetch a new token when the component is mounted
  useEffect(() =&gt; {
    const fetchFormToken = async () =&gt; {
      const response = await fetch(&#39;/api/form-token&#39;);
      const data = await response.json();
      setFormToken(data.token);
    };

    fetchFormToken();
  }, []);

  const handleSubmit = async (event) =&gt; {
    event.preventDefault();

    const response = await fetch(&#39;/api/submit-form&#39;, {
      method: &#39;POST&#39;,
      headers: {
        &#39;Content-Type&#39;: &#39;application/json&#39;,
      },
      body: JSON.stringify({ token: formToken, formData }),
    });

    const data = await response.json();

    if (response.status === 409) {
      // Handle form submission conflict (already submitted)
      console.error(&#39;Form already submitted by someone else&#39;);
    } else {
      // Handle form submission success
      console.log(&#39;Form submitted successfully&#39;);
    }
  };

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      {/* Your form fields here */}
      &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
    &lt;/form&gt;
  );
};

export default MyForm;</code></pre>
<p>해당 제출 페이지가 랜더링 될 때 <code>/api/form-token</code>을 <code>fetch</code>해서 새로운 토큰을 받고 제출을 할 때 해당 토큰과 데이터를 같이 넘겨주는 방식으로 구현</p>
<br>

<blockquote>
<p><strong>🖥️ WebSocket 방식</strong></p>
</blockquote>
<h4 id="1-server-nodejs-1">1. Server (Node.js)</h4>
<pre><code class="language-javascript">const express = require(&#39;express&#39;);
const { Server } = require(&#39;socket.io&#39;);
const { v4: uuidv4 } = require(&#39;uuid&#39;);
const http = require(&#39;http&#39;);

const app = express();
const server = http.createServer(app);
const io = new Server(server);

const PORT = process.env.PORT || 3000;

// In-memory store to keep track of tokens and form data
const formDataStore = {};

io.on(&#39;connection&#39;, (socket) =&gt; {
  console.log(&#39;A user connected&#39;);

  // Send a new unique token to the client
  const newToken = uuidv4();
  formDataStore[newToken] = null; // Initialize the form data as null
  socket.emit(&#39;form-token&#39;, newToken);

  // Handle form submission
  socket.on(&#39;submit-form&#39;, ({ token, formData }) =&gt; {
    if (!formDataStore.hasOwnProperty(token)) {
      return socket.emit(&#39;submit-result&#39;, { success: false, error: &#39;Invalid token&#39; });
    }

    if (formDataStore[token] !== null) {
      return socket.emit(&#39;submit-result&#39;, { success: false, error: &#39;Form already submitted&#39; });
    }

    formDataStore[token] = formData; // Save the form data

    socket.emit(&#39;submit-result&#39;, { success: true, message: &#39;Form submitted successfully&#39; });
  });

  socket.on(&#39;disconnect&#39;, () =&gt; {
    console.log(&#39;A user disconnected&#39;);
  });
});

server.listen(PORT, () =&gt; {
  console.log(`Server running on port ${PORT}`);
});</code></pre>
<h4 id="2-client-react-app-1">2. Client (react-app)</h4>
<pre><code class="language-javascript">import { useState, useEffect } from &#39;react&#39;;
import { io } from &#39;socket.io-client&#39;;

const MyForm = () =&gt; {
  const [socket, setSocket] = useState(null);
  const [formToken, setFormToken] = useState(null);
  const [formData, setFormData] = useState({}); // Your form data here

  // Connect to the WebSocket server when the component is mounted
  useEffect(() =&gt; {
    const socket = io(&#39;http://localhost:3000&#39;);
    setSocket(socket);

    socket.on(&#39;form-token&#39;, (token) =&gt; {
      setFormToken(token);
    });

    socket.on(&#39;submit-result&#39;, ({ success, message, error }) =&gt; {
      if (success) {
        console.log(message);
      } else {
        console.error(error);
      }
    });

    return () =&gt; {
      socket.disconnect();
    };
  }, []);

  const handleSubmit = (event) =&gt; {
    event.preventDefault();

    if (socket &amp;&amp; formToken) {
      socket.emit(&#39;submit-form&#39;, { token: formToken, formData });
    }
  };

  return (
    &lt;form onSubmit={handleSubmit}&gt;
      {/* Your form fields here */}
      &lt;button type=&quot;submit&quot;&gt;Submit&lt;/button&gt;
    &lt;/form&gt;
  );
};

export default MyForm;</code></pre>
<p>위의 HTTP API 방식과 같은 방식이다. 통신 구현 방법이 다를 뿐이지 같은 내용을 다루고 있음.</p>
<br>

<h3 id="💡-uuid란">💡 UUID란?</h3>
<p>그렇다면 위의 코드에서 token을 발급하는데 사용되는 UUID는 무엇일까?</p>
<blockquote>
</blockquote>
<p>UUID는 <code>Universally Unique Identifier</code>의 약자. 분산 시스템 또는 데이터베이스에서 개체 또는 레코드를 고유하게 식별하는 데 사용되는 128비트 숫자로, 고유하게 설계되어 충돌(동일한 식별자를 가진 두 개체)을 피해야 하는 응용 프로그램에서 키 또는 식별자로 사용하기에 적합하다.</p>
<p>UUID는 다음과 같은 형식으로 지정됨</p>
<pre><code>xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx</code></pre><p>여기서 <code>x</code>는 16진수(0-9 또는 A-F)를 나타내고 <code>M</code>은 UUID 버전(1-5)을 나타내며 <code>N</code>은 UUID 변형을 나타내는 값이다.</p>
<p>UUID는 총 5가지 버전이 있다.</p>
<ol>
<li>v1: 시간 기반(타임스탬프 및 MAC 주소 사용)</li>
<li>v2: DCE 보안(버전 1과 유사하지만 추가 POSIX UID/GID 데이터 포함)</li>
<li>v3: MD5 해싱을 사용한 이름 기반</li>
<li>v4: 임의(암호화 보안 난수 사용)</li>
<li>v5: SHA-1 해싱을 사용한 이름 기반</li>
</ol>
<p>일반적으로 v4가 랜덤값 기반이라 자주 사용된다.</p>
<br>

<p>node에서는 uuid관련 라이브러리를 제공한다.</p>
<pre><code class="language-bash">npm install uuid</code></pre>
<p>를 사용해서 설치할 수 있음
<br></p>
<p>v4 uuid를 사용하고자 한다면 다음과 같은 코드를 상단에 추가하면 된다.</p>
<pre><code class="language-javascript">const { v4: uuidv4 } = require(&#39;uuid&#39;);
const uniqueId = uuidv4();</code></pre>
<p>UUID는 고유한 토큰 역할을 하므로 양식이 이미 제출되었는지 여부를 UUID를 통해 판단하면 쉽게 확인할 수 있다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Array vs LinkedList]]></title>
            <link>https://velog.io/@dev_ming/CS-Array-vs-LinkedList</link>
            <guid>https://velog.io/@dev_ming/CS-Array-vs-LinkedList</guid>
            <pubDate>Sat, 08 Apr 2023 08:25:52 GMT</pubDate>
            <description><![CDATA[<p>📚 본 포스팅은 <strong>CS 완전정복</strong> 강의를 수강하고 적는 복습 포스팅입니다.</p>
<h3 id="1-array">1. Array</h3>
<p>연관된 데이터를 메모리상에 연속적이며 순차적으로 미리 할당된 크기만큼 저장하는 자료구조</p>
<p>여기서 중요한거는!!</p>
<blockquote>
</blockquote>
<ol>
<li>메모리상에 연속적으로</li>
<li>미리 할당된 데이터만큼</li>
</ol>
<p>이라는 두가지 포인트가 중요하다.</p>
<p>Array는</p>
<ul>
<li>고정된 자장공간</li>
<li>순차적 데이터 저장</li>
</ul>
<p>이라는 특징을 가지고 있음</p>
<p>컴퓨터의 메모리의 일정 부분을 array 요소 하나의 크기로 할당하고, 그 시점부터 연속적으로 array의 크기만큼 할당한다.</p>
<h4 id="array-operation들의-time-complexity">Array Operation들의 Time Complexity</h4>
<ol>
<li><strong>조회 -&gt; <code>O(1)</code> random Access</strong>
특정 인덱스의 값 조회는 계산으로 바로 접근 가능하기 때문에 다음과 같은 시간복잡도를 가진다.</li>
</ol>
<p><em>ex) array의 한 요소에 메모리 4개가 할당되었고 4번째 index의 값을 알고싶다면?
첫 index + 4(메모리크기) x 3(index)
이런식으로 계산해서 접근 후 조회한다.</em></p>
<ol start="2">
<li><p><strong>마지막 인덱스 데이터 추가/삭제 (<code>append()</code>, <code>delete()</code>) -&gt; <code>O(1)</code></strong>
그냥 마지막 메모리에 데이터를 넣기만 하면 되기 때문이다.</p>
</li>
<li><p><strong>삽입 / 삭제 -&gt; <code>O(n)</code></strong>
삭제 / 삽입을 한 후 남은 데이터들을 한 칸씩 옮겨줘야하기 때문에 n개의 배열이라면 O(n)의 시간복잡도가 발생하게 된다.</p>
</li>
<li><p><strong>탐색 -&gt; <code>O(n)</code></strong>
일일이 방문해서 확인하기 때문에 O(n)의 시간복잡도가 발생하게 된다.</p>
</li>
</ol>
<br>

<p>다음과 같은 특징을 바탕으로 장점과 단점이 있다.
<strong>장점: 조회랑 데이터 추가의 속도가 빠르다
단점: 선언시에 크기를 미리 정해야하고 이에 따라 메모리 낭비나 추가적 overhead와 같은 문제가 발생할 수 있다.</strong> </p>
<h3 id="2-dynamic-array">2. Dynamic Array</h3>
<p>Array의 fixed size라는 한계점을 보완하기 위해 고안된 Array.
저장공간이 가득 차게 되면 resize를 하여 유동적으로 size를 조절해 데이터를 저장하는 자료구조이다.</p>
<p>중요하게 볼 것은 두가지</p>
<blockquote>
<ol>
<li>resize 방식</li>
<li>데이터를 추가할 때 시간복잡도</li>
</ol>
</blockquote>
<p><strong>resize 방식</strong>
기존에 할당된 메모리 이상으로 데이터가 들어온다면?
기존의 메모리보다 크게 메모리를 할당한 배열을 선언한 후 그 배열로 모든 데이터를 옮긴다.
대표적으로는 기존 Array Size의 2배를 할당하는 Doubling 방법이 있다.</p>
<p><em>Doubling (더블링)</em>
기존 배열 사이즈보다 2배 큰 배열을 선언함</p>
<p>큰 배열을 선언하고 기존의 배열의 모든 데이터를 옮겨야 하기 때문에 <code>O(n)</code>의 시간복잡도를 가진다.</p>
<p><strong>데이터를 추가할 때의 시간복잡도</strong>
Dynamic Array도 Array이기 때문에 결국 데이터를 추가할때는 <code>O(1)</code>의 시간복잡도를 가진다.
하지만 resize의 시간복잡도는 <code>O(n)</code>
그렇다면 데이터 추가의 시간복잡도는?</p>
<p>결론은 <code>O(1)</code> 이다.
데이터를 추가할 때 resize가 일어나는 경우는 아주 가끔 발생한다. 따라서 주로 <code>O(1)</code>의 시간 복잡도를 가지게 되는것. </p>
<p>이를 <code>amortized O(1)</code>이라고 한다. 
아주 가끔 발생하는 <code>O(n)</code>의 시간복잡도를 자주 발생하는 <code>O(1)</code>이 나눠가지면서 <code>O(1)</code>이 된다고 생각하면 된다. 바닷물에 식초를 빠뜨린다고 해서 바닷물이 셔지지는 않고 여전히 짠 그런거일려나..? ㅎ</p>
<h4 id="dynamic-array-vs-linked-list">Dynamic Array vs Linked List</h4>
<p>Dynamic Array를 Linked List와 비교했을 때 장단점은 무엇일까?</p>
<p><strong>장점</strong></p>
<ol>
<li>Dynamic Array가 Linked List에 비해 데이터 접근과 할당이 <code>O(1)</code>로 빠르다. index 접근법이 연산으로 이루어지기 때문 (random access).</li>
<li>데이터를 맨 뒤에 추가/삭제가 <code>O(1)</code>로 상대적으로 빠르다.</li>
</ol>
<p><strong>단점</strong></p>
<ol>
<li>맨 끝이 아닌 곳에 데이터를 삽입/삭제 할 때는 <code>O(n)</code>으로 느리다. 데이터들을 shift 하기 때문.</li>
<li>resize시 현저히 낮은 performance 발생. 데이터를 다 옮겨야 하기 때문.</li>
<li>메모리공간을 resize 시에 넉넉히 할당받는데 이렇게 되면 사용하지 않고 남는 메모리 공간이 발생 할 수 있다. </li>
</ol>
<h3 id="3-linked-list">3. Linked List</h3>
<p>node 구조체로 이루어져 있는 자료구조. node에는 데이터값과 다음 node의 address가 저장되어 있다. 물리적 메모리 상에서는 비연속적으로 나타나지만 각각의 node가 다음 node의 address를 가리킴으로써 논리적 연속성을 가진 자료구조이다.</p>
<p>중요한 포인트</p>
<blockquote>
<ol>
<li>node</li>
<li>물리적 메모리는 비연속적</li>
<li>논리적 연속성</li>
</ol>
</blockquote>
<p>Linked List는 tree, graph 등 다른 자료구조에서 자주 사용되는 기본이다. 설명 포인트는 메모리상에서는 불연속적이지만 node의 address값을 가리키기 때문에 논리적 연속성을 보장한다.
또한 데이터가 추가되는 시점에 메모리를 할당하기 때문에 메모리를 좀 더 효율적으로 사용이 가능하다. 
node에는 데이터 값과 다음 node의 address가 저장되어 있는데 마지막 node가 가리키는 address는 <code>0x00000</code>로 <code>null</code>값이다.</p>
<h4 id="논리적-연속성">논리적 연속성</h4>
<p>각 node들은 next address 정보를 가지고 있기 때문에 논리적 연속성을 가지고 있고 연결되어 있다. Array는 이와는 다르게 연속성을 위해 메모리에 순차적으로 저장된다. Linked List는 논리적 연속성으로 메모리에 순차적으로 저장될 필요가 없기 때문에 메모리 사용이 더 자유롭고 효율적이지만 각각의 데이터가 데이터값만 가지고 있는 것이 아니라 address도 추가로 저장되기 때문에 각 데이터가 차지하는 메모리는 더 크다.</p>
<h4 id="데이터-삽입삭제">데이터 삽입/삭제</h4>
<p>Linked List에서 데이터의 삽입과 삭제는 둘다 node의 address 값만 변경해주면 된다.
삽입을 원하는 경우는 원하는 위치의 앞의 노드의 address를 삽입하는 data의 address로 변경해주면 되고 삭제를 원하는 경우는 삭제하는 노드의 앞의 노드의 address를 뒤의 address로 변경해주면 된다. 따라서 시간복잡도는 <code>O(1)</code>이 된다.</p>
<h4 id="데이터-access-접근--search">데이터 access (접근) / search</h4>
<p>데이터 접근의 시간복잡도는 <code>O(n)</code>이다. Linked List는 데이터의 순차적 접근만이 가능하기 때문이다. n번째의 데이터가 알고 싶다면 처음부터 n까지의 address를 따라가야 한다. search도 같은 방식으로 작동한다.</p>
<h3 id="4-array-vs-linked-list">4. Array vs Linked List?</h3>
<p>Array는 메모리상에 데이터가 연속적으로 저장된다. Linked List는 연속적으로 저장되진 않지만 논리적 연속성을 띈다. 이에 따라 각 operation의 시간복잡도가 다르게 나타난다. </p>
<table>
<thead>
<tr>
<th></th>
<th>Array</th>
<th>Linked List</th>
</tr>
</thead>
<tbody><tr>
<td>조회</td>
<td>O(1)</td>
<td>O(n)</td>
</tr>
<tr>
<td>삽입/삭제</td>
<td>O(n)</td>
<td>O(1)</td>
</tr>
</tbody></table>
<p>따라서 데이터의 갯수가 정해져있고 자주 조회한다면 Array를 사용하면 되고
데이터의 갯수를 예상할 수 없고 삽입/삭제가 자주 일어난다면 Linked List를 사용하면 된다.
주된 차이점은 메모리구조로 <strong>Array는 연속적, Linked List는 불연속적</strong>이라는 걸 외워두면 된다.</p>
<p>둘은 각각 메모리 활용도도 다르기 때문에 상황에 따라 뭐가 더 효율적인지 판단하면 된다.</p>
<h4 id="조회">조회</h4>
<ul>
<li>Array: 즉시 접근 random access. <code>O(1)</code></li>
<li>Linked List: 순차 접근 sequential access. <code>O(n)</code></li>
</ul>
<h4 id="삽입삭제">삽입/삭제</h4>
<ul>
<li>Array: 마지막인 경우 -&gt; <code>O(1)</code> / 중간인 경우 -&gt; <code>O(n)</code></li>
<li>Linked List: 주소값만 바꾸기 때문에 <code>O(1)</code>의 시간복잡도
하지만 Linked List는 해당 index까지 가는 데에 <code>O(n)</code>의 시간복잡도를 가진다.</li>
</ul>
<h4 id="memory">memory</h4>
<ul>
<li>Array: fixed size라서 데이터가 저장되어 있지 않더라도 메모리를 차지하고 있을 수 있기 때문에 메모리 낭비가 발생 가능하다.</li>
<li>Linked List: runtime 중에서도 size 늘리고 줄이기가 가능하기 때문에 initial size를 고민할 필요가 없고, 필요한 만큼만 memory allocation이 일어나기 때문에 메모리 낭비도 없다.
하지만 Linked List는 address 저장 메모리도 함께 사용하기 때문에 Array보다 각 원소의 memory가 크다. 따라서 데이터의 수가 정해져있다면 메모리상에서는 Array가 더 효율이 좋다.</li>
</ul>
<h4 id="linked-list를-사용하는-상황">Linked List를 사용하는 상황</h4>
<ol>
<li>삽입/삭제가 자주 발생</li>
<li>조회 작업이 자주 발생하지 않음</li>
<li>데이터의 양을 예측할 수 없을 때</li>
</ol>
<h4 id="array를-사용하는-상황">Array를 사용하는 상황</h4>
<ol>
<li>조회 작업을 자주 할 때</li>
<li>데이터 갯수를 미리 아는 경우</li>
<li>데이터 반복문을 통해 빠르게 순회할 때</li>
<li>메모리를 적게 쓰는게 중요한 상황일 때</li>
</ol>
<h4 id="array와-linked-list의-memory-allocation은-언제-일어나며-메모리의-어느-영역에-할당되는가">Array와 Linked List의 Memory Allocation은 언제 일어나며 메모리의 어느 영역에 할당되는가?</h4>
<ul>
<li>Stack 영역 -&gt; compile time에 메모리 크기 결정</li>
<li>Heap 영역 -&gt; runtime에 메모리 크기 결정</li>
</ul>
<p>Array는 compile 단게에서 memory allocation
= Static Memory Allocation으로 <strong>Stack Memory 영역에 할당</strong></p>
<p>Linked List는 runtime 단계에서 memory allocation
= Dynamic Memory Allocation으로 <strong>Heap Memory 영역에 할당</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 프로그래머스 - k진수에서 소수 개수 구하기 (2022 KAKAO BLIND RECRUITMENT)]]></title>
            <link>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-k%EC%A7%84%EC%88%98%EC%97%90%EC%84%9C-%EC%86%8C%EC%88%98-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-k%EC%A7%84%EC%88%98%EC%97%90%EC%84%9C-%EC%86%8C%EC%88%98-%EA%B0%9C%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 03 Apr 2023 07:06:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="k진수에서-소수-개수-구하기">k진수에서 소수 개수 구하기</h3>
</blockquote>
<h4 id="문제-설명">문제 설명</h4>
<p>양의 정수 n이 주어집니다. 이 숫자를 k진수로 바꿨을 때, 변환된 수 안에 아래 조건에 맞는 소수(Prime number)가 몇 개인지 알아보려 합니다.</p>
<blockquote>
</blockquote>
<ul>
<li>0P0처럼 소수 양쪽에 0이 있는 경우</li>
<li>P0처럼 소수 오른쪽에만 0이 있고 왼쪽에는 아무것도 없는 경우</li>
<li>0P처럼 소수 왼쪽에만 0이 있고 오른쪽에는 아무것도 없는 경우</li>
<li>P처럼 소수 양쪽에 아무것도 없는 경우</li>
<li>단, P는 각 자릿수에 0을 포함하지 않는 소수입니다.<ul>
<li>예를 들어, 101은 P가 될 수 없습니다.<blockquote>
</blockquote>
예를 들어, 437674을 3진수로 바꾸면 211020101011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 왼쪽부터 순서대로 211, 2, 11이 있으며, 총 3개입니다. (211, 2, 11을 k진법으로 보았을 때가 아닌, 10진법으로 보았을 때 소수여야 한다는 점에 주의합니다.) 211은 P0 형태에서 찾을 수 있으며, 2는 0P0에서, 11은 0P에서 찾을 수 있습니다.<blockquote>
</blockquote>
정수 n과 k가 매개변수로 주어집니다. n을 k진수로 바꿨을 때, 변환된 수 안에서 찾을 수 있는 위 조건에 맞는 소수의 개수를 return 하도록 solution 함수를 완성해 주세요.<h4 id="제한사항">제한사항</h4>
</li>
</ul>
</li>
<li>1 ≤ n ≤ 1,000,000</li>
<li>3 ≤ k ≤ 10<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>n</th>
<th>k</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>437674</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
<td>110011</td>
<td>10</td>
<td>2</td>
</tr>
<tr>
<td>#### 입출력 예 설명</td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
<li><em>입출력 예 #1*</em>
문제 예시와 같습니다.<blockquote>
</blockquote>
</li>
<li><em>입출력 예 #2*</em>
110011을 10진수로 바꾸면 110011입니다. 여기서 찾을 수 있는 조건에 맞는 소수는 11, 11 2개입니다. 이와 같이, 중복되는 소수를 발견하더라도 모두 따로 세어야 합니다.</li>
</ul>
<br>

<h3 id="⭐처음에-구현한-코드">⭐처음에 구현한 코드</h3>
<pre><code class="language-python">import string

tmp = string.digits+string.ascii_lowercase
def convert(num, base) :
    q, r = divmod(num, base)
    if q == 0 :
        return tmp[r] 
    else :
        return convert(q, base) + tmp[r]

def is_decimal(n):
    if n == 1:
        return False
    else:
        for i in range(2,n):
            if n%i == 0:
                return False
        return True

def solution(n, k):
    answer = 0
    arr = []
    convert_num = convert(n,k)
    arr = convert_num.split(&quot;0&quot;)
    for num in arr:
        if num == &quot;&quot;:
            arr.remove(&quot;&quot;)

    for num in arr:
        n = int(num)
        if is_decimal(n) is True:
            answer += 1

    return answer</code></pre>
<p> 입력된 <code>n</code>을 <code>k</code>진수로 변환하기 위해 <code>convert()</code> 함수를 구현했다. n진수로 바꾸는 코드는 가져온거라서 어떻게 구현해야하는지 살펴봐야 할 것 같다. 그리고 소수인지 판별하기 위해 <code>is_decimal</code> 함수를 구현했다. <code>True</code> 가 반환된다면 소수인걸로 구현했다.</p>
 <br>

<h3 id="🤔오답노트">🤔오답노트</h3>
<p><img src="https://velog.velcdn.com/images/dev_ming/post/6965ef89-6a0a-442c-8ae3-c683b8179c3d/image.png" alt="">
테스트 케이스1에서 시간초과, 12에서 런타임 에러가 났다... 왜지...</p>
<p>숫자의 용량 문제인 것 같다. 하지만 파이썬에는 long형 자료형이 없는데..? ㅜㅜ</p>
<pre><code class="language-python">def is_decimal(n):
    if n == 1:
        return False
    else:
        for i in range(2,int(math.sqrt(n))+1):
            if n%i == 0:
                return False
        return True</code></pre>
<p>소수인지 판별하는 코드를 <code>int(math.sqrt(n))+1</code> 까지로 바꿔줬다. 소수 판별을 위해서는 해당 수 n의 제곱근까지만 나눠봐도 판별이 가능하다. 따라서 k진수로 바꾼다면 n이 int자료형을 넘어서기 때문에 제곱근까지만 나눠보는 것으로 시간 초과를 막는 것이다. </p>
<p>12번 런타임 에러는 질문을 보고 해결했다. 예를 들어, 36을 3진수로 바꾸는 경우에는 <code>1100</code>이 되는데 해당 경우에 <code>remove()</code>를 한다면 뒤의 빈칸 하나는 없어지지 않는다.
<img src="https://velog.velcdn.com/images/dev_ming/post/4ed4bf58-eeb3-4181-9a5b-44f3ba4b2e28/image.png" alt="">
테스트 케이스를 추가해서 확인하면 이런식으로 된다. 따라서 빈칸은 int형으로 취급되지 못하기 때문에 런타임 에러가 나는 것이다. </p>
<pre><code class="language-python"> new_arr = []
    for num in arr:
        if num == &quot;&quot;:
            continue
        else:
            new_arr.append(num)
    arr = new_arr</code></pre>
<p>해결하기 위해 전에 했던 것 처럼 빈칸이 아닌 경우에 새 배열에 저장을 해서 해당 배열로 바꿔줬다. </p>
<br>

<h3 id="✔수정코드">✔수정코드</h3>
<pre><code class="language-python">import string
import math

tmp = string.digits+string.ascii_lowercase
def convert(num, base) :
    q, r = divmod(num, base)
    if q == 0 :
        return tmp[r] 
    else :
        return convert(q, base) + tmp[r]

def is_decimal(n):
    if n == 1:
        return False
    else:
        for i in range(2,int(math.sqrt(n))+1):
            if n%i == 0:
                return False
        return True

def solution(n, k):
    answer = 0
    arr = []
    convert_num = convert(n,k)
    arr = convert_num.split(&quot;0&quot;)

    new_arr = []
    for num in arr:
        if num == &quot;&quot;:
            continue
        else:
            new_arr.append(num)
    arr = new_arr

    for num in arr:
        n = int(num)
        if is_decimal(n) is True:
            answer += 1

    return answer</code></pre>
<p>소수 판별은 제곱근 까지만 판별한다는 그런거는 힌트를 보지 않는다면 풀 수 없었을 것이다.. ㅜㅜ.. 그런게 나오면 어떡한담.. 많이 푸는 수 밖에 없는 것일까,,
그리고 그냥 제곱근까지만 하면 안되고 +1을 해줘야 제대로 된 정답이 나오드라,,
실패 케이스를 찾아내는게 너무 어려운거 같다🥲</p>
<br>

<h3 id="🤓다른-코드">🤓다른 코드</h3>
<pre><code class="language-python"># n을 k진법으로 나타낸 문자열 반환
def conv(n, k):
    s = &#39;&#39;
    while n:
        s += str(n%k)
        n //= k
    return s[::-1]

# n이 소수인지 판정
def isprime(n):
    if n &lt;= 1: return False
    i = 2
    while i*i &lt;= n:
        if n%i == 0: return False
        i += 1
    return True

def solution(n, k):
    s = conv(n,k)
    cnt = 0
    for num in s.split(&#39;0&#39;):
        if not num: continue # 빈 문자열에 대한 예외처리
        if isprime(int(num)): cnt += 1
    return cnt</code></pre>
<p>깔끔하고 괜찮은 코드인 것 같다. 내가 사용한 방법처럼 어렵게 k진수로 바꾸는 것이 아닌 나누는 방법으로 나누는 코드가 더 괜찮은 것 같다. 그리고 sqrt를 사용한게 아니라 <code>i*i &lt;= n</code> 을 사용한게 괜찮은 것 같다. 음 결국 같은 코드이긴 한데 왜 저기서는 +1을 안해도 제대로 나오는거지? 흐음.. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 프로그래머스 - 이상한 문자 만들기]]></title>
            <link>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AC%B8%EC%9E%90-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%9D%B4%EC%83%81%ED%95%9C-%EB%AC%B8%EC%9E%90-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Thu, 30 Mar 2023 05:43:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="이상한-문자-만들기">이상한 문자 만들기</h3>
</blockquote>
<h4 id="문제-설명">문제 설명</h4>
<p>문자열 s는 한 개 이상의 단어로 구성되어 있습니다. 각 단어는 하나 이상의 공백문자로 구분되어 있습니다. 각 단어의 짝수번째 알파벳은 대문자로, 홀수번째 알파벳은 소문자로 바꾼 문자열을 리턴하는 함수, solution을 완성하세요.</p>
<h4 id="제한-사항">제한 사항</h4>
<ul>
<li>문자열 전체의 짝/홀수 인덱스가 아니라, 단어(공백을 기준)별로 짝/홀수 인덱스를 판단해야합니다.</li>
<li>첫 번째 글자는 0번째 인덱스로 보아 짝수번째 알파벳으로 처리해야 합니다.<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>s</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>&quot;try hello world&quot;</td>
<td>&quot;TrY HeLlO WoRlD&quot;</td>
</tr>
<tr>
<td>#### 입출력 예 설명</td>
<td></td>
</tr>
<tr>
<td>&quot;try hello world&quot;는 세 단어 &quot;try&quot;, &quot;hello&quot;, &quot;world&quot;로 구성되어 있습니다. 각 단어의 짝수번째 문자를 대문자로, 홀수번째 문자를 소문자로 바꾸면 &quot;TrY&quot;, &quot;HeLlO&quot;, &quot;WoRlD&quot;입니다. 따라서 &quot;TrY HeLlO WoRlD&quot; 를 리턴합니다.</td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<br>

<h3 id="⭐처음에-구현한-코드">⭐처음에 구현한 코드</h3>
<pre><code class="language-python">def solution(s):
    answer = &#39;&#39;
    arr = []
    arr = s.split()
    for str in arr:
        for i in range(len(str)):
            if i%2 == 0:
                answer += str[i].upper()
            else:
                answer += str[i].lower()
        answer += &#39; &#39;

    return answer[:-1] </code></pre>
<p><code>arr</code> 에 입력된 문자열 s를 <code>split()</code> 을 사용해서 공백 기준으로 나누고 <code>for</code> 문을 돌려서 index가 짝수면 대문자로, 홀수면 소문자로 변환하도록 해서 answer에 추가했다. 공백은 마지막에 한번 더 추가되기 때문에 <code>return</code> 값은 <code>answer[:-1]</code>로 해준다. 
하지만 생각보다 조금 맞고 많이 틀림 ,,, 🥲 오늘도 눈물만 흘린다 주륵주륵,,,
<br></p>
<h3 id="🤔오답노트">🤔오답노트</h3>
<p>왜 안되는건지?? 도저히 감이 안잡혔다. 그래서 힌트가 있길래 보니까
<img src="https://velog.velcdn.com/images/dev_ming/post/9d44da3c-c69d-43dd-a8ea-adb7e48d6f7d/image.png" alt="">
이렇게 말하고 있더라,, 솔직히 좀 이해가 안간다. 코딩 능력을 보는 코딩테스트 인데 꼭 저렇게 말장난 같은 지문을 잘 읽어봐라! 를 내야하는지,,, 그런건 좀 비문학에 가깝지 않나?
ㅎㅎ; 어쨌든 공백을 잘 생각해보라니까 잘 생각해봐야겠죠,, 어쨌든 이제까지 코딩테스트를 풀면서 느끼는거 (특히 프로그래머스 쪽) </p>
<p><strong>입출력 예만 보고 생각하면 절대 다 맞을수가 없다</strong></p>
<p>그래서 내가 왜 틀렸다고? 답은 의외로 간단했다.
파이썬에서 <code>spilt()</code> 을 인자 없이 사용하게 되면 여러개의 공백이 있는 것도 하나의 공백으로 취급하고, 시작과 끝에 오는 공백은 무시하게 된다. 따라서 <code>split()</code> 이 아니라 <code>split(&quot; &quot;)</code> 과 같이 공백을 문자열 안에 넣어야 공백을 하나하나씩 취급하게 된다.
결국 파이썬 라이브러리의 사용법을 더 잘 알았어야 했다는 소리. 더 열심히 하자.</p>
<br>

<h3 id="✔수정코드">✔수정코드</h3>
<pre><code class="language-python">def solution(s):
    answer = &#39;&#39;
    arr = []
    arr = s.split(&quot; &quot;)
    for str in arr:
        for i in range(len(str)):
            if i%2 == 0:
                answer += str[i].upper()
            else:
                answer += str[i].lower()
        answer += &#39; &#39;

    return answer[:-1]</code></pre>
<p> 기존의 코드에서 <code>split()</code> 에 인자만 넣어줬다. 그랬더니 백점~</p>
 <br>

<h3 id="🤓다른-코드">🤓다른 코드</h3>
<pre><code class="language-python">def toWeirdCase(s):
    return &quot; &quot;.join(map(lambda x: &quot;&quot;.join([a.lower() if i % 2 else a.upper() for i, a in enumerate(x)]), s.split(&quot; &quot;)))</code></pre>
<p>와우... 코드를 줄이는걸 좋아하긴 하지만 그래도 이런식으로는 안쓸것 같다. 어느정도의 가독성은 있어야 한다고 생각하기 때문에... 하지만 정말 대단하긴 하다!
<code>lambda</code>랑 <code>enumerate</code>를 어떻게 사용했는지도 알아보면 좋겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 프로그래머스 - 체육복]]></title>
            <link>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%B2%B4%EC%9C%A1%EB%B3%B5</link>
            <guid>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%B2%B4%EC%9C%A1%EB%B3%B5</guid>
            <pubDate>Tue, 28 Mar 2023 08:52:12 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="체육복">체육복</h3>
</blockquote>
<h4 id="문제-설명">문제 설명</h4>
<p>점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번호의 학생이나 바로 뒷번호의 학생에게만 체육복을 빌려줄 수 있습니다. 예를 들어, 4번 학생은 3번 학생이나 5번 학생에게만 체육복을 빌려줄 수 있습니다. 체육복이 없으면 수업을 들을 수 없기 때문에 체육복을 적절히 빌려 최대한 많은 학생이 체육수업을 들어야 합니다.</p>
<blockquote>
</blockquote>
<p>전체 학생의 수 n, 체육복을 도난당한 학생들의 번호가 담긴 배열 lost, 여벌의 체육복을 가져온 학생들의 번호가 담긴 배열 reserve가 매개변수로 주어질 때, 체육수업을 들을 수 있는 학생의 최댓값을 return 하도록 solution 함수를 작성해주세요.</p>
<h4 id="제한사항">제한사항</h4>
<ul>
<li>전체 학생의 수는 2명 이상 30명 이하입니다.</li>
<li>체육복을 도난당한 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.</li>
<li>여벌의 체육복을 가져온 학생의 수는 1명 이상 n명 이하이고 중복되는 번호는 없습니다.</li>
<li>여벌 체육복이 있는 학생만 다른 학생에게 체육복을 빌려줄 수 있습니다.</li>
<li>여벌 체육복을 가져온 학생이 체육복을 도난당했을 수 있습니다. 이때 이 학생은 체육복을 하나만 도난당했다고 가정하며, 남은 체육복이 하나이기에 다른 학생에게는 체육복을 빌려줄 수 없습니다.<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>n</th>
<th>lost</th>
<th>reserve</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>5</td>
<td>[2, 4]</td>
<td>[1, 3, 5]</td>
<td>5</td>
</tr>
<tr>
<td>5</td>
<td>[2, 4]</td>
<td>[3]</td>
<td>4</td>
</tr>
<tr>
<td>3</td>
<td>[3]</td>
<td>[1]</td>
<td>2</td>
</tr>
<tr>
<td>#### 입출력 예 설명</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>예제 #1</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1번 학생이 2번 학생에게 체육복을 빌려주고, 3번 학생이나 5번 학생이 4번 학생에게 체육복을 빌려주면 학생 5명이 체육수업을 들을 수 있습니다.</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<blockquote>
</blockquote>
예제 #2
3번 학생이 2번 학생이나 4번 학생에게 체육복을 빌려주면 학생 4명이 체육수업을 들을 수 있습니다.</li>
</ul>
<br>

<h3 id="⭐처음에-구현한-코드">⭐처음에 구현한 코드</h3>
<pre><code class="language-python">def solution(n, lost, reserve):
    answer = 0
    new_reserve = []
    new_lost = []

    for x in lost:
        if x in reserve:
            reserve.remove(x)
        else:
            new_lost.append(x)

    lost = new_lost
    answer = n - len(lost)

    for x in reserve:
        if x + 1 in lost:
            lost.remove(x+1)
            answer += 1
        else:
            new_reserve.append(x)

    reserve = new_reserve

    if not reserve or not lost:
        return answer
    else:
        for x in reserve:
            if x-1 in lost:
                answer += 1

    return answer</code></pre>
<br>

<h3 id="🤔오답노트">🤔오답노트</h3>
<p><img src="https://velog.velcdn.com/images/dev_ming/post/eb8faf84-1ba0-4b1e-9484-0c4628fe1a36/image.png" alt=""></p>
<p>11~16번 까지의 테스트케이스에서 실패가 떴다 ㅜㅜ.. 
이럴때 보면 테스트 케이스를 안 알려줘서 넘 짱남 흑흑...
물론 모든 케이스를 다 생각하고 짜는것이 능력이라고는 하지만 어렵당 @.@</p>
<p>어디서 잘못됐는지 도저히 모르겠어서 질문글을 봤고 해답을 찾았다. <code>x + 1</code>을 먼저 실행한게 문제였다. 단순하게 <code>x - 1</code> 부터 해야 옷을 빌려 입을 수 있는 학생의 최댓값이 나오는 것. </p>
<pre><code>n=5
lost = [1,3] 
reserve = [2,4]</code></pre><p>테스트 케이스가 이렇게 되어있다면 <code>x + 1</code> 부터 실행한다면 2는 3에게 옷을 빌려주게 되고 4는 1에게 옷을 빌려주지 못하게 된다. 하지만 <code>x - 1</code> 부터 실행한다면 2는 1에게, 4는 3에게 옷을 빌려줘서 최대값인 5를 구할 수 있다.</p>
<p>그래서 단순하게 <code>x + 1</code> 과 <code>x - 1</code> 의 위치만 바꿨더니 이번에는 17~20, 25 테스트 케이스에서 실패가 발생.. 아무래도 큰 수를 먼저 해도 비슷한 문제가 생기는 것 같다. 밥먹으면서 생각해보니</p>
<pre><code>n=5
lost = [2,4] 
reserve = [1,3]</code></pre><p>이렇게 위에랑 반대로 된다면 <code>x - 1</code> 부터 실행하게 된다면 1은 0이라서 안되고, 3은 2에게 옷을 빌려주게 된다. 하지만 <code>x + 1</code> 부터 실행을 한다면 모두에게 옷을 빌려줄 수 있는 최댓값을 구할 수 있다. 그럼 어떻게 해야할까?</p>
<br>

<h3 id="✔수정코드">✔수정코드</h3>
<pre><code class="language-python">def solution(n, lost, reserve):
    answer = 0
    answer1 = 0
    new_reserve = []
    new_lost = []
    lost1 = []
    reserve1 = []

    for x in lost:
        if x in reserve:
            reserve.remove(x)
        else:
            new_lost.append(x)

    lost = new_lost

    for x in lost:
        lost1.append(x)
    for x in reserve:
        reserve1.append(x)

    answer = n - len(lost)
    answer1 = n - len(lost)

    for x in reserve:
        if x-1 in lost:
            lost.remove(x-1)
            answer += 1
        else:
            new_reserve.append(x)

    reserve = new_reserve

    for x in reserve:
        if x+1 in lost:
            answer += 1

    # + 먼저
    new_reserve = []

    for x in reserve1:
        if x+1 in lost1:
            lost1.remove(x+1)
            answer1 += 1
        else:
            new_reserve.append(x)

    reserve1 = new_reserve

    for x in reserve1:
        if x-1 in lost1:
            answer1 += 1

    return max(answer,answer1)</code></pre>
<p>도저히 방법이 생각이 안나서 두 방법으로 다 구하고 나온 수를 비교하여 둘 중에 큰 수를 return 하는 방식으로 코드를 구현했다. 테스트케이스는 다 통과했지만 코드도 너무 길고 뭔가 더 효율적인 방법이 있을 것 같아서 풀었어도 푼 것 같지가 않다.. 슬픔 ㅜ</p>
<br>

<h3 id="🤓다른-코드">🤓다른 코드</h3>
<pre><code class="language-python">def solution(n, lost, reserve):
    _reserve = [r for r in reserve if r not in lost]
    _lost = [l for l in lost if l not in reserve]
    for r in _reserve:
        f = r - 1
        b = r + 1
        if f in _lost:
            _lost.remove(f)
        elif b in _lost:
            _lost.remove(b)
    return n - len(_lost)</code></pre>
<p>와 이렇게 짧게 짤 수 있다니! 하고 감탄했지만 아무래도 이것도 결국에는 - 를 먼저 실행하는 것이다 보니 안될 것 같아서 돌려보니까 실제로 테스트 케이스 일부분에서 통과를 못했다. 아마 옛날에 테스트케이스가 더 추가되기 전의 코드인가보다. 하지만 별개로 <code>_reserve = [r for r in reserve if r not in lost]</code> 이 부분의 코드는 저렇게 짜는 방식을 배워야겠다. 무조건 짧게 짜는게 좋은건 아니라지만 쓸데 없이 길게 짜는것도 그렇게 좋은 방식 같지는 않다.
이 외의 나머지 코드들도 돌려봤는데 테스트케이스 몇개에서 실패했다. 아마 추가가 되어서 그런가보다. 내가 짠 코드를 더 발전 시키는 방향으로 봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 프로그래머스 - 7의 개수]]></title>
            <link>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-7%EC%9D%98-%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-7%EC%9D%98-%EA%B0%9C%EC%88%98</guid>
            <pubDate>Fri, 24 Mar 2023 07:54:55 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="7의-개수">7의 개수</h3>
</blockquote>
<h4 id="문제-설명">문제 설명</h4>
<p>머쓱이는 행운의 숫자 7을 가장 좋아합니다. 정수 배열 array가 매개변수로 주어질 때, 7이 총 몇 개 있는지 return 하도록 solution 함수를 완성해보세요.</p>
<h4 id="제한사항">제한사항</h4>
<ul>
<li>1 ≤ array의 길이 ≤ 100</li>
<li>0 ≤ array의 원소 ≤ 100,000<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>array</th>
<th>result</th>
</tr>
</thead>
<tbody><tr>
<td>[7, 77, 17]</td>
<td>4</td>
</tr>
<tr>
<td>[10, 29]</td>
<td>0</td>
</tr>
<tr>
<td>#### 입출력 예 설명</td>
<td></td>
</tr>
<tr>
<td>입출력 예 #1</td>
<td></td>
</tr>
</tbody></table>
</li>
<li>[7, 77, 17]에는 7이 4개 있으므로 4를 return 합니다.<blockquote>
</blockquote>
입출력 예 #2</li>
<li>[10, 29]에는 7이 없으므로 0을 return 합니다.</li>
</ul>
<br>

<h3 id="⭐처음에-구현한-코드">⭐처음에 구현한 코드</h3>
<pre><code class="language-python">def solution(array):
    answer = 0
    array = map(str, array)
    for i in array:
        for j in i:
            if j == &#39;7&#39;:
                answer += 1         

    return answer</code></pre>
<p>레벨 0이라 한번에 맞췄기 때문에 오답노트는 따로 없습니당.
<code>int array</code>를 <code>string array</code>로 바꾸고 이중 <code>for</code>문을 사용해서 7이 있는 것의 count를 세는 방식으로 구현.</p>
<br>

<h3 id="🤓다른-코드">🤓다른 코드</h3>
<pre><code class="language-python">def solution(array):
    return str(array).count(&#39;7&#39;)</code></pre>
<p>댓글들이 전부 &#39;나 뭐한거지&#39; 하던데 나도 마찬가지 기분이었다..
count를 하는게 생각은 났는데 int에서만 가능한줄 알았음 ㅜ .. 
문자열을 할 떄는 string 형식으로 넣어서 <code>count()</code>사용하기!!</p>
<p>그리고 <code>str(array)</code>하면 <code>map(str,array)</code> 할 필요없이 한번에 형식이 변환되는 것도 기억하기.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 프로그래머스 - 문자열 다루기 기본]]></title>
            <link>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EA%B8%B0%EB%B3%B8</link>
            <guid>https://velog.io/@dev_ming/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8B%A4%EB%A3%A8%EA%B8%B0-%EA%B8%B0%EB%B3%B8</guid>
            <pubDate>Tue, 21 Mar 2023 05:07:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="문자열-다루기-기본">문자열 다루기 기본</h3>
</blockquote>
<h4 id="문제-설명">문제 설명</h4>
<p>문자열 s의 길이가 4 혹은 6이고, 숫자로만 구성돼있는지 확인해주는 함수, <code>solution</code>을 완성하세요. 예를 들어 s가 &quot;a234&quot;이면 <code>False</code>를 리턴하고 &quot;1234&quot;라면 <code>True</code>를 리턴하면 됩니다.</p>
<blockquote>
</blockquote>
<h4 id="제한-사항">제한 사항</h4>
<ul>
<li>s는 길이 1 이상, 길이 8 이하인 문자열입니다.</li>
<li>s는 영문 알파벳 대소문자 또는 0부터 9까지 숫자로 이루어져 있습니다.<h4 id="입출력-예">입출력 예</h4>
<table>
<thead>
<tr>
<th>s</th>
<th>return</th>
</tr>
</thead>
<tbody><tr>
<td>&quot;a234&quot;</td>
<td>false</td>
</tr>
<tr>
<td>&quot;1234&quot;</td>
<td>true</td>
</tr>
</tbody></table>
</li>
</ul>
<br>

<h3 id="⭐처음에-구현한-코드">⭐처음에 구현한 코드</h3>
<pre><code class="language-python">def solution(s):    
    if s.isnumeric() and (len(s) == 4 or len(s) == 6):
        return True
    else:
        return False
</code></pre>
<p>간단한 문제라서 한번에 맞았다! 따라서 오답노트는 없음~ ･ᴥ･ ~</p>
<p><code>isnumeric()</code> 함수로 해당 문자열이 숫자인지 판단하고, <code>len(s)</code>가 4 or 6일때만 <code>True</code>를 반환하도록 했다.  </p>
<br>

<h3 id="🤓다른-코드">🤓다른 코드</h3>
<pre><code class="language-python">def alpha_string46(s):
    import re
    return bool(re.match(&quot;^(\d{4}|\d{6})$&quot;, s))</code></pre>
<p> 이건 정규식을 사용해서 풀었길래 신기해서 넣어봄!
 <br></p>
<pre><code class="language-python">def solution(s):
    return s.isdigit() and len(s) in [4,6]</code></pre>
<p>난 이렇게 한 줄로 코드를 짠 사람들을 볼때마다 갈 길이 멀다고 느낀다... 🥲
<code>isnumeric()</code> 이랑 <code>isdigit()</code> 중 사람들은 <code>isdigit()</code> 을 더 많이 쓰는 것 같던데 이유가 있을까? </p>
<br>

<h3 id="📚추가공부">📚추가공부</h3>
<h4 id="isnumeric-isdigit-isdecimal-의-차이">isnumeric(), isdigit(), isdecimal() 의 차이?</h4>
<p>간단하게 말해서 <code>isnumeric()</code>이 가장 포괄적이고 <code>isdecimal()</code>이 가장 제한적이라고 할 수 있다. <code>isdecimal()</code>은 해당 문자열이 0~9의 int 형태로 이루어진 것인지를 검사한다. <code>isdigit()</code>은 숫자인지를 검사한다. 예를 들어, <code>3²</code>도 <code>isdigit()</code>에서는 <code>true</code>다.
그렇다면 <code>isnumeric()</code>은? <code>isdigit()</code>보다 더 많은 케이스를 숫자로 쳐준다. 예를 들어 <code>½</code>같은 수도 <code>true</code>로 반환해줌.</p>
<p>코딩테스트 준비 수준에서는 <code>isdigit()</code> 정도까지만 사용해도 충분하기에 다들 <code>isdigit()</code>을 쓰는 것 같다.</p>
]]></description>
        </item>
    </channel>
</rss>