<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>koo-rogie.log</title>
        <link>https://velog.io/</link>
        <description>front-end를 꿈꿉니다</description>
        <lastBuildDate>Thu, 23 Jul 2026 13:28:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>koo-rogie.log</title>
            <url>https://velog.velcdn.com/images/koo-rogie/profile/77dfaf37-a6c3-4623-bb23-a5dd14880118/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. koo-rogie.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/koo-rogie" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2026년 7월, 프론트엔드 업데이트 모음]]></title>
            <link>https://velog.io/@koo-rogie/2026%EB%85%84-7%EC%9B%94-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EB%AA%A8%EC%9D%8C</link>
            <guid>https://velog.io/@koo-rogie/2026%EB%85%84-7%EC%9B%94-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EB%AA%A8%EC%9D%8C</guid>
            <pubDate>Thu, 23 Jul 2026 13:28:12 GMT</pubDate>
            <description><![CDATA[<h2 id="목차">목차</h2>
<ol>
<li>TypeScript 7.0 — 컴파일러가 Go로 다시 태어났다</li>
<li>Next.js 16.3 &amp; 보안 패치</li>
<li>npm 12.0.0 — 공급망 보안 강화</li>
<li>정리: 이번 달 흐름 한 줄 요약</li>
</ol>
<hr>
<h2 id="1-typescript-70-202678">1. TypeScript 7.0 (2026.7.8)</h2>
<h3 id="1-1-먼저-컴파일러가-뭘-하는-건지부터">1-1. 먼저, &quot;컴파일러&quot;가 뭘 하는 건지부터</h3>
<p>우리가 <code>.tsx</code> 파일에 타입을 붙여서 코드를 짜면, 그걸 실제로 검사하고 브라우저가 이해할 수 있는 JS로 바꿔주는 프로그램이 필요해요. 이게  TypeScript 컴파일러(<code>tsc</code>) 예요. 예를 들어 <code>const age: number = &quot;스물&quot;</code> 처럼 잘못 쓰면, 이 컴파일러가 &quot;어? number라면서 문자열 넣었네&quot; 하고 에러를 잡아주는 거죠.</p>
<p>문제는 프로젝트가 커질수록 이 검사 작업이 점점 오래 걸린다는 거예요. 큰 회사 프로젝트에서는 코드 한 줄 고치고 저장했는데 에디터가 빨간 줄(에러) 표시해주는 데까지 몇십 초씩 걸리는 경우도 있었어요.</p>
<h3 id="1-2-핵심-한-줄">1-2. 핵심 한 줄</h3>
<p>Microsoft가 이 컴파일러 자체를 <strong>완전히 다른 언어(Go)로 새로 만들어서</strong> 훨씬 빠르게 만들었어요.</p>
<h3 id="1-3-왜-굳이-언어를-바꿨나">1-3. 왜 굳이 언어를 바꿨나</h3>
<p>지금까지 TypeScript 컴파일러는 원래 <strong>TypeScript/JavaScript로 짜여져 있었고</strong>, 그걸 Node.js 위에서 돌리는 구조였어요. 비유하자면 &quot;번역기를 만드는데, 그 번역기 자체를 느린 언어로 짜놓은&quot; 셈이죠. 이 구조에는 세 가지 태생적 한계가 있었어요.</p>
<ol>
<li><strong>한 번에 파일 하나씩만 검사 가능</strong> (싱글 스레드) — 파일이 100개면 순서대로 하나씩 봐야 함</li>
<li><strong>처음 실행할 때 워밍업 시간이 필요함</strong> (JIT 컴파일 방식이라 그럼)</li>
<li><strong>메모리 정리(가비지 컬렉션) 방식이 코드 구조(트리 형태)랑 잘 안 맞음</strong></li>
</ol>
<p>Go라는 언어로 완전히 옮기면서 이 세 가지가 한 번에 해결됐어요. 특히 Go는 여러 파일을 <strong>동시에</strong> 검사할 수 있게 해줘서, 코어가 여러 개인 컴퓨터의 성능을 제대로 활용할 수 있게 됐습니다.</p>
<ul>
<li><p><strong>잠깐, Go가 뭐예요?</strong></p>
<p>  Go(Golang)는 구글이 만든 프로그래밍 언어예요. </p>
<p>  JavaScript/TypeScript처럼 브라우저에서 돌아가는 언어가 아니라, C++이나 Rust처럼 <strong>컴퓨터가 바로 실행할 수 있는 네이티브 코드로 컴파일되는 언어</strong>예요.</p>
<p>  실행 속도가 빠르고, 특히 <strong>여러 작업을 동시에 처리하는(동시성) 데 강한 것으로 유명</strong>해서 도커(Docker), 쿠버네티스(Kubernetes) 같은 인프라 도구들도 Go로 만들어졌어요. </p>
<p>  한마디로 &quot;웹 프론트엔드용 언어&quot;가 아니라 &quot;빠르고 튼튼한 시스템/백엔드 도구를 만들 때 쓰는 언어&quot;라고 생각하면 됩니다.</p>
</li>
</ul>
<blockquote>
<p><strong>오해하기 쉬운 부분</strong>: 이건 TypeScript를 처음부터 다시 설계한 게 아니에요. 로직과 검사 규칙은 <strong>그대로 옮기기만</strong> 했어요(포팅). 그래서 예전 버전에서 통과하던 코드는 새 버전에서도 똑같이 통과합니다. &quot;언어(도구)만 바뀌고 규칙은 그대로&quot;라고 생각하면 됩니다.</p>
</blockquote>
<h3 id="1-4-체감-성능-숫자로-보면-확-와닿아요">1-4. 체감 성능 (숫자로 보면 확 와닿아요)</h3>
<p>!7-0-speedup-chart-2.png</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>TypeScript 6</th>
<th>TypeScript 7</th>
<th>얼마나 빨라졌나</th>
</tr>
</thead>
<tbody><tr>
<td>vscode</td>
<td>125.7s</td>
<td>10.6s</td>
<td>11.9x</td>
</tr>
<tr>
<td>sentry</td>
<td>139.8s</td>
<td>15.7s</td>
<td>8.9x</td>
</tr>
<tr>
<td>bluesky</td>
<td>24.3s</td>
<td>2.8s</td>
<td>8.7x</td>
</tr>
<tr>
<td>playwright</td>
<td>12.8s</td>
<td>1.47s</td>
<td>8.7x</td>
</tr>
<tr>
<td>tldraw</td>
<td>11.2s</td>
<td>1.46s</td>
<td>7.7x</td>
</tr>
</tbody></table>
<p>쉽게 말하면, 예전엔 커피 한 잔 타올 시간(2분)에 될까 말까 하던 검사가 이제는 숨 한 번 쉬는 사이에 끝난다는 거예요.</p>
<p>!7-0-mem-chart-2.png</p>
<table>
<thead>
<tr>
<th>Codebase</th>
<th>TypeScript 6</th>
<th>TypeScript 7</th>
<th>Memory Delta</th>
</tr>
</thead>
<tbody><tr>
<td>vscode</td>
<td>5.2GB</td>
<td>4.2GB</td>
<td>-18%</td>
</tr>
<tr>
<td>sentry</td>
<td>4.9GB</td>
<td>4.6GB</td>
<td>-6%</td>
</tr>
<tr>
<td>bluesky</td>
<td>1.8GB</td>
<td>1.3GB</td>
<td>-26%</td>
</tr>
<tr>
<td>playwright</td>
<td>1.0GB</td>
<td>0.9GB</td>
<td>-11%</td>
</tr>
<tr>
<td>tldraw</td>
<td>0.6GB</td>
<td>0.5GB</td>
<td>-15%</td>
</tr>
</tbody></table>
<h3 id="1-5-아직-다-못-쓰는-이유--속도-vs-호환성-트레이드오프">1-5. 아직 다 못 쓰는 이유 — &quot;속도 vs 호환성&quot; 트레이드오프</h3>
<p>TypeScript 7.0은 속도를 얻은 대신, 아직  다른 프로그램들이 이 컴파일러를 &quot;연결&quot;해서 쓸 수 있는 창구(프로그래매틱 API) 가 완성되지 않았어요. 이 API가 있어야 Vue, Svelte, Astro 같은 프레임워크들이 자기네 에디터 기능(자동완성, 실시간 에러 표시)에 TypeScript 7을 끼워 넣을 수 있는데, 지금은 그 창구 자체가 없는 상태예요.</p>
<ul>
<li><strong>지금 당장 못 올라타는 곳</strong>: Vue, Svelte, Astro, MDX, Angular 템플릿 타입체킹</li>
<li><strong>이 API는 TypeScript 7.1에서 제공될 예정</strong> (대략 2026년 10월경 예상)</li>
<li>그때까지는 저 프레임워크들 프로젝트에서 억지로 업그레이드하면 에디터 자동완성이나 에러 표시가 오작동할 수 있어요</li>
</ul>
<h3 id="1-6-우리reactnextjs-프로젝트는-어떨까">1-6. 우리(React/Next.js) 프로젝트는 어떨까?</h3>
<p>다행히 React나 Next.js는 이 프로그래매틱 API에 크게 의존하지 않는 구조라, <strong>지금 바로 업그레이드해도 되는 그룹</strong>에 속해요.</p>
<pre><code class="language-bash">npm install -D typescript@latest</code></pre>
<p>업그레이드 전에 확인하면 좋은 것들:</p>
<ul>
<li><code>tsconfig.json</code>에서 없어진 옵션들(<code>target: es5</code>, <code>moduleResolution: node</code>, <code>baseUrl</code> 등) 쓰고 있는지 확인</li>
<li>업그레이드 후 <code>npx tsc --noEmit</code>으로 타입 에러만 먼저 한번 검사해보기 (빌드는 안 하고 검사만)</li>
</ul>
<hr>
<h2 id="2-nextjs-163--보안-패치-20267">2. Next.js 16.3 &amp; 보안 패치 (2026.7)</h2>
<h3 id="2-1-배경-nextjs와-turbopack이-뭔지">2-1. 배경: Next.js와 Turbopack이 뭔지</h3>
<p>Next.js는 우리가 쓰는 React 프레임워크고, <strong>Turbopack</strong>은 그 안에서 코드를 묶어주는(번들링하는) 도구예요. 코드를 저장할 때마다 &quot;이 파일들을 모아서 브라우저가 읽을 수 있는 하나의 묶음으로 만드는&quot; 작업을 하는데, 이 속도가 개발 경험을 크게 좌우해요. 예전엔 Webpack이라는 도구를 썼는데, Next.js가 최근 자체적으로 훨씬 빠른 Rust 기반 도구인 Turbopack으로 갈아탔어요.</p>
<h3 id="2-2-turbopack-개선-사항">2-2. Turbopack 개선 사항</h3>
<p><strong>① Memory Eviction (메모리 회수)</strong></p>
<p>!image.png</p>
<ul>
<li>문제: 개발 서버를 오래 켜놓고 작업하다 보면(하루 종일 켜놓는 경우도 많죠) 메모리 사용량이 계속 쌓여서 컴퓨터가 느려지는 경우가 있었어요</li>
<li>개선: 이제 필요 없어진 컴파일 결과를 알아서 메모리에서 정리해줘서, 오래 켜놔도 무거워지지 않아요</li>
</ul>
<p><strong>② Persistent Cache for Builds (영구 캐시)</strong></p>
<p>!image.png</p>
<ul>
<li>문제: 예전엔 빌드할 때마다(예: 배포 전 <code>next build</code> 실행할 때마다) 처음부터 다시 다 컴파일했어요</li>
<li>개선: 이전 빌드 결과를 저장해뒀다가 재사용해서, 두 번째 빌드부터는 훨씬 빨라져요</li>
</ul>
<p><strong>③ Rust로 짜여진 React Compiler 지원</strong></p>
<ul>
<li>React 19부터 나온 &quot;React Compiler&quot;라는 도구(코드 최적화를 자동으로 해주는 도구)가 있는데, 이걸 더 빠른 언어(Rust)로 다시 짠 버전을 쓸 수 있게 됐어요</li>
</ul>
<p><strong>④ <code>import.meta.glob</code> 추가</strong></p>
<ul>
<li>여러 파일을 한 번에 패턴으로 불러오는 문법인데, Vite라는 다른 도구에서 쓰던 문법을 Next.js에서도 쓸 수 있게 지원 추가됨 (당장 급한 건 아니고, 알아두면 좋은 정도)</li>
</ul>
<h3 id="2-3-보안-패치--이번-달-중요한-부분">2-3. 보안 패치 — 이번 달 중요한 부분</h3>
<p><strong>&quot;캐시 포이즈닝(Cache Poisoning)&quot;이 뭔지부터 설명하면:</strong>
Next.js는 성능을 위해 페이지나 데이터를 캐시(임시 저장)해뒀다가 재사용해요. 그런데 이 캐시 시스템에 허점이 있으면, 공격자가 <strong>악의적인 내용을 캐시에 슬쩍 끼워 넣어서</strong>, 이후 그 페이지에 접속하는 <strong>다른 정상 사용자들에게</strong> 그 악성 내용이 보이게 만들 수 있어요. 내 서버가 자기도 모르게 공격자의 콘텐츠를 다른 사람들에게 뿌려주는 셈이죠.</p>
<p>이번 패치에서 고친 것들:</p>
<ul>
<li><strong>RSC(서버 컴포넌트) 응답 캐시 포이즈닝</strong> — 서버에서 렌더링한 컴포넌트 응답이 잘못된 캐시에 섞여 들어갈 수 있던 문제 2건</li>
<li><strong>미들웨어/프록시 리다이렉트 캐시 포이즈닝</strong> — 페이지 이동(리다이렉트) 처리 과정에서 발생할 수 있던 캐시 오염 문제</li>
<li><strong>미들웨어 우회 취약점</strong> — 특정 방식으로 요청을 보내면 보안 검사(미들웨어)를 건너뛸 수 있던 허점</li>
<li><strong>DoS(서비스 거부 공격) 취약점</strong> — 특정 캐시 기능을 악용해 서버 연결을 고갈시켜서 서비스를 마비시킬 수 있던 문제</li>
<li>그 외 App Router, 이미지 최적화, URL 파싱 관련 자잘한 버그들도 함께 수정됨</li>
</ul>
<h3 id="2-4-우리-프로젝트에-적용하려면">2-4. 우리 프로젝트에 적용하려면</h3>
<pre><code class="language-bash">npm install next@latest</code></pre>
<p>버전을 올리기만 하면 대부분 자동으로 적용돼요. 특별히 뭔가 새로 설정할 건 없고, &quot;패치니까 올려두면 안전하다&quot; 정도로 이해하면 됩니다.</p>
<hr>
<h2 id="3-npm-1200-2026710-릴리즈">3. npm 12.0.0 (2026.7.10 릴리즈)</h2>
<h3 id="3-1-먼저-공급망-공격이-뭔지부터">3-1. 먼저, &quot;공급망 공격&quot;이 뭔지부터</h3>
<p><code>npm install</code>을 실행하면 우리가 직접 짠 코드뿐 아니라, 그 패키지가 의존하는 또 다른 패키지들(의존성의 의존성...)까지 줄줄이 내 컴퓨터에 설치됩니다. 문제는 npm 패키지들이 설치되는 순간 <strong>자동으로 스크립트를 실행할 수 있다</strong>는 점이에요. (<code>postinstall</code> 스크립트 같은 것들)</p>
<p>만약 누군가 인기 있는 패키지의 계정을 해킹하거나, 이름을 살짝 비슷하게 지은 가짜 패키지를 올려놓으면 → 개발자가 <code>npm install</code> 한 번 실행하는 순간, 그 악성 스크립트가 자동으로 실행돼서 내 컴퓨터의 파일이나 환경변수(비밀번호, API 키 등)를 훔쳐갈 수 있습니다. 이게 바로 <strong>&quot;공급망 공격(supply chain attack)&quot;</strong>이에요. 실제로 최근 몇 년간 npm 생태계에서 이런 사고가 여러 번 있었고요.</p>
<p>npm 12.0.0은 이 문제에 정면으로 대응하는 업데이트입니다.</p>
<h3 id="3-2-무엇이-바뀌었나">3-2. 무엇이 바뀌었나</h3>
<p><strong>① 설치 스크립트가 이제 기본적으로 안 돌아감</strong></p>
<ul>
<li>예전: <code>npm install</code> 하면 패키지에 딸려온 스크립트가 <strong>자동으로</strong> 실행됐음</li>
<li>이제: 기본값이 &quot;실행 안 함&quot;으로 바뀜. 스크립트를 돌리고 싶으면 개발자가 직접 허용(<code>allowScripts</code>)해줘야 함</li>
<li>쉽게 말해 &quot;낯선 소포가 오면 일단 뜯어보지 않고, 안전하다고 확인된 것만 뜯는다&quot;는 정책으로 바뀐 것</li>
</ul>
<p><strong>② git이나 외부 링크로 받는 패키지도 기본 차단</strong></p>
<ul>
<li><code>package.json</code>에 &quot;이 패키지는 깃허브 저장소에서 바로 받아와&quot; 또는 &quot;이 URL의 압축파일을 받아와&quot; 같은 식으로 지정할 수 있는데, 이런 출처가 npm 공식 레지스트리보다 훨씬 위험함 (검증이 덜 되니까)</li>
<li>이제 이런 설치도 기본적으로 막혀 있고, 필요할 때만 명시적으로 허용해야 함</li>
</ul>
<p><strong>③ 오타나 잘못된 설정을 봐주지 않음</strong></p>
<ul>
<li>예전엔 <code>.npmrc</code> 설정 파일에 오타가 있거나 없는 옵션을 써도 그냥 &quot;경고&quot;만 뜨고 넘어갔음</li>
<li>이제는 이런 게 <strong>에러</strong>로 처리돼서 설치 자체가 멈춤 → 잘못된 설정을 방치한 채 넘어가는 일이 줄어듦</li>
</ul>
<p><strong>요약하면</strong>: &quot;일단 되게 하고 문제 생기면 그때 막자&quot;에서 → &quot;기본적으로 다 막아두고, 필요한 것만 허용하자&quot;로 npm의 기본 철학이 바뀐 릴리즈예요.</p>
<h3 id="3-3-그-외-정리된-기능들-참고용">3-3. 그 외 정리된 기능들 (참고용)</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td><code>npm shrinkwrap</code></td>
<td>완전 제거 (지금은 다들 <code>package-lock.json</code>만 씀)</td>
</tr>
<tr>
<td><code>npm adduser</code></td>
<td>제거 — 웹사이트에서 계정 만들고 <code>npm login</code>으로 로그인</td>
</tr>
<tr>
<td><code>star</code>, <code>stars</code>, <code>unstar</code></td>
<td>예전에 패키지에 별표 주던 기능, 제거됨</td>
</tr>
<tr>
<td>Node.js 지원 범위</td>
<td>너무 오래된 Node.js 버전은 이제 지원 안 함</td>
</tr>
</tbody></table>
<h3 id="3-4-참고-pnpmnpm의-대체-도구도-같은-흐름">3-4. 참고: pnpm(npm의 대체 도구)도 같은 흐름</h3>
<ul>
<li>npm 말고 pnpm이라는 패키지 매니저를 쓰는 팀들도 있는데, pnpm도 지난 4월 v11에서 <strong>&quot;새로 올라온 패키지는 하루 지나야 설치 가능&quot;</strong>, <strong>&quot;전역 설치도 프로젝트별로 격리&quot;</strong> 같은 비슷한 보안 강화를 이미 적용했어요</li>
<li>→ npm과 pnpm 둘 다 비슷한 시기에 &quot;일단 의심하고 본다&quot;는 방향으로 움직였다는 건, 그만큼 요즘 공급망 공격이 업계 전체의 진짜 골칫거리라는 뜻으로 읽을 수 있음</li>
</ul>
<hr>
<h2 id="4-정리">4. 정리</h2>
<table>
<thead>
<tr>
<th>도구</th>
<th>이번 달 핵심 변화</th>
<th>키워드</th>
</tr>
</thead>
<tbody><tr>
<td>TypeScript 7.0</td>
<td>컴파일러 Go 네이티브 포팅, 최대 12배 성능 향상</td>
<td><strong>속도</strong></td>
</tr>
<tr>
<td>Next.js 16.3</td>
<td>Turbopack 캐싱/메모리 개선 + 다수 CVE 보안 패치</td>
<td><strong>속도 + 보안</strong></td>
</tr>
<tr>
<td>npm 12.0.0</td>
<td>설치 스크립트 기본 차단, 공급망 보안 강화</td>
<td><strong>보안</strong></td>
</tr>
</tbody></table>
<p><strong>결론</strong>: 2026년 7월 한 달 사이, 프론트엔드 툴체인 전반이 &quot;더 빠르게&quot;와 &quot;더 안전하게&quot;라는 두 축을 동시에 밀어붙이고 있습니다. 특히 npm과 pnpm이 약속이라도 한 듯 같은 시기에 공급망 보안을 강화한 건, 최근 반복된 npm 패키지 해킹 사고들이 생태계 전체의 기본값을 바꿔놓고 있다는 신호로 읽을 수 있습니다.</p>
<hr>
<h2 id="참고-자료">참고 자료</h2>
<ul>
<li>TypeScript 7.0 공식 발표 (Microsoft DevBlogs, 2026.7.8): <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/">https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/</a></li>
<li>Next.js 16.3 Turbopack 개선 공식 블로그:
<a href="https://nextjs.org/blog/next-16-3-turbopack">https://nextjs.org/blog/next-16-3-turbopack</a></li>
<li>Next.js 16.3 Instant Navigations 공식 블로그:
<a href="https://nextjs.org/blog/next-16-3-instant-navigations">https://nextjs.org/blog/next-16-3-instant-navigations</a></li>
<li>npm 12.0.0 릴리즈 노트 (GitHub): 
<a href="https://github.com/npm/cli/releases/tag/v12.0.0">https://github.com/npm/cli/releases/tag/v12.0.0</a></li>
<li>npm v12 주요 변경사항 사전 공지 (GitHub Changelog): 
<a href="https://github.blog/changelog/2026-06-09-upcoming-breaking-changes-for-npm-v12/">https://github.blog/changelog/2026-06-09-upcoming-breaking-changes-for-npm-v12/</a></li>
<li>pnpm 11.0 릴리즈 블로그: 
<a href="https://pnpm.io/blog/releases/11.0">https://pnpm.io/blog/releases/11.0</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[디지털 이미지 - 픽셀과 해상도]]></title>
            <link>https://velog.io/@koo-rogie/%EB%94%94%EC%A7%80%ED%84%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%ED%94%BD%EC%85%80%EA%B3%BC-%ED%95%B4%EC%83%81%EB%8F%84</link>
            <guid>https://velog.io/@koo-rogie/%EB%94%94%EC%A7%80%ED%84%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%ED%94%BD%EC%85%80%EA%B3%BC-%ED%95%B4%EC%83%81%EB%8F%84</guid>
            <pubDate>Thu, 25 Jun 2026 12:03:09 GMT</pubDate>
            <description><![CDATA[<h1 id="픽셀pixel이란">픽셀(Pixel)이란?</h1>
<p><strong>픽셀은 디지털 이미지의 최소 단위</strong>입니다. &#39;Picture Element&#39;의 합성어로, 컴퓨터 화면에 표시되는 모든 이미지는 실제로 매우 작은 사각형 점들로 구성되어 있습니다.</p>
<ul>
<li>디지털 이미지를 계속 확대하면 정사각형 모양의 픽셀들이 모자이크처럼 배열된 것을 볼 수 있습니다</li>
<li>각 픽셀은 고유한 색상 정보를 가지고 있습니다</li>
<li>수많은 픽셀이 모여서 실물과 비슷한 이미지를 만들어냅니다</li>
</ul>
<h3 id="픽셀의-주요-특징"><strong>픽셀의 주요 특징</strong></h3>
<ul>
<li><strong>최소 단위:</strong> 디지털 이미지를 이루는 가장 작은 점입니다. 화면을 확대하면 모자이크처럼 보이는 사각형들이 픽셀입니다.</li>
<li><strong>색상 정보:</strong> 각 픽셀은 R(빨강), G(초록), B(파랑) 등의 빛 정보를 조합하여 다양한 색을 표현합니다.</li>
<li><strong>해상도와 관련:</strong> 화면의 해상도(예: 1920x1080)는 가로, 세로 픽셀 수를 나타내며, 픽셀이 많을수록 해상도가 높고 이미지가 선명해집니다</li>
</ul>
<hr>
<h2 id="해상도resolution의-두-가지-개념">해상도(Resolution)의 두 가지 개념</h2>
<p>해상도는 이미지의 크기와 품질을 결정하는 핵심 요소입니다. 해상도라는 용어는 두 가지 의미로 사용됩니다.</p>
<h3 id="1-픽셀의-총량-이미지-크기">1. 픽셀의 총량 (이미지 크기)</h3>
<p><strong>전체 픽셀 개수를 나타내는 개념</strong></p>
<ul>
<li><strong>카메라 화소수</strong>: 800만 화소 = 800만 개의 픽셀</li>
<li><strong>모니터 해상도</strong>: 1920×1080, 2560×1440 등 (가로×세로 픽셀 수)</li>
<li>디지털 카메라는 메가픽셀(MP) 단위로 표현 (1MP = 100만 픽셀)</li>
</ul>
<h3 id="2-픽셀의-밀도-이미지-품질">2. 픽셀의 밀도 (이미지 품질)</h3>
<p><strong>단위 면적당 픽셀 개수를 나타내는 개념</strong></p>
<h3 id="ppi-pixels-per-inch">PPI (Pixels Per Inch)</h3>
<ul>
<li>1인치×1인치 면적에 들어가는 픽셀 수</li>
<li>예: 72ppi = 1인치당 72×72 = 5,184개의 픽셀</li>
<li>디지털 화면에 주로 사용</li>
</ul>
<p><img src="https://velog.velcdn.com/images/koo-rogie/post/f90f3e6f-3bbb-4ea2-806c-4ce294cba315/image.png" alt="">
같은 이미지의 72 ppi와 300 ppi의 100% 화면</p>
<p><img src="https://velog.velcdn.com/images/koo-rogie/post/8206b1cb-7eff-4149-834d-349fca019e38/image.png" alt=""></p>
<p>같은 이미지의 72 ppi와 300 ppi의 100% 화면</p>
<hr>
<h2 id="해상도의-상관관계">해상도의 상관관계</h2>
<p>해상도는 <strong>픽셀 수</strong>, <strong>픽셀 밀도</strong>, <strong>이미지 크기</strong> 세 가지가 서로 연결되어 있습니다.</p>
<h3 id="실제-예시">실제 예시</h3>
<p><strong>72ppi, 10×10인치 이미지의 경우:</strong></p>
<ul>
<li>총 픽셀 수: 518,400개 (720×720)</li>
<li>필요한 저장 공간을 계산 가능</li>
</ul>
<p><strong>이를 300ppi 인쇄용으로 변환하면:</strong></p>
<ul>
<li>같은 크기 유지 → 약 900만 개의 픽셀 필요</li>
<li>픽셀 수 유지 → 이미지 크기가 2.4×2.4인치로 축소</li>
</ul>
<h3 id="핵심-원리">핵심 원리</h3>
<blockquote>
<p>픽셀이 많을수록 더 많은 이미지 정보를 담을 수 있습니다. 이 픽셀들을 얼마나 조밀하게, 어떤 크기로 표현할 것인가가 해상도의 핵심입니다.</p>
</blockquote>
<hr>
<h2 id="이미지-용량-계산-참고">이미지 용량 계산 (참고)</h2>
<p>픽셀 수가 많을수록 파일 용량도 커집니다.</p>
<h3 id="계산-예시-rgb-8bit-720×720-픽셀-이미지">계산 예시: RGB 8bit, 720×720 픽셀 이미지</h3>
<ol>
<li><strong>1픽셀 용량</strong>: 24bit (8bit × RGB 3채널) = 3byte</li>
<li><strong>총 픽셀</strong>: 720 × 720 = 518,400픽셀</li>
<li><strong>총 용량</strong>: 518,400 × 3 = 1,555,200byte</li>
<li><strong>변환</strong>:<ul>
<li>1,555,200byte ÷ 1,024 = 1,518.75KB</li>
<li>1,518.75KB ÷ 1,024 = <strong>약 1.48MB</strong></li>
</ul>
</li>
</ol>
<hr>
<h2 id="주요-용도별-권장-해상도">주요 용도별 권장 해상도</h2>
<ul>
<li><strong>웹용 이미지</strong>: 72ppi</li>
<li><strong>인쇄용 이미지</strong>: 300ppi 이상</li>
<li><strong>전문 인쇄</strong>: 600ppi 이상</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[모두를 위한 웹: 접근성(A11y) 가이드]]></title>
            <link>https://velog.io/@koo-rogie/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1A11y-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
            <guid>https://velog.io/@koo-rogie/%EB%AA%A8%EB%91%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1A11y-%EA%B0%80%EC%9D%B4%EB%93%9C</guid>
            <pubDate>Thu, 25 Jun 2026 11:59:56 GMT</pubDate>
            <description><![CDATA[<h2 id="1-웹-접근성이란">1. 웹 접근성이란?</h2>
<hr>
<blockquote>
<p>장애 유무나 사용 환경에 관계없이 모든 사람이 웹 콘텐츠를 이용할 수 있도록 보장하는 것</p>
</blockquote>
<p><strong>대상 사용자</strong></p>
<ul>
<li>시각 장애 (전맹, 저시력, 색각 이상)</li>
<li>청각 장애 (난청, 농)</li>
<li>운동 장애 (마우스 사용 불가)</li>
<li>인지 장애 (난독증, 학습 장애)</li>
</ul>
<h2 id="2-웹-접근성-왜-우리가-신경-써야-할까요">2. 웹 접근성, 왜 우리가 신경 써야 할까요?</h2>
<hr>
<p>단순히 &#39;착한 일&#39;을 하려는 것이 아닙니다. 웹 접근성은 <strong>제품의 품질</strong>과 <strong>비즈니스</strong>에 직결됩니다.</p>
<ul>
<li><strong>잠재적 고객 확보:</strong> 전 세계 인구의 15%는 크고 작은 장애를 가지고 있습니다. 접근성을 지키지 않는 것은 이 시장을 포기하는 것과 같습니다.</li>
<li><strong>법적 리스크 방지:</strong> 2013년부터 민간 사이트까지 &#39;장애인차별금지법&#39; 적용 대상이 확대되었습니다.</li>
<li><strong>검색 엔진 최적화(SEO):</strong> 구글의 검색 로봇은 눈이 없습니다. 스크린 리더처럼 텍스트를 읽기 때문에, 접근성이 좋은 사이트가 검색 결과 상단에 노출됩니다.</li>
<li><strong>상황적 장애의 해결:</strong> 햇빛이 강한 야외에서 화면을 볼 때, 한 손에 짐을 들고 마우스를 쓸 수 없을 때 등 우리 모두에게 도움이 됩니다.</li>
</ul>
<h2 id="3-이것만은-꼭-핵심-4원칙-pour">3. 이것만은 꼭! 핵심 4원칙 (POUR)</h2>
<hr>
<h3 id="31-perceivable-인식-가능">3.1 Perceivable (인식 가능)</h3>
<p><strong>&quot;눈으로 보지 못해도 정보를 얻을 수 있는가?”</strong></p>
<ul>
<li><strong>대체 텍스트:</strong> 이미지에 <code>alt</code> 속성을 넣는 것은 기본 중의 기본입니다.</li>
<li><strong>색 대비:</strong> 저시력자나 노안이 온 사용자도 읽기 쉽도록 배경과 글자색 대비를 4.5:1 이상으로 유지하세요.</li>
<li><strong>자막:</strong> 영상 콘텐츠에 소리가 없어도 내용을 알 수 있게 자막을 제공합니다.</li>
</ul>
<h3 id="32-operable-운용-가능">3.2 Operable (운용 가능)</h3>
<p><strong>&quot;마우스 없이 모든 기능을 쓸 수 있는가?&quot;</strong></p>
<ul>
<li><strong>키보드 친화적:</strong> Tab 키만으로 모든 버튼과 링크에 접근할 수 있어야 합니다.</li>
<li><strong>충분한 시간:</strong> 팝업이 너무 빨리 사라지거나, 타임아웃이 너무 짧으면 안 됩니다.</li>
</ul>
<h3 id="33-understandable-이해-가능">3.3 Understandable (이해 가능)</h3>
<p><strong>&quot;내용이 쉽고 예측 가능한가?&quot;</strong></p>
<ul>
<li><strong>일관성:</strong> 메뉴 위치가 페이지마다 바뀌면 안 됩니다.</li>
<li><strong>친절한 에러 메시지:</strong> &quot;잘못된 접근입니다&quot; 대신 &quot;비밀번호는 8자리 이상이어야 합니다&quot;처럼 해결 방법을 알려주세요.</li>
</ul>
<h3 id="34-robust-견고함">3.4 Robust (견고함)</h3>
<p><strong>&quot;어떤 환경에서도 잘 작동하는가?&quot;</strong></p>
<ul>
<li><strong>표준 준수:</strong> 최신 브라우저는 물론, 스크린 리더 같은 보조 공학 기기에서도 깨지지 않도록 표준 HTML을 사용합니다.</li>
</ul>
<hr>
<h2 id="5-개발디자인-실전-사례-bad-vs-good">5. 개발/디자인 실전 사례 (Bad vs Good)</h2>
<hr>
<h3 id="나쁜-예-vs-좋은-예">나쁜 예 vs 좋은 예</h3>
<p><strong>이미지 대체 텍스트</strong></p>
<pre><code class="language-html">&lt;!-- ❌ 나쁜 예 --&gt;
&lt;img src=&quot;icon_01.png&quot;&gt;

&lt;!-- ✅ 좋은 예 --&gt;
&lt;img src=&quot;logo.png&quot; alt=&quot;서비스 로고&quot;&gt;

&lt;!-- 장식용 이미지 --&gt;
&lt;img src=&quot;decoration.png&quot; alt=&quot;&quot;&gt;
</code></pre>
<ul>
<li><strong>Bad:</strong> <code>&lt;img src=&quot;icon_01.png&quot;&gt;</code> (스크린 리더는 &quot;이미지&quot;라고만 읽고 지나갑니다.)</li>
<li><strong>Good:</strong> <code>&lt;img src=&quot;logo.png&quot; alt=&quot;서비스 로고&quot;&gt;</code></li>
<li><strong>Deco:</strong> 장식용 이미지는 <code>alt=&quot;&quot;</code>로 비워두어야 스크린 리더가 무시합니다.</li>
</ul>
<p><strong>버튼</strong></p>
<pre><code class="language-html">&lt;!-- ❌ 나쁜 예 --&gt;
&lt;div onclick=&quot;save()&quot;&gt;저장&lt;/div&gt;

&lt;!-- ✅ 좋은 예 --&gt;
&lt;button type=&quot;button&quot; onclick=&quot;save()&quot;&gt;저장&lt;/button&gt;
</code></pre>
<ul>
<li><strong>Bad:</strong> <code>&lt;div onclick=&quot;save()&quot;&gt;저장&lt;/div&gt;</code> (키보드 탭 키로 이동이 안 됩니다.)</li>
<li><strong>Good:</strong> <code>&lt;button type=&quot;button&quot; onclick=&quot;save()&quot;&gt;저장&lt;/button&gt;</code> (가장 완벽한 방법입니다.)</li>
</ul>
<p><strong>링크 텍스트</strong></p>
<pre><code class="language-html">&lt;!-- ❌ 나쁜 예 --&gt;
&lt;a href=&quot;/product&quot;&gt;여기를 클릭하세요&lt;/a&gt;

&lt;!-- ✅ 좋은 예 --&gt;
&lt;a href=&quot;/product&quot;&gt;제품 상세 정보 보기&lt;/a&gt;
</code></pre>
<ul>
<li><strong>Bad:</strong> <code>&lt;a&gt;여기를 클릭하세요&lt;/a&gt;</code> (맥락을 알 수 없습니다.)</li>
<li><strong>Good:</strong> <code>&lt;a&gt;제품 상세 정보 보기&lt;/a&gt;</code></li>
</ul>
<hr>
<h2 id="6-wai-aria-꼭-필요할-때만-쓰는-치트키">6. WAI-ARIA: 꼭 필요할 때만 쓰는 치트키</h2>
<p>ARIA는 HTML의 부족한 부분을 채워주지만, <strong>잘못 쓰면 독</strong>이 됩니다.</p>
<ul>
<li><strong>제1원칙:</strong> &quot;HTML5 태그(<code>nav</code>, <code>button</code>, <code>section</code> 등)로 할 수 있다면 ARIA를 쓰지 마세요.&quot;</li>
<li><strong>사용 예시:</strong> 커스텀 탭 메뉴, 모달 창의 역할 정의 등 HTML만으로 설명이 부족한 동적 UI에만 적용합니다.</li>
</ul>
<hr>
<h2 id="7-우리-팀을-위한-접근성-체크리스트">7. 우리 팀을 위한 접근성 체크리스트</h2>
<ul>
<li><input disabled="" type="checkbox"> 모든 이미지에 <code>alt</code> 속성이 있는가? (의미 없는 건 <code>alt=&quot;&quot;</code>)</li>
<li><input disabled="" type="checkbox"> 마우스 없이 <code>Tab</code> 키로만 로그인이 가능한가?</li>
<li><input disabled="" type="checkbox"> 텍스트와 배경색의 대비가 명확한가?</li>
<li><input disabled="" type="checkbox"> 모든 입력창(<code>input</code>)에 이름표(<code>label</code>)가 붙어 있는가?</li>
<li><input disabled="" type="checkbox"> 페이지의 제목(<code>title</code>)이 페이지 내용을 잘 설명하는가?</li>
</ul>
<h2 id="🔗참고사이트">🔗참고사이트</h2>
<ul>
<li><p>접근성 | MDN [<a href="https://developer.mozilla.org/ko/docs/Web/Accessibility%5D">https://developer.mozilla.org/ko/docs/Web/Accessibility]</a></p>
</li>
<li><p>NULI [<a href="https://nuli.navercorp.com/%5D">https://nuli.navercorp.com/]</a></p>
</li>
<li><p>AOA11Y (Academy Of Accessibility) [<a href="https://www.youtube.com/@AOA11Y/playlists%5D">https://www.youtube.com/@AOA11Y/playlists]</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[변수 이름을 어떻게 하면 잘 지을까?]]></title>
            <link>https://velog.io/@koo-rogie/%EB%B3%80%EC%88%98-%EC%9D%B4%EB%A6%84%EC%9D%84-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EC%9E%98-%EC%A7%80%EC%9D%84%EA%B9%8C</link>
            <guid>https://velog.io/@koo-rogie/%EB%B3%80%EC%88%98-%EC%9D%B4%EB%A6%84%EC%9D%84-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%98%EB%A9%B4-%EC%9E%98-%EC%A7%80%EC%9D%84%EA%B9%8C</guid>
            <pubDate>Tue, 23 Dec 2025 12:57:43 GMT</pubDate>
            <description><![CDATA[<h1 id="0-들어가기-앞서서">0. 들어가기 앞서서</h1>
<hr>
<p>❓ 다 아는 건데 왜 이 주제를 왜 가지고 왔냐</p>
<p>🅰️ 최근 인스타를 보다가 변수 명 관련해서 영상이 하나가 떴는데 처음 안 사실들이 있어서 신기해서 파고 있어서 이런 주제를 꺼내게 됐다.</p>
<h3 id="❗주의할점">❗주의할점</h3>
<ul>
<li>js기준으로 문서가 정의되어있음.</li>
<li>다른언어를 공부하고 있는 사람에게는 2.1~2.10 방법 중 몇 개는 패스해도 좋다.</li>
</ul>
<h1 id="1-변수란">1. 변수란?</h1>
<hr>
<p>‘변수’는 어떤 공간에 어떤 값을 저장하기 위한 이름을 가진 공간이다.</p>
<h1 id="2-변수-이름을-잘-짓는-방법">2. 변수 이름을 잘 짓는 방법</h1>
<hr>
<h2 id="21-명확한-이름-사용하기">2.1 명확한 이름 사용하기</h2>
<p>영어 약어 사용 자제</p>
<p>이름만 봐도 어떤 역할을 하는지 확인 할 수 있어야 한다.</p>
<pre><code class="language-tsx">// 잘못된 예제: 축약어와 모호한 변수명 사용
const it = [];  // it가 뭐지?
let tp = 0.0;   // tp는 무슨 의미?

function al(i: string, p: number) {  // al? 무슨 함수?
  it.push(i);
  tp += p;
}

function rl(i: string, p: number) {  // rl? 무슨 동작?
  // remove 로직
  tp -= p;
}</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 명확한 변수명 활용
const items: string[] = [];
let totalPrice = 0.0;

function addItem(item: string, price: number) {
  items.push(item);
  totalPrice += price;
}

function removeItem(item: string, price: number) {
  const index = items.indexOf(item);
  items.splice(index, 1);
  totalPrice -= price;
}</code></pre>
<h2 id="22-키워드에서-제공해주는-정보-중복으로-사용하지-않기">2.2 키워드에서 제공해주는 정보 중복으로 사용하지 않기</h2>
<p>타입스크립트로 예를 들어보자</p>
<pre><code class="language-tsx">// 잘못된 예제: 타입 정보를 변수명에 중복
interface IUser {
  name: string;
  age: number;
}

let sUserName: string = &quot;구성연&quot;;
let nUserAge: number = 25;</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 타입 시스템이 이미 정보 제공
interface User {
  name: string;
  age: number;
}

let userName: string = &quot;구성연&quot;;
let userAge: number = 25;</code></pre>
<p>이미 앞에 인터페이스를 적었는데 변수 앞에 <code>I</code> 를 붙일 이유가 없고, 문자열로 타입정의를 했다면 앞에 S를 붙이지 않아도 된다.</p>
<h2 id="23-정확한-상속-관계를-보여주는-명칭-사용하기">2.3 정확한 상속 관계를 보여주는 명칭 사용하기</h2>
<pre><code class="language-tsx">// 잘못된 예제: 도대체 기본 값이 왜 필요함?
class BaseDog {}

class Dog extends BaseDog {}</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 실제적인 상속 관계의 이름을 사용
class Dog {}

// 부모 클래스에 Base같은 애매한 명칭을 사용하지말고 차라리 자식 클래스를 상세히 정의
class Puddle extends Dog {}</code></pre>
<p>클래스 명만 봤을 때 <code>BaseDog</code>와 <code>Dog</code> 가 뭐하는건지 알 수가 없음.</p>
<p>부모 클래스는 간단하게 하고 자식 클래스를 상세하게 정의하자.</p>
<h2 id="24-단위를-알-수-있는-변수-명-사용하기">2.4 단위를 알 수 있는 변수 명 사용하기</h2>
<pre><code class="language-tsx">// 잘못된 예제: 단위를 알 수 없음
let length: number = 100;
let width: number = 50.0;
let time: number = 50;
let speed: number = 99;</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 정확한 단위를 알 수 있음
let lengthMeters: number = 100;
let widthPixels: number = 50.0;
let timeSeconds: number = 50;
let speedKph: number = 99;</code></pre>
<p>타입에서 정의할 수 없는 단위들 <code>pixels</code> , <code>Meters</code> 등 알 수 있게 정의하자.</p>
<h2 id="25-일관된-네이밍-규칙-사용하기">2.5 일관된 네이밍 규칙 사용하기.</h2>
<p>개발을 처음하는 사람들이 자주하는 실수</p>
<p>❓ 왜 실수하나요?</p>
<p>🅰️ 코드는 잘 돌아가니까…</p>
<pre><code class="language-tsx">// 잘못된 예제: 네이밍 규칙이 일관되지 않음
function user_manager(user_name: string, UserAge: number) {  
    // snake_case와 PascalCase 섞임
  return {
    user_name,
    UserAge
  };
}

function UpdateUserProfile(NewName: string, new_age: number) {  
    // 파라미터도 섞여있음
  return {
    user_name: NewName,
    UserAge: new_age
  };
}

const user = user_manager(&quot;Minji&quot;, 21);
UpdateUserProfile(&quot;Alice&quot;, 22);</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 일관된 camelCase 사용
function createUser(userName: string, userAge: number) {  // camelCase
  return {
    userName,
    userAge
  };
}

function updateUserProfile(newName: string, newAge: number) {  // camelCase
  return {
    userName: newName,
    userAge: newAge
  };
}

const user = createUser(&quot;Minji&quot;, 21);
updateUserProfile(&quot;Alice&quot;, 22);</code></pre>
<h2 id="26-함수-명에서는-동사-사용하기">2.6 함수 명에서는 동사 사용하기</h2>
<p>영어가 약하신 분들이 자주 하는 실수</p>
<pre><code class="language-tsx">// 잘못된 예제: 함수명에 명사만 사용
function user(id: number) {
  return database.find(id);
}

function profile(userId: number) {
  return api.request(userId);
}</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 함수명에 동사 사용
function getUser(id: number) {
  return database.find(id);
}

function fetchProfile(userId: number) {
  return api.request(userId);
}</code></pre>
<h2 id="27-같은-개념에-여러-용어-혼동해-사용하지-않기">2.7 같은 개념에 여러 용어 혼동해 사용하지 않기</h2>
<p>데이터를 가지고 오는 <code>get</code>, <code>fetch</code></p>
<p>데이터를 지우는 <code>delete</code>, <code>remove</code></p>
<p>데이터를 생성하는 <code>create</code>, <code>add</code></p>
<p>이 중에 하나로 통일해서 사용하기.</p>
<pre><code class="language-tsx">// 잘못된 예제: 같은 동작에 다른 용어 혼용
function fetchUserData(userId: number) {
  return database.query(userId);
}

function getUserPosts(userId: number) {
  return database.query(userId);
}

function removeComment(commentId: number) {
  database.delete(commentId);
}

function deletePost(postId: number) {
  database.delete(postId);
}</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 일관된 네이밍 사용
function getUserData(userId: number) {
  return database.query(userId);
}

function getUserPosts(userId: number) {
  return database.query(userId);
}

function deleteComment(commentId: number) {
  database.delete(commentId);
}

function deletePost(postId: number) {
  database.delete(postId);
}</code></pre>
<h2 id="28-발음하기-쉬운-이름-사용하기">2.8 발음하기 쉬운 이름 사용하기</h2>
<p>내가 영어 발음이 약하다 싶으면 약어를 사용하지 말자</p>
<p>예를들면 <code>isAvailable</code> 을 어떻게 발음해야할지도 모르겠는데 약어로 써놓으면 더 모르니까 영어를 모르겠다 싶으면 약어 말고 영어 원문 그대로 써놓는게 좋다</p>
<pre><code class="language-tsx">// 잘못된 예제: 축약어 사용
function chkUsrAge(usrAge: number): boolean {
  return usrAge &gt;= 18;
}

const isVld = chkUsrAge(20);  // Valid 축약</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 읽기 쉬운 변수명
function checkUserAge(userAge: number): boolean {
  return userAge &gt;= 18;
}

const isValid = checkUserAge(20);</code></pre>
<h2 id="29-검색-가능한-이름-사용하기">2.9 검색 가능한 이름 사용하기</h2>
<p>예를 들어보자</p>
<p>시간이라는 이름을 영어로 검색하고 싶은데 어떤 블로그에서는 시간을 <code>t</code>로 줄여서 말하면 검색하기 까다로울 것이다. 그러면 블로그를 작성한 사람도 <code>t</code>가 어떤걸 말하는지 햇갈릴것이다.</p>
<pre><code class="language-tsx">// 잘못된 예제: 의미 없는 짧은 변수명
function calculateDuration(t: number): number {
  return t * 60;  // t가 뭐지? 초? 분? 시간?
}</code></pre>
<pre><code class="language-tsx">// 올바른 예제: 검색하기 쉬운 명확한 변수명
function calculateDuration(timeMinutes: number): number {
  return timeMinutes * 60;  // IDE에서 &#39;time&#39; 검색하면 바로 찾을 수 있음
}</code></pre>
<h2 id="210-언어별-스타일-가이드-준수하기">2.10 언어별 스타일 가이드 준수하기</h2>
<p>언어별 가이드 라인이 있으면 가이드라인을 준수하는게 좋다.</p>
<p>A언어에서 사용하는 가이드라인을 B라는 언어에 접목시키지 말라는 소리이다.</p>
<ul>
<li><strong>JS/TS/Java/C++/C#</strong>: <code>camelCase</code></li>
<li><strong>Python/C</strong>: <code>snake_case</code></li>
</ul>
<pre><code class="language-jsx">// JavaScript
const userName = &quot;Alice&quot;;
const isActive = true;
const userAge = 25;</code></pre>
<pre><code class="language-tsx">// TypeScript
const userName: string = &quot;Alice&quot;;
const isActive: boolean = true;
const userAge: number = 25;</code></pre>
<pre><code class="language-java">// Java
String userName = &quot;Alice&quot;;
boolean isActive = true;
int userAge = 25;</code></pre>
<pre><code class="language-cpp">// C++
string userName = &quot;Alice&quot;;
bool isActive = true;
int userAge = 25;</code></pre>
<pre><code class="language-csharp">// C#
string userName = &quot;Alice&quot;;
bool isActive = true;
int userAge = 25;</code></pre>
<hr>
<pre><code class="language-python"># Python
user_name = &quot;Alice&quot;
is_active = True
user_age = 25</code></pre>
<pre><code class="language-c">// C
char user_name[] = &quot;Alice&quot;;
int is_active = 1;
int user_age = 25;</code></pre>
<h1 id="💡-참고사이트">💡 참고사이트</h1>
<p><a href="https://www.instagram.com/reel/DSP4W8djGib/?igsh=MW4xd3lsZ3dka2ZjZQ==">Asfar Ali on Instagram: &quot;Your code is read by humans, so make it sound like human language  #cleancode #code #programming&quot;</a></p>
<p><a href="https://brunch.co.kr/@team-thecompass/25">사수한테 칭찬받는 읽기 좋은 함수, 변수명 잘 짓는 법</a></p>
<p><a href="https://www.youtube.com/watch?v=dQzsgQnpufk">변수 이름 작명 마스터클래스</a></p>
<p><a href="https://brunch.co.kr/@wapj2000/29">변수명을 잘 짓기 위한 몸부림</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 개발자인데 SQL을 배워야할까?]]></title>
            <link>https://velog.io/@koo-rogie/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%B8%EB%8D%B0-SQL%EC%9D%84-%EB%B0%B0%EC%9B%8C%EC%95%BC%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@koo-rogie/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%B8%EB%8D%B0-SQL%EC%9D%84-%EB%B0%B0%EC%9B%8C%EC%95%BC%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Tue, 23 Dec 2025 12:56:57 GMT</pubDate>
            <description><![CDATA[<h2 id="q-sql발표를-왜-하게-되었느냐">Q. SQL발표를 왜 하게 되었느냐?</h2>
<p>A.  아이스 브레이킹 시간에 빠지지 않고 SQL이야기가 나오는 것을 느꼈고 그래서 SQL이 뭔데? 라는 궁금증에서 출발했습니다.</p>
<hr>
<h1 id="1-sql이란">1. SQL이란</h1>
<p>SQL(Structured Query Language)은 데이터베이스와 대화하는 언어입니다.</p>
<p>웹사이트에 있는 거의 모든 데이터는 데이터베이스에 저장되어 있습니다.</p>
<ul>
<li>유저 정보 (이름, 이메일, 비밀번호)</li>
<li>게시글 (제목, 내용, 작성자)</li>
<li>댓글, 좋아요, 주문 내역...</li>
</ul>
<p>SQL은 이런 데이터를 가져오거나 저장하거나 수정할 때 사용합니다.</p>
<p><strong>쉽게 말하면:</strong></p>
<p>&quot;users 테이블에서 나이가 20살 이상인 사람들 보여줘&quot;
&quot;posts 테이블에 새 게시글 저장해줘&quot;</p>
<p>이런 명령을 데이터베이스에게 내리는 언어입니다.</p>
<hr>
<h1 id="2-프론트엔드는-sql을-직접-안-쓰는데-왜">2. 프론트엔드는 SQL을 직접 안 쓰는데 왜?</h1>
<p><strong>맞습니다. 프론트엔드는 SQL을 직접 쓰지 않습니다.</strong></p>
<p>프론트엔드 개발자가 하는 일:</p>
<ul>
<li>API를 호출해서 데이터 받아오기</li>
<li>받은 데이터를 화면에 예쁘게 보여주기</li>
</ul>
<p>백엔드 개발자가 하는 일:</p>
<ul>
<li>API를 만들고</li>
<li>SQL로 데이터베이스에서 데이터를 가져와서</li>
<li>프론트엔드에게 전달하기</li>
</ul>
<p><strong>그럼 왜 프론트엔드가 SQL을 알아야 하냐고요?</strong></p>
<p>백엔드 개발자와 협업할 때 소통이 안 되는 문제가 생깁니다.</p>
<p>예시:</p>
<ul>
<li>프론트: &quot;유저 목록이랑 각 유저가 쓴 글 개수 주세요&quot;</li>
<li>백엔드: &quot;JOIN 해야 하는데 N+1 문제가...&quot;</li>
<li>프론트: &quot;...???&quot;</li>
</ul>
<p>이런 상황이 반복되면 답답합니다.</p>
<hr>
<h1 id="3-프론트엔드가-sql-개념과-마주치는-순간">3. 프론트엔드가 SQL 개념과 마주치는 순간</h1>
<h3 id="상황-1-사이드-프로젝트-할-때">상황 1: 사이드 프로젝트 할 때</h3>
<p>혼자 간단한 웹사이트 만들다가 데이터 저장이 필요해집니다.
&quot;어... 데이터를 어디에 어떻게 저장하지?&quot;
결국 유튜브 보면서 따라하는데 테이블을 어떻게 만들어야 하는지 감이 안 옵니다.</p>
<h3 id="상황-2-ai-도구cursor-chatgpt-쓸-때"><strong>상황 2: AI 도구(Cursor, ChatGPT) 쓸 때</strong></h3>
<p>Cursor한테 &quot;데이터베이스 설계해줘&quot;라고 물어봅니다.
답변이 SQL로 주르륵 나오는데, 이게 맞는지 틀린지 판단을 못 합니다.
SQL을 알면 AI 답변을 제대로 활용할 수 있습니다.</p>
<h3 id="상황-3-api-응답-데이터-순서가-이상할-때">상황 3: API 응답 데이터 순서가 이상할 때</h3>
<p>API로 게시글 목록을 받았는데 순서가 1-3-4-2-5 이렇게 뒤죽박죽입니다.
백엔드: &quot;데이터는 다 줬는데요?&quot;
프론트: &quot;근데 순서가 이상해요...&quot;</p>
<p>SQL을 알면: &quot;ORDER BY id DESC 빠진 것 같은데 추가해주세요&quot; → 바로 해결</p>
<p>SQL을 모르면: 프론트에서 sort() 써서 임시방편... (근본 해결 안 됨)</p>
<hr>
<h1 id="4-sql을-알면-좋은-점">4. SQL을 알면 좋은 점</h1>
<h3 id="백엔드와-말이-통함">백엔드와 말이 통함</h3>
<p>예: 백엔드가 &quot;인덱스 없어서 이 필드로는 정렬 못 해요&quot;라고 하면
→ &quot;아 그럼 created_at 같은 다른 필드로 정렬하면 되겠네요&quot; 바로 대안 제시
SQL 모르면: &quot;...왜요? 그냥 정렬 하면 안돼요?&quot; (답답)</p>
<h3 id="api를-똑똑하게-요청할-수-있음">API를 똑똑하게 요청할 수 있음</h3>
<p>막연하게: &quot;유저 목록이랑 게시글 개수 주세요&quot;
구체적으로: &quot;users랑 posts JOIN해서 COUNT 집계한 결과 주세요&quot;
백엔드도 바로 이해하고 개발 속도 빨라집니다.</p>
<h3 id="속도가-왜-느린지-알-수-있음">속도가 왜 느린지 알 수 있음</h3>
<p>페이지 느릴 때
&quot;프론트 렌더링 문제인가? 백엔드 쿼리 문제인가?&quot;
구분할 수 있어서 문제를 빨리 찾습니다.</p>
<p>예: &quot;API 100번 호출하고 있네? N+1 문제다&quot; → JOIN으로 한 번에 해결 요청</p>
<h3 id="혼자서도-뭔가-만들-수-있음">혼자서도 뭔가 만들 수 있음</h3>
<p>간단한 앱 만들 때 백엔드 없이도 직접 데이터 저장하고 가져올 수 있습니다.
Supabase 같은 도구 쓸 때도 SQL 알면 훨씬 쉽습니다.
풀스택 개발자로 갈 수 있는 길이 열립니다.</p>
<hr>
<h1 id="5-현실적인-이야기">5. 현실적인 이야기</h1>
<h3 id="프론트는-이미-배울-게-너무-많습니다">프론트는 이미 배울 게 너무 많습니다</h3>
<p>Next.js, React, TypeScript, 상태관리, CSS, 성능 최적화, 웹 접근성...
프론트엔드만 해도 평생 배워야 합니다.
SQL까지 깊게 파면 정작 중요한 프론트 기술이 부족해질 수 있습니다.</p>
<h3 id="실무에서-쿼리-짤-일은-거의-없습니다">실무에서 쿼리 짤 일은 거의 없습니다</h3>
<p>대부분 회사는 백엔드와 프론트가 명확히 분리되어 있습니다.
프론트엔드가 직접 데이터베이스를 건드리는 일은 없습니다.</p>
<hr>
<h1 id="6-결론">6. 결론</h1>
<h3 id="프론트엔드도-sql을-배워야-할까">프론트엔드도 SQL을 배워야 할까?</h3>
<p><strong>무조건 배워야 한다 ❌</strong></p>
<p><strong>알면 분명히 도움된다 ✅</strong></p>
<p>❗출처</p>
<p><a href="https://velog.io/@eunnbi/Project-%EB%B0%B1%EC%97%94%EB%93%9C%EC%99%80-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0">[Project] 백엔드와 협업하기</a></p>
<p><a href="https://okky.kr/articles/575663">프론트엔드 신입개발자가 sql도 다루나요? | OKKY</a></p>
<p><a href="https://hyung1.tistory.com/90">프론트엔드 개발자가 SQL을 공부하는 이유</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[git branch]]></title>
            <link>https://velog.io/@koo-rogie/git-branch</link>
            <guid>https://velog.io/@koo-rogie/git-branch</guid>
            <pubDate>Tue, 23 Dec 2025 12:56:09 GMT</pubDate>
            <description><![CDATA[<h2 id="0-들어가기-앞서서-용어-정리">0. 들어가기 앞서서 용어 정리</h2>
<table>
<thead>
<tr>
<th>용어</th>
<th>설명</th>
<th>이번 발표 사용</th>
</tr>
</thead>
<tbody><tr>
<td><strong>저장소 (repository)</strong></td>
<td>프로젝트 파일과 해당 파일의 변경 이력이 저장되는 곳이다. 로컬 저장소, 원격 저장소 두 종류가 있다.</td>
<td>✅</td>
</tr>
<tr>
<td><strong>커밋 (commit)</strong></td>
<td>파일 또는 디렉토리의 변경 사항을 로컬 저장소에 기록한다. 커밋은 변경 내용, 작성자, 날짜 같은 정보와 함께 고유한 ID를 가진다. ID를 통해 특정 시점의 프로젝트 상태로 돌아갈 수 있다.</td>
<td>✅</td>
</tr>
<tr>
<td><strong>브랜치 (Branch)</strong></td>
<td>작업을 분리하기 위한 수단이다. 주로 “master” 또는 “main” 브랜치가 주 브랜치로 사용된다. 기능 추가, 버그 수정 등을 위해서 새로운 브랜치를 생성하여 작업한다.</td>
<td>✅</td>
</tr>
<tr>
<td>병합 (Merge)</td>
<td>두 브랜치의 변경 사항을 하나로 합치는 과정이다.</td>
<td>✅</td>
</tr>
<tr>
<td>충돌 (Conflict)</td>
<td>두 브랜치를 병합할 때 같은 파일의 같은 부분이 다르게 수정되어 Git이 병합할 수 없는 상황이다</td>
<td>❌</td>
</tr>
<tr>
<td>풀 (Pull)</td>
<td>원격 저장소의 변경 사항을 로컬 저장소로 가져오고 자동으로 현재 브랜치와 병합하는 과정이다.</td>
<td>✅</td>
</tr>
<tr>
<td>푸시 (Push)</td>
<td>로컬 저장소의 변경 사항을 원격 저장소로 업로드하는 과정이다.</td>
<td>✅</td>
</tr>
<tr>
<td>패치 (Fetch)</td>
<td>원격 저장소의 최신 history를 로컬 저장소로 가져오지만, 현재 작업 중인 브랜치와는 병합하지 않는다.</td>
<td>❌</td>
</tr>
<tr>
<td>스태이징 (Staging)</td>
<td>커밋 전 변경 사항을 준비하는 단계이다.</td>
<td>❌</td>
</tr>
<tr>
<td>태그 (Tag)</td>
<td>특정 커밋을 참조하기 위한 레이블이다.</td>
<td>❌</td>
</tr>
<tr>
<td>체크아웃 (Checkout)</td>
<td>다른 브랜치로 전환하거나 특정 버전의 파일을 작업 디렉토리로 가져오는 과정이다.</td>
<td>✅</td>
</tr>
<tr>
<td>클론 (clone)</td>
<td>원격 저장소의 복사본을 로컬 저장소에 생성한다.</td>
<td>❌</td>
</tr>
<tr>
<td>포크 (Fork)</td>
<td>다른 사용자의 원격 저장소를 자신의 원격 저장소로 복사하는 과정이다.</td>
<td>❌</td>
</tr>
<tr>
<td>풀 리퀘스트 (Pull Request)</td>
<td>PR은 하나의 브랜치에서 다른 브랜치로 변경사항을 병합하기 위한 요청이다.</td>
<td>✅</td>
</tr>
</tbody></table>
<h1 id="1-git-branch-전략">1. git branch 전략</h1>
<hr>
<p>여러 개발자가 하나의 저장소에서 작업을 할 때 협업을 좀 더 효과적으로 하기 위해</p>
<p><code>git branch</code> 에 대한 규칙을 정하고 저장소를 잘 활용하기 위한 <code>workflow</code> 를 정의하는 것을 바로 <strong>git branch 전략</strong>이라고 합니다.</p>
<h3 id="❓-이러한-git-branch-전략은-왜-필요한가">❓ 이러한 Git Branch 전략은 왜 필요한가</h3>
<p>여러 명의 개발자가 동시에 작업할 때 가장 빛을 발하는데요, 각자 다른 기능을 담당하는 브랜치를 사용하여 작업하면,</p>
<p>개발 중인 기능이나 수정사항이 서로 독립적이게 되며 영향을 주지 않고 동시에 진행될 수 있습니다.</p>
<p>또한, 각각의 브랜치가 특정 기능, 이슈에 대응하여 특정 작업을 추적하고, 필요한 경우 작업 단위의 Rollback 이 가능하여 프로젝트 관리의 유연성을 향상시켜줍니다.</p>
<p>각각의 태그는 Release 를 원하는 버전 단위로 관리할 수 있도록 하여, 배포 안정성을 향상시켜줍니다.</p>
<h3 id="❓브랜치-전략이-없으면-어떤-일이-발생하는가">❓브랜치 전략이 없으면 어떤 일이 발생하는가</h3>
<ul>
<li>어떤 브랜치가 최신 브랜치지?</li>
<li>어떤 브랜치를 끌어와서 개발을 시작해야 하지?</li>
<li>어디에 Push를 보내야 하지?</li>
<li>핫픽스를 해야하는데 어떤 브랜치를 기준으로 수정해야할까?</li>
<li>배포 버전은 어떤 걸 골라야하지?</li>
</ul>
<p>Git Branch 전략은 여러가지가 있지만, 대표적으로 여러 프로젝트에서 널리 사용되고 있는 두가지 대표 브랜치 전략인 Git Flow 와 GitHub Flow 에 대해서 알아보도록 하겠습니다.</p>
<h2 id="11-git-flow">1.1 <strong>Git Flow</strong></h2>
<hr>
<p>가장 전통적으로 많이 사용되는 방식이다.</p>
<p><img src="attachment:4472e409-ebab-4bcc-aba6-e3d4d61e3290:6c564810665399f6549ed2bffc7e763c7e39f5fab128a3442ddeb44ee6593c04.png" alt="6c564810665399f6549ed2bffc7e763c7e39f5fab128a3442ddeb44ee6593c04.png"></p>
<ul>
<li>기본적인 가지의 이름은 아래의 5가지로 구분하곤 한다.</li>
<li><strong>feature &gt; develop &gt; release &gt; hotfix &gt; master</strong></li>
<li>위 순서들은 왼쪽으로 갈수록 포괄적인 가지이며 master branch를 병합할 경우 그 왼쪽에 있는 hotfix 등 모든 가지들에 있는 커밋들도 병합하도록 구성하게 된다.</li>
<li>5가지 중, <strong>항시 유지되는 메인 브랜치 master, develop</strong> 2가지와 <strong>merge 되면 사라지는 보조 브랜치 feature, release, hotfix</strong> 3가지로 구성된다.</li>
</ul>
<h3 id="111-브랜치-별-설명">1.1.1 브랜치 별 설명</h3>
<h3 id="1111-메인-브랜치master-develop">1.1.1.1 메인 브랜치(<code>master</code>, <code>develop</code>)</h3>
<p><img src="attachment:e05eb84d-592b-4ee4-9a91-ddc894d5e5c6:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>master는 배포 가능한 상태만을 관리하는 브랜치를 말하며</p>
<p>develop은 다음에 배포할 것을 개발하는 브랜치이다.</p>
<p>즉 develop은 통합 브랜치의 역할을 하며, 평소에는 이 브랜치를 기반으로 개발을 진행한다.</p>
<h3 id="1112-보조-브랜치">1.1.1.2 보조 브랜치</h3>
<p>보조 브랜치는 피처 브랜치(feature branch) 또는 토픽 브랜치(topic branch)를 말한다.</p>
<p><img src="attachment:62413f10-b629-4656-af7a-416c4d6675c6:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<ul>
<li>가지가 뻗어나오는 곳 : develop</li>
<li>뻗어나갔던 가지가 다시 합쳐지는 곳 : develop</li>
<li>이름 설정 : master, develop, release-<em>, hotfix-</em>를 제외하기만 하면 자유롭게 이름 설정이 가능하다.
새로운 기능을 추가할 때 주로 사용하는 가지이다.</li>
</ul>
<p>develop 브랜치에는 기존에 잘 작동하는 개발코드가 담겨있으며, </p>
<p>보조 브랜치는 새로 변경될 개발코드를 분리하고 각각 보존하는 역할을 한다.</p>
<p>즉, 보조 브랜치는 기능을 다 완성할 때까지 유지하고, 다 완성되면 develop 브랜치로 merge 하고 결과가 좋지 못하면 버리는 방향을 취한다.</p>
<h3 id="1113-릴리즈-브랜치release-branch">1.1.1.3 릴리즈 브랜치(release branch)</h3>
<p>릴리즈 브랜치는 배포를 위한 최종적인 버그 수정 등의 개발을 수행하는 브랜치를 말한다.</p>
<p><img src="attachment:236e5ef7-43db-48d3-8636-087674d1f44d:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<ul>
<li>가지가 뻗어나오는 곳 : develop</li>
<li>뻗어나갔던 가지가 다시 합쳐지는 곳 : develop, master</li>
<li>이름 설정 : release-*</li>
<li>새로운 제품을 배포하고자 할 때 사용하는 가지이다.</li>
</ul>
<p>develop 브랜치에 버전에 포함되는 기능이 merge 되었다면 QA를 위해 develop 브랜치에서부터 release 브랜치를 생성한다. </p>
<p>배포 가능한 상태가 되면 master 브랜치로 병합시키고, 출시된 master 브랜치에 버전 태그(ex, v1.0, v0.2)를 추가한다.</p>
<p>release 브랜치에서 기능을 점검하며 발견한 버그 수정 사항은 develop 브랜치에도 적용해줘야 한다.
그러므로 배포 완료 후 develop 브랜치에 대해서도 merge 작업을 수행해야 한다.</p>
<h3 id="1114-핫픽스-브랜치hotfix-branch">1.1.1.4 핫픽스 브랜치(hotfix branch)</h3>
<p>핫픽스 브랜치는 배포한 버전에서 긴급하게 수정할 필요가 있을 때 master 브랜치에서 분리하는 브랜치를 말한다.</p>
<p><img src="attachment:6e97fba4-7edd-4814-936a-5956c1f65606:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<ul>
<li>가지가 뻗어나오는 곳 : master</li>
<li>뻗어나갔던 가지가 다시 합쳐지는 곳 : develop, master</li>
<li>이름 설정 : hotfix-*</li>
<li>제품에서 버그가 발생했을 경우에는 처리를 위해 이 가지로 해당 정보들을 모아준다. 버그에 대한 수정이 완료된 후에는 develop, master에 곧장 반영해주며 tag를 통해 관련 정보를 기록해둔다.</li>
</ul>
<p>버그를 잡는 사람이 일하는 동안에도 다른 사람들은 develop 브랜치에서 하던 일을 계속할 수 있다.</p>
<p>이 때 만든 hotfix 브랜치에서의 변경 사항은 develop 브랜치에도 merge 하여 문제가 되는 부분을 처리해줘야 한다.</p>
<p>release 가지가 생성되어 관리되고 있는 상태라면 해당 가지에 hotfix정보를 병합시켜 다음번 배포 시 반영이 정상적으로 이루어질 수 있도록 해준다.</p>
<p>Hotfix는 보통 다급하게 버그를 고치기 위해 생성되는 가지이기 때문에 버그를 해결하면 보통 제거하는 일회성 가지다.</p>
<h3 id="112-git-flow-정리">1.1.2 Git Flow 정리</h3>
<hr>
<h3 id="1121-신규-기능-개발">1.1.2.1 신규 기능 개발</h3>
<p><img src="attachment:a4bcd2d4-91bf-4dc5-9cba-0549b1dc17bc:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<ol>
<li>개발자는 develop 브랜치로부터 본인이 신규 개발할 기능을 위한 feature 브랜치를 생성한다. </li>
<li>feature 브랜치에서 기능을 완성하면 develop 브랜치에 merge를 진행하게 된다.</li>
</ol>
<h3 id="1122-라이브-서버로-배포">1.1.2.2 라이브 서버로 배포</h3>
<p><img src="attachment:4acf90f9-94b2-4c18-8a70-a5d20d67b973:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<ol>
<li>feature 브랜치들이 모두 develop 브랜치에 merge 되었다면 QA를 위해 release 브랜치를 생성한다. </li>
<li>release 브랜치를 통해 오류가 확인된다면 release 브랜치 내에서 수정을 진행한다.</li>
<li>QA와 테스트를 모두 통과했다면, 배포를 위해 release 브랜치를 master 브랜치 쪽으로 merge하며,</li>
<li>만일 release 브랜치 내부에서 오류 수정이 진행되었을 경우 동기화를 위해 develop 브랜치 쪽에도 merge를 진행한다.</li>
</ol>
<h3 id="1123-배포-후-관리">1.1.2.3 배포 후 관리</h3>
<p><img src="attachment:549d85bf-eecf-4246-84eb-b20687c2a216:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<ol>
<li>만일 배포된 라이브 서버(master)에서 버그가 발생된다면, hotfix 브랜치를 생성하여 버그 픽스를 진행한다.</li>
<li>그리고 종료된 버그 픽스를 master와 develop 양 쪽에 merge하여 동기화 시킨다.</li>
</ol>
<h2 id="12-github-flow">1.2 GitHub Flow</h2>
<hr>
<p><img src="attachment:75a819b8-82fc-48b0-99c3-9dde1ee54e49:0d231fe21e58bd49c9367c990287f6f7d68d0fb8a37afd650992bfc91523cb8a.png" alt="0d231fe21e58bd49c9367c990287f6f7d68d0fb8a37afd650992bfc91523cb8a.png"></p>
<p>release branch가 명확하게 구분되지 않은 시스템에서의 사용이 유용하다.</p>
<p>GitHub 자체의 서비스 특성상 배포의 개념이 없는 시스템으로 되어있기 때문에 이 flow가 유용하다.</p>
<p>웹 서비스들에 배포의 개념이 없어지고 있는 추세이기 때문에 앞으로도 Git flow에 비해 사용하기에 더 수월할 것이다.</p>
<p>hotfix와 가장 작은 기능을 구분하지 않는다. 모든 구분사항들도 결국 개발자가 전부 수정하는 일들 중 하나이기 때문이다. 이 대신 구분하는 것은 우선 순위가 어떤 것이 더 높은지에 대한 것이다.</p>
<h3 id="121-흐름">1.2.1 흐름</h3>
<hr>
<h3 id="1211-브랜치-생성">1.2.1.1 브랜치 생성</h3>
<p><img src="attachment:ab2f6036-beb9-4e32-a982-5efb7c78d906:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>Github-flow 전략은 기능 개발, 버그 픽스 등 어떤 이유로든 새로운 브랜치를 생성하는 것으로 시작된다.</p>
<p>단, 이때 체계적인 분류 없이 브랜치 하나에 의존하게 되기 때문에 브랜치 이름을 통해 의도를 명확하게 드러내는 것이 매우 중요하다.</p>
<ul>
<li>master 브랜치는 항상 최신 상태며, stable 상태로 product에 배포되는 브랜치다. 이 브랜치에 대해서는 엄격한 role과 함께 사용한다</li>
<li>새로운 브랜치는 항상 master 브랜치에서 만든다</li>
<li>Git-flow와는 다르게 feature 브랜치나 develop 브랜치가 존재하지 않는다.</li>
<li>그렇지만, 새로운 기능을 추가하거나 버그를 해결하기 위한 브랜치 이름은 자세하게 어떤 일을 하고 있는지에 대해서 작성해주도록 하자</li>
</ul>
<h3 id="1212-개발-커밋-푸쉬">1.2.1.2 개발, 커밋, 푸쉬</h3>
<p><img src="attachment:2e6db81e-895f-4014-a711-70b1f1faba02:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>개발을 진행하면서 커밋을 남긴다.이때도 브랜치와 같이 커밋 메세지에 의존해야 하기 때문에, 커밋 메세지를 최대한 상세하게 적어주는 것이 중요하다.</p>
<ul>
<li>커밋메시지를 명확하게 작성하자</li>
<li>원격지 브랜치로 수시로 push 하자</li>
<li>Git-flow와 상반되는 방식</li>
<li>항상 원격지에 자신이 하고 있는 일들을 올려 다른 사람들도 확인할 수 있도록 해준다</li>
<li>이는 하드웨어에 문제가 발생해 작업하던 부분이 없어지더라도, 원격지에 있는 소스를 받아서 작업할 수 있도록 해준다</li>
</ul>
<h3 id="1213-pr-생성">1.2.1.3 PR 생성</h3>
<p><img src="attachment:3650b341-63d4-425b-9342-acce9ec52a0f:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>피드백이나 도움이 필요할 때, 그리고 merge 준비가 완료되었을 때는 pull request를 생성한다</p>
<ul>
<li>pull request는 코드 리뷰를 도와주는 시스템</li>
<li>이것을 이용해 자신의 코드를 공유하고, 리뷰받는다.</li>
<li>merge 준비가 완료되었다면 master 브랜치로 반영을 요구한다.</li>
</ul>
<h3 id="1214-리뷰-토의">1.2.1.4 리뷰, 토의</h3>
<p><img src="attachment:fe039e4d-d634-4574-a50c-dcc5937951ca:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>Pull-Request가 master 브랜치 쪽에 합쳐진다면 곧장 라이브 서버에 배포되는 것과 다름 없으므로, 상세한 리뷰와 토의가 이루어져야 한다.</p>
<h3 id="1215-테스트">1.2.1.5 테스트</h3>
<p><img src="attachment:d7548ba6-f180-44aa-bcc2-2856f9803545:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>리뷰와 토의가 끝났다면 해당 내용을 라이브 서버(혹은 테스트 환경)에 배포해본다.</p>
<p>배포시 문제가 발생한다면 곧장 master 브랜치의 내용을 다시 배포하여 초기화 시킨다.</p>
<h3 id="1216-최종-merge">1.2.1.6 최종 Merge</h3>
<p><img src="attachment:ee59c98c-fe49-41bf-9677-10bfc792caa0:img1.daumcdn.png" alt="img1.daumcdn.png"></p>
<p>라이브 서버(혹은 테스트 환경)에 배포했음에도 문제가 발견되지 않았다면 그대로 master 브랜치에 푸시를 하고, 즉시 배포를 진행한다.</p>
<p>대부분의 Github-flow 에선 master 브랜치를 최신 브랜치라고 가정하기 때문에 배포 자동화 도구를 이용해서 Merge 즉시 배포를 시킨다.</p>
<p><strong>master로 merge되고 push 되었을 때는, 즉시 배포되어야한다</strong></p>
<ul>
<li>GitHub-flow의 핵심</li>
<li>master로 merge가 일어나면 자동으로 배포가 되도록 설정해놓는다. (CI / CD)</li>
</ul>
<h2 id="13-❗-git-flow-와-github-flow-중-어떤-전략을-사용해야-할까">1.3 ❗ <strong>Git Flow 와 GitHub Flow 중 어떤 전략을 사용해야 할까?</strong></h2>
<p>Git Flow 와 GitHub Flow 중 어떤 전략을 사용하는게 좋을까요? 다양한 관점에서 두 전략을 비교해보겠습니다.</p>
<ol>
<li><p>브랜치 수: Git Flow는 다양한 종류의 브랜치를 사용하는 반면, GitHub Flow는 단일 브랜치 (<code>master</code>) 를 사용합니다.</p>
</li>
<li><p>배포 방식: Git Flow는 <code>release</code> 와 <code>hotfix</code> 브랜치를 통해 명확한 배포 절차를 갖추고 있습니다.</p>
<p> 반면에, GitHub Flow는 단순하며 지속적인 배포를 강조하며, <code>master</code> 브랜치에서 배포를 수행합니다.</p>
</li>
<li><p>복잡성: Git Flow는 복잡한 프로젝트나 대규모 팀에서 사용하기 좋습니다.</p>
<p> 그러나 이는 작은 팀이나 개인 프로젝트에 적용하기에는 많은 브랜치와 과정이 불필요하고 부담스러울 수 있습니다.</p>
<p> GitHub Flow 는 단순하며 빠른 개발 및 배포를 위해 사용됩니다.</p>
</li>
</ol>
<p>각각의 전략은 장, 단점이 존재하기에 프로젝트의 규모, 요구 사항 및 팀의 작업 방식에 맞추어 적절하게 채택하는 것이 좋습니다.</p>
<p><code>Git Flow</code>는 더 많은 제어와 복잡성을 가지고 있어 특정 기능이나 수정을 빠르게 배포해야 할 경우 등에서 유연성이 다소 떨어집니다.</p>
<p>그러나 그만큼 배포 안정성과 버전 관리 및 롤백 등 체계적인 운영이 가능합니다.</p>
<p><code>GitHub Flow</code> 는 테스트와 검증 절차를 거치지 않고 바로 <code>master</code> 브랜치로 Merge 되므로 위험성을 가지고 있습니다.</p>
<p>하지만 그만큼 단순하고 빠르게 기능을 테스트하고 Agile 하게 배포할 수 있기 때문에, 주로 각 환경의 구분이 명확하지 않고 작은 규모의 프로젝트에 적합한 전략입니다.</p>
<h3 id="💡-참고-자료">💡 참고 자료</h3>
<p><a href="https://techblog.woowahan.com/2553/">우린 Git-flow를 사용하고 있어요 | 우아한형제들 기술블로그</a></p>
<p><a href="https://dntmdgns03.tistory.com/80">[GitHub] 기본 용어 정리</a></p>
<p><a href="https://inpa.tistory.com/entry/GIT-%E2%9A%A1%EF%B8%8F-github-flow-git-flow-%F0%9F%93%88-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EC%A0%84%EB%9E%B5">[GIT] 📈 깃 브랜치 전략 정리 - Github Flow / Git Flow</a></p>
<p><a href="https://devocean.sk.com/blog/techBoardDetail.do?ID=165571&amp;boardType=techBlog">Git Branch 전략 비교 - Git Flow vs GitHub Flow</a></p>
<p><a href="https://velog.io/@kw2577/Git-branch-%EC%A0%84%EB%9E%B5">Git branch 전략(Git-Flow, Github-Flow, Gitlab-Flow)</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[next.js page 라우터 vs app 라우터]]></title>
            <link>https://velog.io/@koo-rogie/next.js-page-%EB%9D%BC%EC%9A%B0%ED%84%B0-vs-app-%EB%9D%BC%EC%9A%B0%ED%84%B0</link>
            <guid>https://velog.io/@koo-rogie/next.js-page-%EB%9D%BC%EC%9A%B0%ED%84%B0-vs-app-%EB%9D%BC%EC%9A%B0%ED%84%B0</guid>
            <pubDate>Tue, 23 Dec 2025 12:54:27 GMT</pubDate>
            <description><![CDATA[<h1 id="1-pages-router"><strong>1. Pages Router</strong></h1>
<p>Pages Router는 Next.js의 전통적인 라우팅 시스템입니다. </p>
<p>이 시스템은 파일 시스템 기반 라우팅을 사용하며, <code>pages</code> 디렉토리 내의 파일 구조가 곧 애플리케이션의 라우트 구조가 됩니다.</p>
<p>많은 기업에서 사용되고 있는 안정적인 라우터</p>
<h2 id="주요-특징"><strong>주요 특징</strong></h2>
<ul>
<li><code>pages</code> 디렉토리 사용</li>
<li>파일 이름 기반의 라우팅</li>
<li><code>getStaticProps</code>, <code>getServerSideProps</code> 등을 통한 데이터 페칭</li>
<li>간단하고 직관적인 구조</li>
</ul>
<h2 id="11-router">1.1 router</h2>
<h2 id="111-파일명-기준">1.1.1 파일명 기준</h2>
<p>pages라는 폴더안에 기능을 제공함.</p>
<p>pages폴더 안 컨포넌트파일명 기반의 페이지 라우팅을 자동으로 제공함.</p>
<p>ex)</p>
<ul>
<li>index.js → ~/</li>
<li>about.js → ~/<strong>about</strong></li>
<li>item.js → ~/<strong>item</strong></li>
</ul>
<h2 id="112-폴더-명기준">1.1.2 폴더 명기준</h2>
<p>about.js 파일이 없으니 폴더안에 있는 index.js 컨포넌트를 찾아 랜더링함.</p>
<h2 id="113-동적-경로dynamic-rotes">1.1.3 동적 경로(Dynamic Rotes)</h2>
<p><strong>동적 경로란 경로 상의 어떠한 변할 수 있는 가변적인 값을 포함하고 있는 경로를 말함</strong> </p>
<p>예시) 블로그의 게시글, 쇼핑물의 상품별 상세페이지</p>
<p>동적 라우팅을 만들고 싶으면 파일명, 폴더명에 대괄호를 묶어서 사용한다</p>
<p>ex) <code>[id]</code>,  <code>[bookid]</code></p>
<p>매핑된다.</p>
<h2 id="12-getserversideprops-활용">1.2 getServerSideProps 활용</h2>
<pre><code class="language-tsx">import { useState } from &quot;react&quot;;

const URL =
  &quot;https://www.7timer.info/bin/astro.php?lon=113.2&amp;lat=23.1&amp;ac=0&amp;unit=metric&amp;output=json&amp;tzshift=0&quot; as const;

export default function Home({ product }: any) {
  const [count, setCount] = useState(0);

  return (
    &lt;div
      style={{
        display: &quot;flex&quot;,
        flexDirection: &quot;column&quot;,
        alignItems: &quot;flex-start&quot;,
      }}
    &gt;
      &lt;span&gt;{product}&lt;/span&gt;
      &lt;span&gt;{count}&lt;/span&gt;
      &lt;button onClick={() =&gt; setCount((prev) =&gt; prev + 1)}&gt;count&lt;/button&gt;
    &lt;/div&gt;
  );
}

export async function getServerSideProps() {
  const res = await fetch(URL);
  const data = await res.json();
  return {
    props: {
      product: data.product,
    },
  };
}</code></pre>
<h1 id="2-app-router">2. <strong>App Router</strong></h1>
<p>App Router는 Next.js 13에서 도입된 새로운 라우팅 시스템입니다. React 18의 새로운 기능들을 활용하며, 특히 React Server Components를 기본적으로 지원합니다.</p>
<h2 id="주요-특징-1"><strong>주요 특징</strong></h2>
<ul>
<li><code>app</code> 디렉토리 사용</li>
<li>폴더 구조 기반의 라우팅</li>
<li>레이아웃, 로딩 상태, 에러 처리 등을 위한 특수 파일들</li>
<li>서버 컴포넌트 기본 지원</li>
<li>향상된 성능과 유연성</li>
</ul>
<p>app router로 변하면서 파일명 router는 지원하지 않음.</p>
<p>그래서 폴더 기준으로 변함</p>
<p>검색 페이지인 search 페이지를 사용하려면 폴더를 만들어서 사용해야함.</p>
<h1 id="3-차이점-정리">3. 차이점 정리</h1>
<table>
<thead>
<tr>
<th><strong>구분</strong></th>
<th><strong>Pages Router</strong></th>
<th><strong>App Router</strong></th>
</tr>
</thead>
<tbody><tr>
<td>디렉토리 구조</td>
<td><code>pages</code> 디렉토리</td>
<td><code>app</code> 디렉토리</td>
</tr>
<tr>
<td>라우트 정의</td>
<td>파일 이름으로 라우트 정의</td>
<td>폴더 이름으로 라우트 정의, <code>page.js</code> 파일이 해당 라우트의 UI를 담당</td>
</tr>
<tr>
<td>레이아웃</td>
<td><code>_app.js</code>와 <code>_document.js</code>로 전역 레이아웃 관리</td>
<td>각 폴더에 <code>layout.js</code> 파일을 두어 중첩 레이아웃 쉽게 구현</td>
</tr>
<tr>
<td>데이터 페칭</td>
<td><code>getStaticProps</code>, <code>getServerSideProps</code> 등의 특수 함수 사용</td>
<td>컴포넌트 내에서 직접 <code>async</code>/<code>await</code> 사용 가능</td>
</tr>
<tr>
<td>서버컨포넌트</td>
<td>클라이언트 컴포넌트만 사용</td>
<td>서버 컴포넌트 기본 지원, <code>&#39;use client&#39;</code> 지시어로 클라이언트 컴포넌트 지정</td>
</tr>
<tr>
<td>동적 라우트</td>
<td><code>[param].js</code> 파일로 동적 라우트 생성</td>
<td><code>[param]</code> 폴더로 동적 라우트 생성</td>
</tr>
</tbody></table>
<h2 id="31-폴더-구조">3.1 폴더 구조</h2>
<p>pages router</p>
<pre><code>pages
├── _app.js
├── _document.js
├── index.js
├── about.js
└── posts
    └── [id].js
</code></pre><p>App router</p>
<pre><code>app
├── layout.js
├── page.js
├── about
│   └── page.js
└── posts
    └── [id]
        └── page.js</code></pre><h2 id="3-3-실제-사용-경험과-추세">3. 3 <strong>실제 사용 경험과 추세</strong></h2>
<ol>
<li>Pages Router 선호 이유:<ul>
<li>익숙함: 많은 개발자들이 이미 Pages Router에 익숙합니다.</li>
<li>단순성: 간단한 프로젝트에서는 Pages Router가 더 직관적일 수 있습니다.</li>
<li>안정성: Pages Router는 오랜 기간 사용되어 안정적입니다.</li>
<li>학습 곡선: App Router는 새로운 개념 학습이 필요합니다.</li>
</ul>
</li>
<li>App Router 불편 사항:<ul>
<li>복잡성: 일부 개발자들은 App Router의 구조가 더 복잡하다고 느낍니다.</li>
<li>호환성 문제: 일부 라이브러리가 App Router와 완벽히 호환되지 않을 수 있습니다.</li>
<li>변화 속도: Next.js의 빠른 변화로 인한 학습 부담이 있습니다.</li>
</ul>
</li>
<li>실제 사용 추세:<ul>
<li>점진적 도입: 많은 팀들이 새 프로젝트에서 App Router를 시도하고 있습니다.</li>
<li>혼합 사용: 일부는 두 라우터를 혼합해서 사용하며 점진적으로 전환합니다.</li>
<li>기업 환경: 대규모 기업에서는 안정성 때문에 Pages Router를 선호하는 경향이 있습니다.</li>
</ul>
</li>
</ol>
<p>🔗 출처</p>
<p><a href="https://keun.me/next-js-router/">Next.js의 Pages Router vs App Router: 상세 비교 가이드</a></p>
<p><a href="https://www.reddit.com/r/nextjs/comments/1gdxcg5/why_do_you_still_prefer_page_router_over_app/?tl=ko">Why Do You Still Prefer Page Router Over App Router?</a></p>
<p>한입 Next.js 섹션 3 2.1, 섹션 4 3.2 강의</p>
<p><a href="https://hackids.tistory.com/148">https://hackids.tistory.com/148</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2025-05-09 count, todolist]]></title>
            <link>https://velog.io/@koo-rogie/2025-05-09-count-todolist</link>
            <guid>https://velog.io/@koo-rogie/2025-05-09-count-todolist</guid>
            <pubDate>Thu, 29 May 2025 12:39:22 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<h3 id="count">COUNT</h3>
<h4 id="counter06-와-counter07-차이점"><code>counter/06/</code> 와 <code>counter/07</code> 차이점</h4>
<ul>
<li><strong>index.js</strong></li>
</ul>
<table>
<thead>
<tr>
<th>항목</th>
<th><code>counter/06/index.js</code></th>
<th><code>counter/07/index.js</code></th>
</tr>
</thead>
<tbody><tr>
<td>console.log</td>
<td>없음</td>
<td>Header, Counter, App 함수 호출 시 로그 출력</td>
</tr>
<tr>
<td>상태 관리 방식</td>
<td>지역 변수 <code>count</code> 사용 후, 이벤트 핸들러 내에서 <code>document.querySelector(...).textContent</code>로 DOM 직접 업데이트</td>
<td><code>Reaction.useState</code> 훅으로 상태 저장, <code>setCount</code> 호출 시 내부적으로 자동 리렌더링</td>
</tr>
<tr>
<td>이벤트 핸들러</td>
<td><code>handleDown</code>/<code>handleUp</code>/<code>handleReset</code>에서 직접 <code>count</code> 조작 후 수동으로 텍스트 갱신</td>
<td>동일한 핸들러 이름 사용하나, 내부에서는 <code>setCount</code>만 호출해 리렌더링에 위임</td>
</tr>
<tr>
<td>렌더링 동작</td>
<td>최초 렌더링 이후 상태 변경 시 수동 업데이트 필요</td>
<td>상태 변경 시 컴포넌트 전체가 자동으로 재 렌더링</td>
</tr>
</tbody></table>
<ul>
<li><strong>reaction.js</strong></li>
</ul>
<table>
<thead>
<tr>
<th align="center">항목</th>
<th><code>counter/06/reaction.js</code></th>
<th><code>counter/06/reaction.js</code></th>
</tr>
</thead>
<tbody><tr>
<td align="center">전역 변수 선언</td>
<td>전역 상태 변수 없음</td>
<td><code>_root</code>, <code>_stateValue</code> 전역으로 선언</td>
</tr>
<tr>
<td align="center">createRoot 구현</td>
<td><code>render(appFn)</code> 호출 시 단순히 <code>appendChild(appFn())</code> 실행</td>
<td>컴포넌트 함수 캐싱 (<code>_appComponent = _appComponent **??** appFn</code>)기존 자식 제거 <br>(<code>firstChild?.remove()</code>) 후 재렌더</td>
</tr>
<tr>
<td align="center">상태 관리 (useState)</td>
<td>없음</td>
<td><code>useState(initialValue)</code> 구현<code>_stateValue</code> 보관 및 <code>setValue</code> 호출 시 <code>render()</code> 트리거</td>
</tr>
<tr>
<td align="center">상태 초기화 방식</td>
<td>해당 없음</td>
<td><code>_stateValue = _stateValue ?? initialValue</code></td>
</tr>
<tr>
<td align="center">렌더링 동작</td>
<td>최초 렌더만 지원</td>
<td>상태 변경 감지 시 (<code>Object.is</code> 비교 후) <code>render()</code> 재호출</td>
</tr>
</tbody></table>
<br>

  <details>
  <summary>?? vs || 연산자</summary>

<ul>
<li><p><code>||</code> 논리 OR 연산자</p>
<ul>
<li>왼쪽 값이 <strong>거짓(falsy)</strong> 으로 평가되면(예: <code>false</code>, <code>0</code>, <code>&quot;&quot;</code>, <code>null</code>, <code>undefined</code>, <code>NaN</code>) → 오른쪽으로 대체</li>
</ul>
</li>
<li><p><code>??</code> (Nullish Coalescing) 연산자 (null 병합 연산자)</p>
<ul>
<li>왼쪽 값이 <strong>오직</strong> <code>null</code> 또는 <code>undefined</code>일 때만 → 오른쪽으로 대체</li>
<li><code>false</code>, <code>0</code>, <code>&quot;&quot;</code>, <code>NaN</code> 등은 <strong>유효한 값</strong>으로 그대로 유지</li>
</ul>
</li>
<li><p>예시보기</p>
<pre><code class="language-tsx">function test(val) {
  const initial = &quot;기본값&quot;;
  console.log(val || initial, &quot; ← || 결과&quot;);
  console.log(val ?? initial, &quot; ← ?? 결과&quot;);
}

test(false);   // 기본값 ← ||    , false ← ??
test(0);       // 기본값 ← ||    , 0     ← ??
test(&quot;&quot;);      // 기본값 ← ||    , &quot;&quot;    ← ??
test(null);    // 기본값 ← ||    , 기본값 ← ??
test(undefined); // 기본값 ← ||  , 기본값 ← ??</code></pre>
</details>


</li>
</ul>
<hr>
<h3 id="todolist">TODOLIST</h3>
<ul>
<li>파일별 차이점</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th><code>todolist/06/index.js</code></th>
<th><code>todolist/07/index.js</code></th>
<th><code>todolist/08/index.js</code></th>
</tr>
</thead>
<tbody><tr>
<td>주요 목적</td>
<td>단일 <code>App</code> 함수로 Reaction.createElement() 활용한 UI 구성</td>
<td>UI를 기능별 컴포넌트 함수로 분리</td>
<td><code>useState</code> 도입으로 상태 변경 시 화면 리렌더링</td>
</tr>
<tr>
<td>컴포넌트 구조</td>
<td><code>App</code> 하나만 정의</td>
<td><code>Header</code>, <code>Todo</code>, <code>Footer</code>, <code>TodoItem</code>, <code>TodoInput</code>, <code>TodoList</code> 분리</td>
<td>07과 동일한 분리 + 각 컴포넌트에 <code>props</code>/<code>state</code> 적용</td>
</tr>
<tr>
<td>TodoItem 정의</td>
<td><code>App</code> 내 하드코딩</td>
<td>인자 없는 재사용 함수</td>
<td><code>{ item }</code> 파라미터 받아 동적 데이터 렌더링</td>
</tr>
<tr>
<td>TodoList 구현 방식</td>
<td><code>App</code>에서 static 요소 하드코딩</td>
<td><code>Reaction.createElement(&quot;ul&quot;,…, TodoItem)</code>로 함수 참조 전달</td>
<td><code>itemList.map(item =&gt; TodoItem({ item }))</code>로 리스트 매핑</td>
</tr>
<tr>
<td>상태 관리</td>
<td>없음</td>
<td>없음</td>
<td><code>const [itemList, setItemList] = Reaction.useState(inititemList)</code></td>
</tr>
<tr>
<td>이벤트 처리 및 props</td>
<td>없음</td>
<td>없음</td>
<td><code>TodoInput</code>에 <code>handleAddKeydown</code>, <code>handleAdd</code> props로 전달, <code>onkeydown</code>/<code>onclick</code> 설정</td>
</tr>
<tr>
<td>동적 기능</td>
<td>없음</td>
<td>없음</td>
<td>아이템 추가(<code>addItem</code>), 삭제(<code>deleteItem</code>), 완료 토글(<code>toggleDone</code>) 기능 포함</td>
</tr>
<tr>
<td>파일 경로 표시 방식</td>
<td><code>location.href.split(&quot;/ch&quot;)[1]</code> 하드코딩</td>
<td>동일</td>
<td>동일</td>
</tr>
</tbody></table>
<br>

  <details>
  <summary>todolist/08/index.js 로 보는 파일 구조 설명</summary>

<pre><code>- 초기 값 및 Reaction 유틸 불러오기
    - `inititemList`에 기본 할 일 배열을 정의
    - `Reaction.useState` 훅을 통해 `itemList` 상태와 갱신 함수 `setItemList`를 선언
- Header 컴포넌트
    - 앱 제목과 현재 파일 경로를 `&lt;h1&gt;`/`&lt;span id=&quot;filepath&quot;&gt;`로 표시
    - `location.href.split(&quot;/ch&quot;)[1]` 로 URL에서 파일명만 추출
- TodoInput 컴포넌트
    - 텍스트 입력창(`input`)과 추가 버튼(`button`)을 렌더링
    - 두 가지 이벤트 핸들러를 props로 받음
        - `handleAddKeydown` : 입력창에서 Enter 키 누르면 호출
        - `handleAdd` : 추가 버튼 클릭 시 호출
- TodoItem 컴포넌트
    - 개별 할 일 객체를 props로 받아서 `&lt;li&gt;`로 출력
    - 클릭하면 완료 상태 전환(`toggleDone`), 옆의 삭제 버튼 클릭 시 해당 항목 삭제(`deleteItem`)
- TodoList 컴포넌트
    - `itemList` 배열을 `map`으로 순회하며
        - 각 요소를 `TodoItem({ item })` 형태로 렌더링
- Footer 컴포넌트
    - 간단한 저작권 또는 추가 정보 표시
- App 컴포넌트 전체 구성
    - 위의 컴포넌트들을 한데 모아 루트 `&lt;div&gt;` 안에 렌더링
    - 상태 조작 함수 정의
        - `addItem(title)` : 새 아이템 객체를 `itemList`에 추가
        - `deleteItem(num)` : 필터링으로 해당 아이템 제거
        - `toggleDone(num)` : 클릭된 아이템의 num을 조회한 후 `done` 속성 토글
        - `handleAddKeydown(e)` : Enter 키일 때 `addItem` 호출
        - `handleAdd()` : 버튼 클릭 시 `addItem` 호출
    - 이들 함수를 `TodoInput`, `TodoItem` 등에 props로 전달
- DOM에 붙이기
    - `document.querySelector(&quot;#root&quot;)` 로 루트 요소 선택
    - `Reaction.render(App(), root)` 또는 `root.appendChild(App())` 호출해 화면에 표시
- 사용자 상호작용 흐름
    - 페이지 로드 → `inititemList` 기반 렌더링
    - 입력창에 텍스트 입력 후
        - Enter 누르거나 추가 버튼 클릭 → `addItem` → `setItemList` → 자동 리렌더링
    - 각 할 일 항목 클릭 시 `toggleDone` → 시각적 스타일 변경
    - 삭제 버튼 클릭 시 `deleteItem` → 해당 항목 제거 → 리렌더링</code></pre>  </details>

<br>

<ul>
<li>전체 구도</li>
</ul>
<pre><code class="language-txt">        ┌───────── App ──────────┐  ← 최상위 컴포넌트
        │           │            │
      Header       Todo        Footer  ← 주요 섹션 컴포넌트들
                    │
                ┌───┴────┐             ← Todo 내부 구조
          TodoInput   TodoList         ← 입력부와 목록부
                         │
                      TodoItem         ← 개별 할일 아이템</code></pre>
<ul>
<li>함수로 보는 파일 구조</li>
</ul>
<pre><code class="language-txt">App()                                ← 최상위 함수 (파라미터 없음)
├─ addItem(title)                    ← 새 아이템 추가 함수 (text: string)
├─ deleteItem(num)                   ← 아이템 삭제 함수 (id: string)
├─ toggleDone(num)                   ← 완료 토글 함수 (id: string)
├─ handleAddKeydown(e)               ← 엔터 키 이벤트 핸들러 (e: KeyboardEvent)
├─ handleAdd()                       ← 추가 버튼 클릭 핸들러 (파라미터 없음)
├─ Header()                          ← 헤더 컴포넌트 함수 (파라미터 없음)
├─ TodoInput(                        ← 입력부 컴포넌트
│     {                           
│       handleAddKeydown,           ← props.handleAddKeydown: function
│       handleAdd                   ← props.handleAdd: function
│     })
├─ TodoList(                         ← 목록부 컴포넌트
│     { itemList }                 ← props.itemList: array of Todo 객체
│   )
│    └─ TodoItem(                    ← 개별 할일 아이템 컴포넌트
│         { item }                 ← props.item: Todo 객체
│       )
└─ Footer()                          ← 푸터 컴포넌트 함수 (파라미터 없음)
</code></pre>
<hr>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li><p>Counter</p>
<ul>
<li>07/ <a href="https://github.com/koo-rogie/React-start/tree/main/workspace/ch01-buildup/counter/07">Counter</a></li>
</ul>
</li>
<li><p>todoList</p>
<ul>
<li>06/ <a href="https://github.com/koo-rogie/React-start/tree/main/workspace/ch01-buildup/todolist/06">단일 <code>App</code> 함수</a></li>
<li>07/ <a href="https://github.com/koo-rogie/React-start/tree/main/workspace/ch01-buildup/todolist/07">UI를 기능별 컴포넌트 함수로 분리</a></li>
<li>08/ <a href="https://github.com/koo-rogie/React-start/tree/main/workspace/ch01-buildup/todolist/08">상태 변경 시 화면 리렌더링</a></li>
</ul>
</li>
<li><p>reaction <a href="https://github.com/koo-rogie/React-start/blob/main/workspace/ch01-buildup/todolist/reaction.js">REACT를 흉내낸 reaction.js</a></p>
</li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>우와...너무 어렵다...이게 뭘까</li>
<li>분명 같은 한국어인데 한국어처럼 들리지 않아</li>
<li>오늘 오타 고치고 잘못 들어간 코드만 고친 하루였다</li>
<li>배운건 없었던 느낌?</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[📆 2025.04.28 ‐ TypeScript type, intersection, interface, optional property,  readonly]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.28-TypeScript-type-intersection-interface-optional-property-readonly</link>
            <guid>https://velog.io/@koo-rogie/2025.04.28-TypeScript-type-intersection-interface-optional-property-readonly</guid>
            <pubDate>Mon, 28 Apr 2025 13:27:27 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<ul>
<li><h3 id="타입ex06-02ts">타입(ex06-02.ts)</h3>
<ul>
<li><h4 id="주요-타입">주요 타입</h4>
<ul>
<li>기본 타입<ul>
<li>string: 문자열 타입</li>
<li>number: 숫자 타입</li>
<li>boolean: true/false 논리 타입</li>
<li>null: 값이 비어있음을 명시하는 타입</li>
<li>undefined: 값이 할당되지 않은 상태</li>
<li>bigint: 매우 큰 정수를 다룰 수 있는 타입</li>
<li>symbol: 고유한 식별자를 만들 때 사용하는 타입</li>
</ul>
</li>
<li>참조 타입<ul>
<li>object: 객체 타입 (key-value 구조)</li>
<li>Array<T>: 특정 타입을 요소로 갖는 배열</li>
<li>tuple: 고정된 타입과 순서를 가지는 배열</li>
</ul>
</li>
<li>특수 타입<ul>
<li>any: 모든 타입을 허용 (비추천, 타입 안정성 떨어짐)</li>
<li>unknown: 모든 타입을 허용하지만 사용 전 타입 검사가 필요하여 any보다 안전</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h4 id="선택적-파라미터-ex06-04ts">선택적 파라미터 (ex06-04.ts)</h4>
<p><strong>함수의 매개 변수를 선택적으로 전달 받고 싶을때 매개 변수명 뒤에 ?를 추가</strong></p>
<pre><code class="language-TypeScript">(()=&gt;{
  function user(name /*1️⃣*/: string, age?/*1️⃣2️⃣*/: number) {
    console.log(name, age);
  }

  user(&#39;하루&#39;, 5);
  user(&#39;나무&#39;); // 3️⃣

})();</code></pre>
<ul>
<li>1️⃣ 타입지정</li>
<li>2️⃣  <strong>선택적 파라미터 선언법:</strong> 뒤에 물음표 적기</li>
<li>3️⃣ 매개변수를 전달하지 않으면 <code>undefined</code></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h4 id="유니언-타입">유니언 타입</h4>
<ul>
<li><p>여러 종류의 타입을 허용하기 위해 | (OR 연산자) 로 연결한 타입</p>
</li>
<li><p>any 타입은 모든 타입을 허용하지만 유니언 타입은 | 연산자로 연결된 타입중 하나를 허용</p>
</li>
<li><p><strong>연산자의 앞뒤가 바뀌어도 상관이 없다</strong></p>
</li>
<li><p>코드(ex06-05.ts)</p>
<pre><code class="language-tsx">(() =&gt; {
  function logString(msg: string) {
    console.log(msg);
  }

  logString(&quot;hello&quot;); // 1️⃣
  logString(123); // 2️⃣
  // --------

  function logNumber(msg: number) {
    console.log(msg);
  }
  logNumber(235); // 1️⃣
  logNumber(&quot;235&quot;);// 2️⃣
  // --------

  function log(msg: number | string) {
    console.log(msg);
  }
  log(123); // 3️⃣
  log(&quot;123&quot;); // 3️⃣
})();</code></pre>
<p><img src="https://github.com/user-attachments/assets/0bde0faf-bc70-4cfd-8f63-ea27b6333503" alt="image"></p>
<ul>
<li>1️⃣  정상 작동 ⇒ 매개변수에 할당한 타입이 일치함, 정상 출력</li>
<li>2️⃣  타입 에러 ⇒  매개변수에 할당한 타입이 불일치함</li>
<li>3️⃣ 매개변수로 정의한 <code>number</code>, <code>string</code> 이 있음, </li>
<li>4️⃣ <strong>타입가드:</strong> 조건문 안에서 <strong>`타입범위</strong>를 한정`시켜줄 수 있는 방법</li>
</ul>
</li>
<li><p>코드(ex06-05-02.ts)</p>
<pre><code class="language-jsx">(() =&gt; {
    function print(msg: number | string | boolean /*1️⃣*/) {
    if (typeof msg === &quot;string&quot;) { // 2️⃣ 
      // string일 경우
      console.log(`${msg} 글자수: ${msg.length}`);
    }
    if (typeof msg === &quot;number&quot;) { // 2️⃣ 
      // number일 경우
      console.log(`${msg} + 10 = ${msg + 10}`);
    }

    if (typeof msg === &quot;boolean&quot;) { // 2️⃣ 
      // boolean일 경우
      console.log(`${msg}: ${msg ? &quot;참&quot; : &quot;거짓&quot;}`);
    }
  }

  print(&quot;world&quot;); // 3️⃣
  print(200); // 3️⃣
  print(false);// 3️⃣
})();</code></pre>
<p><img src="https://github.com/user-attachments/assets/63fa9df8-8f2e-4b8f-8b87-becf2fca927a" alt="image"></p>
<ul>
<li>1️⃣ 타입 설정</li>
<li>2️⃣ <strong>타입가드</strong> </li>
<li>3️⃣ 정상 작동 ⇒  2️⃣ 타입가드가 입력값의 타입(<code>number</code>, <code>string</code>, <code>boolean</code>)을 하나하나 검사하여, 일치하는 경우에만 해당 조건문 안의 코드를 실행하고 출력하기 때문이다. 타입이 정확히 구분되므로 각각 알맞은 방식으로 처리되어 정상 출력된다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h4 id="타입-별칭ex06-06ts">타입 별칭(ex06-06.ts)</h4>
<ul>
<li><p>값을 변수에 저장하듯, 타입을 변수에 저장해서 사용</p>
</li>
<li><p>유니언 타입 같은 복잡한 타입에 의미 있는 이름을 붙여서 사용 (별칭)</p>
</li>
<li><p><strong><code>type</code> 키워드로 선언하는 <code>사용자 정의 타입</code></strong></p>
</li>
<li><p>동일한 이름으로 <code>중복 선언 불가</code></p>
</li>
<li><p>JS로 컴파일되면 제거됨</p>
</li>
<li><p>관련적인 명명 규칙</p>
<ul>
<li>PascalCase</li>
<li>명사형</li>
</ul>
</li>
<li><p>코드</p>
<pre><code class="language-tsx">(() =&gt; {
    function logMessage(msg: string | number) {
    console.log(msg);
  }

  function warnMessage(msg: number | string) {
    // 스타일 적용
    console.log(`%c${msg}`, &quot;color: yellow; font-size: 20px;&quot;);
  }

  logMessage(&quot;hello&quot;);
  logMessage(100);
  warnMessage(&quot;bye&quot;);
  warnMessage(200);
})();</code></pre>
<pre><code class="language-tsx">(() =&gt; {
  **type Massge = string | number; // 1️⃣
  function logMessage(msg: Massge /* 2️⃣ */) {
    console.log(msg);
  }

  function warnMessage(msg: Massge) {
    // 스타일 적용
    console.log(`%c${msg}`, &quot;color: yellow; font-size: 20px;&quot;);
  }

  logMessage(&quot;hello&quot;);
  logMessage(100);
  warnMessage(&quot;bye&quot;);
  warnMessage(200);
})();
</code></pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h4 id="타입-별칭으로-객체의-타입-선언">타입 별칭으로 객체의 타입 선언</h4>
<ul>
<li><p>객체의 속성명과 속성값의 타입을 지정</p>
</li>
<li><p>속성은 , 또는 ; 으로 구분할 수 있지만 공식 스타일 가이드에서는 ;을 권장</p>
</li>
<li><p>타입 별칭을 타입으로 지정한 객체는 타입 별칭에 정의된 속성명과 속성의 타입을 준수해야 함</p>
</li>
<li><p>코드(ex06-07.ts)</p>
<pre><code class="language-tsx">(() =&gt; {
  type user = { // 1️⃣
    name: string;
    age: number;
  };
  const u1: user = { // 2️⃣
    name: &quot;하루&quot;,
    age: 1,
  };
  const u2: user = { // 2️⃣
    name: &quot;나무&quot;,
    age: 5,
  };

  console.log(u1.name); // 3️⃣
  console.log(u2.age); // 3️⃣
})();
</code></pre>
<p><img src="https://github.com/user-attachments/assets/62333f67-3d9c-4343-ba72-94ca84770ca1" alt="image"></p>
<ul>
<li>1️⃣ <code>type</code> 키워드를 이용해 <code>user</code>라는 타입 별칭을 생성하고, <code>name(string)</code>과 <code>age(number)</code>의 타입 구조를 정의함</li>
<li>2️⃣ <code>u1</code>, <code>u2</code>는 <code>user</code> 타입을 명시적으로 지정하여 객체를 생성했음. 이를 통해 타입 안정성을 확보함</li>
<li>3️⃣ <code>u1.name</code>은 문자열(string)로, <code>u2.age</code>는 숫자(number)로 타입이 보장되어 각각 정상 출력됨</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="인터섹션-타입">인터섹션 타입</h3>
<ul>
<li><p>타입 여러개를 하나로 합치기 위해 &amp;(AND 연산자) 로 연결한 타입</p>
<ul>
<li><strong>타입 별칭을 확장할 때 주로 사용</strong></li>
</ul>
</li>
<li><p>동일한 속성을 <strong>인터섹션 타입으로 추가</strong>할때 타입이 다르면 <code>never</code> 타입이 되면서 해당 속성은 사용이 불가함</p>
</li>
<li><p>코드(ex06-08.ts)</p>
<pre><code class="language-jsx">(() =&gt; {
  // 할일 등록시 사용
  type TodoRegist = { // 1️⃣
    title: string;
    content: string;
  };

  // 할일 조회시 사용
  type TodoInfo = TodoRegist &amp; { // 2️⃣
    id: number;
    done: boolean;
  };

  const todo1: TodoRegist = { // 3️⃣
    title: &quot;타입스크립트 공부&quot;,
    content: &quot;타입스크립트 수업 대비해서 미리 책 읽어보기.&quot;,
  };
  const todo2: TodoInfo = { // 3️⃣
    id: 13,
    title: &quot;타입스크립트 공부&quot;,
    content: &quot;타입스크립트 수업 대비해서 미리 책 읽어보기.&quot;,
    done: false,
  };

  console.log(todo1.title, &quot;:&quot;, todo1.content);
  console.log(&quot;todo2 합본!: &quot;, todo2.id, todo2.title, 
  todo2.content, todo2.done);
})();</code></pre>
<ul>
<li>1️⃣ <code>TodoRegist</code> 타입을 만들어 <code>title</code>과 <code>content</code> 속성에 각각 <code>string</code> 타입을 지정</li>
<li>2️⃣ <code>TodoInfo</code> 타입은 <code>TodoRegist</code> 타입을 상속받고(<code>&amp;</code> 사용), 추가로 <code>id</code>(number), <code>done</code>(boolean) 속성을 확장해서 정의</li>
<li>3️⃣ <code>todo1</code>은 <code>TodoRegist</code> 타입을 따르는 객체이고, <code>todo2</code>는 확장된 <code>TodoInfo</code> 타입을 따르는 객체</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="인터페이스">인터페이스</h3>
<ul>
<li><p>객체의 타입을 정의하기 위해 사용(객체의 속성명과 속성값의 타입을 지정)</p>
</li>
<li><p>속성은 <code>,</code>또는 <code>;</code>으로 구분</p>
</li>
<li><p><code>interface</code> 키워드로 선언하는 사용자 정의 타입</p>
</li>
<li><p>인터페이스를 타입으로 지정한 객체는 해당 인터페이스에 정의된 속성명과 속성의 타입을 준수해야 함</p>
</li>
<li><p>JS로 컴파일 하면 제거됨</p>
</li>
<li><p>코드(ex06-07.ts, ex06-09.ts)</p>
<pre><code class="language-tsx">// ex06-07.ts
(() =&gt; {
  type user = { // 1️⃣
    name: string;
    age: number;
  };
  const u1: user = {
    name: &quot;하루&quot;,
    age: 1,
  };
  const u2: user = {
    name: &quot;나무&quot;,
    age: 5,
  };

  console.log(u1.name);
  console.log(u2.age);
})();
</code></pre>
<pre><code class="language-tsx">// ex06-09.ts
(() =&gt; {
  interface User { // 1️⃣
    name: string;
    age: number;
  }
  const u1: User = {
    name: &quot;하루&quot;,
    age: 1,
  };
  const u2: User = {
    name: &quot;나무&quot;,
    age: 5,
  };

  console.log(u1.name);
  console.log(u2.age);
})();
</code></pre>
<p>1️⃣ ex06-07.ts은 <code>type</code>, ex06-09.ts은 <code>interface</code>를 사용해 <code>user</code> 타입을 정의함. 둘 다 <code>name</code>(string)과 <code>age</code>(number) 속성을 가짐</p>
<ul>
<li><p>기본 인터섹션 사용(ex06-10.ts): 변수, 함수의 매개 변수, 함수의리턴 타입에 사용</p>
<pre><code class="language-tsx">(() =&gt; {
  interface User { // 1️⃣
    name: string;
    age: number;
  }

  const u1: User = { // 2️⃣
    name: &quot;하루&quot;,
    age: 1,
  };
  const u2: User = { // 2️⃣
    name: &quot;나무&quot;,
    age: 5,
  };
  console.log(u1.name);
  console.log(u2.age);

  const createUser = function (name: string, age: number): User {
    return { name, age };
  }; // 3️⃣

  const u3: User = createUser(&quot;유저핑&quot;, 9);
  console.log(u3.name);

  function getAge(user: User): number { // 4️⃣
    return user.age;
  }

  console.log(getAge(u1));
  console.log(getAge(u2));
})();
</code></pre>
<ul>
<li>1️⃣ <code>User</code>라는 이름으로 <code>name</code>(string)과 <code>age</code>(number)를 갖는 인터페이스를 생성</li>
<li>2️⃣ <code>u1</code>, <code>u2</code> 객체를 <code>User</code> 타입으로 지정하여 타입 안정성을 확보</li>
<li>3️⃣ <code>createUser</code> 함수가 <code>User</code> 타입 객체를 반환하도록 리턴 타입을 지정</li>
<li>4️⃣ <code>getAge</code> 함수가 매개변수로 <code>User</code> 타입 객체를 받고, 그 객체의 <code>age</code> 값을 반환</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="클래스-인터페이스-사용">클래스 인터페이스 사용</h3>
<ul>
<li><p>클래스의 타입 지정에 사용</p>
</li>
<li><p>클래스명 뒤에 <code>implements</code> 키워드 추가</p>
</li>
<li><p>인터페이스를 타입으로 지정한 클래스의 멤버 변수와 메서드는 인터페이스에 정의된 속성과 속성의 타입을 준수해야 함</p>
</li>
<li><p>코드(ex06-11.ts)</p>
<pre><code class="language-tsx">(() =&gt; {
  interface Score { // 1️⃣
    kor: number;
    eng: number;
    sum(): number;
    avg(): number;
  }

  class HighSchool implements Score { // 2️⃣
    kor: number;
    eng: number;
    constructor(kor: number, eng: number) {
      this.kor = kor;
      this.eng = eng;
    }
    sum() {
      return this.kor + this.eng;
    }
    avg() {
      return this.sum() / 2;
    }
  }

  function printScore(score: Score) { // 3️⃣
    console.log(score.sum(), score.avg());
  }

  const haru = new HighSchool(100, 90); // 4️⃣
  printScore(haru); // 5️⃣
})();
</code></pre>
<ul>
<li>1️⃣ <code>Score</code>라는 인터페이스를 생성해서 <code>kor</code>, <code>eng</code> (<code>number</code> 타입)과 <code>sum()</code>, <code>avg()</code> 메서드를 정의함</li>
<li>2️⃣ <code>HighSchool</code> 클래스가 <code>Score</code> 인터페이스를 <code>implements</code>(구현)하여 <code>kor</code>, <code>eng</code> 속성과 <code>sum()</code>, <code>avg()</code> 메서드를 구현함</li>
<li>3️⃣ <code>printScore</code> 함수는 매개변수로 <code>Score</code> 타입을 받고, <code>sum()</code>과 <code>avg()</code> 결과를 출력함</li>
<li>4️⃣ <code>haru</code>라는 이름으로 <code>HighSchool</code> 인스턴스를 생성하고, <code>kor=100</code>, <code>eng=90</code> 값을 전달함</li>
<li>5️⃣ <code>printScore(haru)</code>를 호출해서 <code>haru</code> 객체의 총점(<code>sum()</code>)과 평균(<code>avg()</code>)을 출력함</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>  ```markdown
  Score 인터페이스
  ├─ kor: number
  ├─ eng: number
  ├─ sum(): number
  └─ avg(): number

  HighSchool 클래스 (implements Score)
  ├─ kor
  ├─ eng
  ├─ sum()
  │  └─ return this.kor + this.eng
  └─ avg()
      └─ return this.sum() / 2

  printScore(score: Score) 함수
  ├─ console.log(score.sum())
  └─ console.log(score.avg())

  haru 객체 생성
  └─ new HighSchool(100, 90)

  printScore(haru) 호출
  ├─ haru.sum() 실행
  └─ haru.avg() 실행

  ```</code></pre><hr>
<ul>
<li><h3 id="optional-property">optional property</h3>
<ul>
<li>객체의 속성을 선택적으로 부여하고 싶을때 인터페이스 속성명 뒤에 <code>?</code>를 추가</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="readonly">readonly</h3>
<ul>
<li><p>인터페이스의 속성명앞에 readonly키워드 추가</p>
</li>
<li><p>객체 생성시에만 값 할당이 가능하고 생성된 이후에는 수정할 수 없는 속성을 만들때 사용</p>
</li>
<li><p>코드</p>
<pre><code class="language-tsx">(() =&gt; {
  interface Todo {
    readonly id: number;
    title: string;
    content: string;
    done?: boolean;
  }

  const todo1: Todo = {
    id: 1,
    title: &quot;TypeScript 학습하기&quot;,
    content: &quot;학습하기&quot;,
    done: false,
  };
  console.log(todo1);
  const todo2: Todo = {
    id: 2,
    title: &quot;TypeScript 학습하기&quot;,
    content: &quot;학습하기&quot;,
  };

  console.log(&quot;변경 전&quot;, todo2);
  todo2.id = 3;
  todo2.content = &quot;학습 끝&quot;;
  console.log(&quot;변경 후&quot;, todo2);
})();
</code></pre>
<p><img src="https://github.com/user-attachments/assets/db7edcf6-fdd0-4a0c-afc7-e6c8a35967c2" alt="image"></p>
<p><img src="https://github.com/user-attachments/assets/9e50ef4e-df1f-480d-b151-1eb532ffa073" alt="image"></p>
<ul>
<li>1️⃣ <code>Todo</code>라는 타입(설계도)을 정의했다. (<code>readonly</code>/<code>optional</code> 특징 있음)</li>
<li>2️⃣ <code>Todo</code> 타입을 이용해서 <code>todo1</code> 객체를 만들었다. (설계도에 맞춰 생성)</li>
<li>3️⃣ <code>todo2</code> 객체를 만들고 수정하려 했는데, <code>readonly id</code>는 수정 못하고, <code>content</code>는 수정 가능했다</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="인터페이스-상속">인터페이스 상속</h3>
<ul>
<li><p>부모 인터페이스의 속성과 메서드 정의를 자식 인터페이스가 물려 받고 확장</p>
</li>
<li><p>interface선언부의 extends키워드 뒤에 상속 받을 부모 인터페이스 지정</p>
</li>
<li><p>코드(ex06-13.ts)</p>
<pre><code class="language-tsx">(() =&gt; {
  interface TodoRegist { //  1️⃣
    title: string;
    content: string;
  }

  interface TodoInfo extends TodoRegist { // 2️⃣
    id: number;
    done: boolean;
  }

  const todo1: TodoRegist = { // 3️⃣
    title: &quot;TypeScript&quot;,
    content: &quot;학습하기&quot;,
  };
  console.log(&quot;할일 상세 조회&quot;, todo1);

  const todo2: TodoInfo = { // 4️⃣
    id: 1,
    title: &quot;TS&quot;,
    content: &quot;학습하기&quot;,
    done: false,
  };

  console.log(&quot;할일 상세 조회&quot;, todo2); // 5️⃣
})();
</code></pre>
<ul>
<li>1️⃣ <code>TodoRegist</code>라는 인터페이스를 만들어 <code>title</code>과 <code>content</code> 속성(string 타입)을 정의함</li>
<li>2️⃣ <code>TodoInfo</code>라는 인터페이스를 생성하고, <code>TodoRegist</code>를 <code>extends</code>(상속)하여 <code>id</code>, <code>done</code> 속성을 추가함<ul>
<li><code>title</code>, <code>content</code>는 상속받아서 자동 포함됨</li>
</ul>
</li>
<li>3️⃣ <code>todo1</code> 객체를 <code>TodoRegist</code> 타입으로 생성하고, <code>title</code>과 <code>content</code> 값을 할당함</li>
<li>4️⃣ <code>todo2</code> 객체를 <code>TodoInfo</code> 타입으로 생성하고, <code>id</code>, <code>title</code>, <code>content</code>, <code>done</code> 값을 모두 할당함</li>
<li>5️⃣ 각각의 <code>todo1</code>, <code>todo2</code> 객체를 <code>console.log</code>로 출력하여 내용 확인</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li>ex06<ul>
<li>02.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-02.ts">기본 타입</a></li>
<li>02.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-02.js">기본 타입</a></li>
<li>03.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-03.ts">함수에 타입 지정</a></li>
<li>03.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-03.js">함수에 타입 지정</a></li>
<li>04.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-04.ts">선택적 파라미터(optional parameter)</a></li>
<li>04.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-04.js">선택적 파라미터(optional parameter)</a></li>
<li>05.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-05.ts">유니언 타입</a></li>
<li>05.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-05.js">유니언 타입</a></li>
<li>05-02.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-05-02.ts">유니언 타입과 타입 가드</a></li>
<li>05-02.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-05-02.js">유니언 타입과 타입 가드</a></li>
<li>06.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-06.ts">유니언 타입</a></li>
<li>06.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-06.js">유니언 타입</a></li>
<li>06-02.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-06-02.ts">유니언 타입에 타입 별칭 지정</a></li>
<li>06-02.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-06-02.js">유니언 타입에 타입 별칭 지정</a></li>
<li>07.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-07.ts">타입 별칭으로 객체의 타입 선언</a></li>
<li>07.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-07.js">타입 별칭으로 객체의 타입 선언</a></li>
<li>08.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-08.ts">인터섹션 타입(intersection type)</a></li>
<li>08.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-08.js">인터섹션 타입(intersection type)</a></li>
<li>09.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-09.ts">인터페이스로 객체의 타입 선언</a></li>
<li>09.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-09.js">인터페이스로 객체의 타입 선언</a></li>
<li>10.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-10.ts">인터페이스 사용 - 변수, 함수의 매개변수, 리턴타입</a></li>
<li>10.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-10.js">인터페이스 사용 - 변수, 함수의 매개변수, 리턴타입</a></li>
<li>11.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-11.ts">인터페이스 사용 - 클래스의 타입 지정</a></li>
<li>11.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-11.js">인터페이스 사용 - 클래스의 타입 지정</a></li>
<li>12.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-12.ts">인터페이스 정의 - 선택적 속성, 읽기 전용 속성</a></li>
<li>12.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-12.js">인터페이스 정의 - 선택적 속성, 읽기 전용 속성</a></li>
<li>13.ts <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/ex06-13.ts">인터페이스 상속</a></li>
<li>13.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch06/js/ex06-13.js">인터페이스 상속</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>익숙한거랑 모르는게 있어서 좋았다</li>
<li>sass는 컴파일링 하는 과정에서 에러가 있으면 컴파일링 자체가 안되는데 TypeScript는 에러가 있어도 무시하고 컴파일링하는 과정이 신기했다.</li>
</ul>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://velog.io/@sanglee/TypeScript-Optional-Parameter">Optional Parameter</a></li>
<li><a href="https://velog.io/@soulee__/TypeScript-Union-Type">유니온 타입과 인터섹션 타입</a></li>
<li><a href="https://www.notion.so/TypeScript-1e25b56ad8d3805bac97d50d396b01da?pvs=4">노션 정리</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[📆 2025.04.24 ‐ Advanced JavaScript: Functions, Prototypes, Closures, and Classes]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.24-Advanced-JavaScript-Functions-Prototypes-Closures-and-Classes</link>
            <guid>https://velog.io/@koo-rogie/2025.04.24-Advanced-JavaScript-Functions-Prototypes-Closures-and-Classes</guid>
            <pubDate>Thu, 24 Apr 2025 12:54:39 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<blockquote>
<p>오늘 공부하면서 인사이트, 개념 요약 등</p>
</blockquote>
<ul>
<li><h3 id="프로토타입-체인을-이용한-상속-기능">프로토타입 체인을 이용한 상속 기능</h3>
<ul>
<li><p>하위 생성자의 프로토타입을 상위 생성자의 객체로 지정</p>
</li>
<li><p>상위 생성자의 모든 속성을 물려받아 사용할 수 있음</p>
</li>
<li><p>상속 ex03-04.js</p>
<ul>
<li><p>중복속성</p>
<pre><code class="language-jsx">/**
 * 고등학교 성적관리 생성자 함수(총점과 평균 계산)
* @param {number} kor 국어 점수
* @param {number} eng 영어 점수
*/
function HighSchool(kor, eng) {
  // 속성 초기 화
  this.kor = kor;
  this.eng = eng;
}

HighSchool.prototype.sum = function () {
  return this.kor + this.eng;
};

HighSchool.prototype.avg = function () {
  return this.sum() / 2;
};

const s1 = new HighSchool(100, 91);
console.log(&quot;고등학교 총점&quot;, s1.sum());
console.log(&quot;고등학교 평균&quot;, s1.avg());
</code></pre>
<p><img src="https://github.com/user-attachments/assets/877c583f-691f-4b5f-a3e6-f66287a412a1" alt="image"></p>
<pre><code class="language-jsx">/**
 * 대학교 성적관리 생성자 함수(총점, 평균과 학점 계산)
* @param {number} kor 국어 점수
* @param {number} eng 영어 점수
*/
function College(kor, eng) {
  this.kor = kor;
  this.eng = eng;
}

College.prototype.sum = function () {
  return this.kor + this.eng;
};

College.prototype.avg = function () {
  return this.sum() / 2;
};
College.prototype.grade = function () {
  const avg = this.avg();
  if (avg &gt;= 90) {
    return &quot;A&quot;;
  } else if (avg &gt;= 80) {
    return &quot;B&quot;;
  } else if (avg &gt;= 70) {
    return &quot;C&quot;;
  } else if (avg &gt;= 60) {
    return &quot;D&quot;;
  } else {
    return &quot;F&quot;;
  }
};

const c1 = new College(80, 91);
console.log(&quot;대학교 총점&quot;, c1.sum());
console.log(&quot;대학교 평균&quot;, c1.avg());
console.log(&quot;대학교 학점&quot;, c1.grade());</code></pre>
<p><img src="https://github.com/user-attachments/assets/ddec3d02-31a1-4d5c-be9d-3e1b7cbadf54" alt="image"></p>
</li>
<li><p>상속 받는 코드
<img src="https://github.com/user-attachments/assets/d21fb36b-9584-4231-a4ab-d8fa02dd0af6" alt="image"></p>
<pre><code class="language-jsx">/**
 * 고등학교 성적관리 생성자 함수(총점과 평균 계산)
* @param {number} kor 국어 점수
* @param {number} eng 영어 점수
*/
function HighSchool(kor, eng) {
  // 속성 초기 화
  this.kor = kor;
  this.eng = eng;
}

HighSchool.prototype.sum = function () {
  return this.kor + this.eng;
};

HighSchool.prototype.avg = function () {
  // 소수 첫째자리에서 반올림한다
  return Math.round(this.sum() / 2);
};

const s1 = new HighSchool(100, 91);
console.log(&quot;고등학교 총점&quot;, s1.sum());
console.log(&quot;고등학교 평균&quot;, s1.avg());</code></pre>
<p><img src="https://github.com/user-attachments/assets/90cc363c-0149-4aa2-9d84-941dd5dba990" alt="image"></p>
<pre><code class="language-jsx">/**
 * 대학교 성적관리 생성자 함수(총점, 평균과 학점 계산)
* @param {number} kor 국어 점수
* @param {number} eng 영어 점수
*/
function College(kor, eng) {
  this.kor = kor;
  this.eng = eng;
}

// College가 HighSchool을 상속 받는다
College.prototype = new HighSchool();
College.prototype.**constructor** = College;

College.prototype.grade = function () {
  const avg = this.avg();
  if (avg &gt;= 90) {
    return &quot;A&quot;;
  } else if (avg &gt;= 80) {
    return &quot;B&quot;;
  } else if (avg &gt;= 70) {
    return &quot;C&quot;;
  } else if (avg &gt;= 60) {
    return &quot;D&quot;;
  } else {
    return &quot;F&quot;;
  }
};

const c1 = new College(80, 91);
console.log(&quot;대학교 총점&quot;, c1.sum());
console.log(&quot;대학교 평균&quot;, c1.avg());
console.log(&quot;대학교 학점&quot;, c1.grade());</code></pre>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes/constructor"><strong><code>constructor</code></strong> 메서드는 클래스의 인스턴스 객체를 생성하고 초기화하는 특별한 메서드입니다.</a>  <br></p>
<ul>
<li><p>gpt 설명</p>
<ul>
<li><code>HighSchool</code>: 점수 → <code>sum()</code>, <code>avg()</code> 계산만 담당</li>
<li><code>College</code>: <code>HighSchool</code> 기능 + <code>grade()</code> 확장</li>
<li><code>College.prototype = new HighSchool()</code> 를 통해 <strong>상속 구현</strong></li>
<li><code>constructor</code>는 다시 <code>College</code>로 되돌려줘야 정확함</li>
</ul>
</li>
<li><p><code>constructor</code>란?</p>
<ul>
<li><p><strong>🔧 constructor란?</strong></p>
<ul>
<li><code>constructor</code>는 객체의 <strong>프로토타입</strong>(<code>prototype</code>) 객체에 기본으로 포함된 속성이야.</li>
<li>이 속성은 해당 객체가 어떤 <strong>생성자 함수에 의해 생성되었는지</strong>를 가리켜.</li>
<li>모든 함수는 기본적으로 <code>.prototype.constructor</code> 속성을 가지고 있어.</li>
</ul>
<p>예시:</p>
<pre><code class="language-jsx">function HighSchool(kor, eng) {
  this.kor = kor;
  this.eng = eng;
}

console.log(HighSchool.prototype.constructor === HighSchool); // ✅ true
</code></pre>
<p>이 말은 즉,</p>
<pre><code class="language-jsx">const s1 = new HighSchool(100, 90);</code></pre>
<p>를 했을 때, <code>s1.constructor === HighSchool</code> 이 성립해.</p>
<p>왜냐면 <code>s1.__proto__ === HighSchool.prototype</code> 이고, 그 안에 있는 <code>.constructor</code>가 <code>HighSchool</code>을 가리키니까!</p>
<hr>
</li>
<li><p><strong>🔁 근데 상속할 때 문제가 생겨!</strong></p>
<pre><code class="language-jsx">College.prototype = new HighSchool();</code></pre>
<p>이렇게 상속하면 <code>College.prototype</code>은 이제 <code>HighSchool</code>의 인스턴스가 되니까,</p>
<p><code>College.prototype.constructor</code>는 <strong>HighSchool을 가리키게 돼.</strong></p>
<pre><code class="language-jsx">console.log(College.prototype.constructor === HighSchool); // ❌ 우리가 원하는 게 아님</code></pre>
<p>그래서 <strong>원래의 생성자 정보가 꼬이게 되고</strong>, 이걸 명시적으로 다시 설정해줘야 해:</p>
<pre><code class="language-jsx">College.prototype.constructor = College;</code></pre>
<p>이렇게 하면:</p>
<pre><code class="language-jsx">const c1 = new College(80, 91);
console.log(c1.constructor === College); // ✅ true</code></pre>
<hr>
</li>
<li><p><strong>🔍 왜 constructor를 바르게 지정해야 할까?</strong></p>
<ol>
<li>디버깅/로깅할 때 어떤 생성자로 만들어졌는지 알 수 있음</li>
<li>클래스 체계를 흉내 낼 때 정확한 정보 제공</li>
<li>어떤 프레임워크/라이브러리는 <code>constructor</code> 값을 보고 타입 분기 처리하기도 함</li>
</ol>
<hr>
</li>
<li><p><strong>📌 요약</strong></p>
<ul>
<li><code>.constructor</code>는 어떤 생성자 함수로 만들어졌는지 알려주는 속성</li>
<li>상속할 때 <code>prototype = new Parent()</code> 하면 <code>.constructor</code>가 꼬이므로 <code>constructor</code>를 직접 재지정해줘야 함</li>
<li>바르게 지정해두면 디버깅이나 타입 확인에서 유리함</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>상속 ex03-04.js를 ex03-05.js로
HighSchool → College 상속 흐름 시각 정리</p>
<pre><code class="language-jsx">/* ex03-04 */
/**
 * 고등학교 성적관리 생성자 함수(총점과 평균 계산)
  * @param {number} kor 국어 점수
  * @param {number} eng 영어 점수
  */
function HighSchool(kor, eng) {
  // 속성 초기 화
  this.kor = kor;
  this.eng = eng;
}

HighSchool.prototype.sum = function () {
  return this.kor + this.eng;
};

HighSchool.prototype.avg = function () {
  // 소수 첫째자리에서 반올림한다
  return Math.round(this.sum() / 2);
};

const s1 = new HighSchool(100, 91);
console.log(&quot;고등학교 총점&quot;, s1.sum());
console.log(&quot;고등학교 평균&quot;, s1.avg());

{...}
console.log(College.prototype);
// College의 프로토타입 출력
</code></pre>
<p><img src="https://github.com/user-attachments/assets/bdd2da0d-72e7-43c5-adcc-889c33839e54" alt="image"></p>
<pre><code class="language-jsx">/* ex03-05 */
{...}
/**
 * 대학교 성적관리 생성자 함수(총점, 평균과 학점 계산)
  * @param {number} kor 국어 점수
  * @param {number} eng 영어 점수
  */
function College(kor, eng) {
  this.kor = kor;
  this.eng = eng;
}

// College가 HighSchool을 상속 받는다

function inherite(Parent, Child) {
  // 첫번째 방법
  const F = new Function();
  F.prototype = HighSchool.prototype; // F의 프로토타입을 HighSchool의 프로토타입으로 변경
  College.prototype = new F(); // F인스턴스 생성후 College의 프로토타입으로 대입한다
  College.prototype.constructor = College;

  // 2번째 방법
  Child.prototype = Object.create(Parent.prototype);
  //create함수는 지정한 prototype 객체를 참조하는 인스턴스 생성
  Child.prototype.constructor = Child; 
  // 자식 생성자의 constructor 프로퍼티 복원
}

inherite(HighSchool, College);

College.prototype.grade = function () {
  const avg = this.avg();
  if (avg &gt;= 90) {
    return &quot;A&quot;;
  } else if (avg &gt;= 80) {
    return &quot;B&quot;;
  } else if (avg &gt;= 70) {
    return &quot;C&quot;;
  } else if (avg &gt;= 60) {
    return &quot;D&quot;;
  } else {
    return &quot;F&quot;;
  }
};

const c1 = new College(80, 91);
console.log(&quot;대학교 총점&quot;, c1.sum());
console.log(&quot;대학교 평균&quot;, c1.avg());
console.log(&quot;대학교 학점&quot;, c1.grade());

console.log(College.prototype);
// College의 프로토타입 출력
</code></pre>
<p><img src="https://github.com/user-attachments/assets/2b42e05c-d2c4-4004-a5bd-091f7908c7fd" alt="image"></p>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="class-사용"><code>Class</code> 사용</h3>
<ul>
<li><p>ECMAScript6(2015)에 추가된 키워드</p>
</li>
<li><p>객체지향 언어의 class와 비슷한 방식으로 생성자 함수를 기술</p>
</li>
<li><p>객체를 생성하고 prototype 기반의 상속을 보다 명료하게 표현</p>
</li>
<li><p><code>class는 사실 **함수**</code>이며 class 선언문과 class 표현식 방식으로 사용</p>
</li>
<li><p>class 선언문</p>
<pre><code class="language-jsx">// 기본 타입
class 클래스명 {...}
// 예시
class hi {...}</code></pre>
<ul>
<li>class 표현식</li>
</ul>
<pre><code class="language-jsx">// 기본 타입
const 변수 = class {...}
// 예시
const hi = class {...}</code></pre>
</li>
<li><p>Class body와 메서드 정의</p>
<p>  클래스의 바디에 클래스 멤버변수(속성)와 메서드 정의</p>
<p>  멤버변수의 초기화는 Constructor 메서드에 정의</p>
</li>
<li><p>Constructor 메서드(생성자)</p>
<ul>
<li>객체를 생성하고 초기화 하는 메서드(생략 가능)</li>
<li>주로 클래스 멤버변수를 초기화하는 작업</li>
<li>constructor라는 이름으로 작성</li>
<li>하나만 작성 가능</li>
<li>super()로 부모의 생성자 호출 가능</li>
</ul>
<pre><code class="language-jsx">// ✅ Class 문법 (ES6)
class HighSchool {
  constructor(kor, eng) {
    this.kor = kor;
    this.eng = eng;
  }
}

const s1 = new HighSchool(100, 90);
console.log(s1.kor, s1.eng);
</code></pre>
<pre><code class="language-jsx">// ✅ Function 생성자 방식
function HighSchool(kor, eng) {
  this.kor = kor;
  this.eng = eng;
}

const s1 = new HighSchool(100, 90);
console.log(s1.kor, s1.eng);
</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="클로저">클로저</h3>
<ul>
<li><p>클로저란</p>
<ul>
<li><p>실행이 끝난 외부 함수의 변수에 접근할 수 있는 내부 함수</p>
</li>
<li><p>함수가 생성되는 시점을 기준으로 접근 가능한 변수는, 그 유효범위가 사라진 후에도 접근 가능</p>
</li>
<li><p>클로저로 인해 유효 범위가 사라진 변수와 함수를 사용할 수 있고, 변수의 경우 그 값을 변경할 수도 있다.</p>
</li>
<li><p>ex04-01.js</p>
<pre><code class="language-jsx">const topLevel = &quot;최상위 변수&quot;;

function outer() {
  const innerVal = &quot;outer의 지역변수&quot;;
  console.log(topLevel); //=&gt; 1️⃣
  console.log(innerVal); //=&gt; 2️⃣
}

outer();
console.log(topLevel); //=&gt; 3️⃣
console.log(innerVal); //=&gt; 4️⃣
/* 출력 순서
  1️⃣ 2️⃣ 3️⃣ (4️⃣는 에러) 
*/</code></pre>
<ul>
<li>1️⃣ 전역 변수 <code>topLevel</code>은 함수 내부에서도 접근 가능하다.
스코프 체인에 따라 하위 스코프에서 상위 스코프 변수를 찾는다.</li>
<li>2️⃣ <code>innerVal</code>은 <code>outer</code> 함수 내부에서 선언된 지역 변수이다.
함수 안에서는 자유롭게 참조 가능하지만 함수 밖에서는 불가하다.</li>
<li>3️⃣ <code>topLevel</code>은 전역 변수이므로 함수 외부에서도 문제 없이 접근됨.
전역 스코프에서 선언된 변수는 어디서든 참조가 가능하기 때문이다.</li>
<li>4️⃣ <code>innerVal</code>은 <code>outer</code> 함수가 종료되면 사라지는 지역 변수이다.
함수 밖에서 접근하면 <code>ReferenceError</code>가 발생하게 된다.</li>
</ul>
<hr>
<pre><code class="language-jsx">const topLevel = &quot;최상위 변수&quot;;

function outer() {
  const innerVal = &quot;outer의 지역변수&quot;;
  console.log(topLevel); // 1️⃣
  console.log(innerVal); // 2️⃣
  return innerVal;
}

outer();
console.log(topLevel); // 3️⃣
console.log(innerVal); // 4️⃣

/* 출력순서
  1️⃣ 2️⃣ 3️⃣ (4️⃣는 에러)
*/</code></pre>
<ul>
<li>1️⃣ <code>topLevel</code>은 함수 외부에서 선언된 전역 변수이며, 함수 내부에서 자동으로 참조된다. 자바스크립트의 스코프 체인 덕분에 하위 스코프 에서는 상위 스코프에 있는 변수에 접근할 수 있게 된다.</li>
<li>2️⃣ <code>innerVal</code>은 <code>outer</code> 함수 안에서 선언된 지역 변수이기 때문에 해당 함수 내부에서만 유효하다. 지역 스코프는 함수 실행 시 생기며 함수 종료와 함께 메모리에서 제거된다.</li>
<li>3️⃣ <code>topLevel</code>은 전역에 선언되어 있기 때문에 어디서든 접근 가능하다.
함수 밖의 <code>console.log(topLevel)</code>도 전혀 문제 없이 실행된다.
전역 변수는 전체 코드에서 공유 가능한 값이다.</li>
<li>4️⃣ <code>innerVal</code>은 <code>outer</code> 내부에서 선언되었기 때문에 외부에서는 참조할 수 없다. 함수 밖에서 접근하려고 하면 <code>ReferenceError</code> 발생.<br>
<strong>이는 함수 스코프에 따른 정상적인 동작이다.</strong></li>
</ul>
<hr>
<pre><code class="language-jsx">const topLevel = &quot;최상위 변수&quot;;

function outer() {
  const innerVal = &quot;outer의 지역변수&quot;;
  console.log(topLevel); // =&gt; 1️⃣
  console.log(innerVal); // =&gt; 2️⃣
  const innerFn = function () {
    console.log(innerVal); // =&gt; 3️⃣
  };
  innerFn();
}

outer();
console.log(topLevel); // =&gt; 4️⃣
console.log(innerVal); // =&gt; 5️⃣
/* 출력 순서
1️⃣ 2️⃣ 3️⃣ 4️⃣ (5️⃣는 에러)
*/</code></pre>
<ul>
<li>1️⃣ 전역 변수는 함수 내부에서도 참조할 수 있는 스코프 체인을 가진다.</li>
<li>2️⃣ 지역 변수는 선언된 함수 내부에서만 유효하며 외부에서는 불가하다.</li>
<li>3️⃣ 중첩 함수는 상위 함수의 지역 변수까지 접근할 수 있는 클로저다.</li>
<li>4️⃣ 전역 변수는 어디에서든 접근 가능하여 오류 없이 출력된다.</li>
<li>5️⃣ <code>innerVal</code> 은 <code>outer</code>함수가 종료되면 메모리에서 제거되므로 오류.</li>
</ul>
<hr>
<pre><code class="language-jsx">const topLevel = &quot;최상위 변수&quot;;

function outer() {
  const innerVal = &quot;outer의 지역변수&quot;;
  console.log(topLevel); // =&gt; 1️⃣
  console.log(innerVal); // =&gt; 2️⃣
  const innerFn = function () {
    console.log(innerVal); // =&gt; 3️⃣
  };
  return innerFn;
}

const innerFn = outer();
console.log(topLevel); // =&gt; 4️⃣
// console.log(innerVal); // =&gt; 5️⃣
innerFn(); // =&gt; 6️⃣
/* 출력 순서
1️⃣ 2️⃣ 4️⃣ 6️⃣ (5️⃣는 주석 처리)
*/</code></pre>
<ul>
<li>1️⃣ 전역 변수는 하위 함수에서도 접근 가능하다. 스코프 체인 덕분이다.</li>
<li>2️⃣ 지역 변수는 선언된 함수 내부에서만 접근 가능하다. 정상 출력된다.</li>
<li>3️⃣ 내부 함수는 부모 함수의 지역 변수를 참조할 수 있다. (클로저)</li>
<li>4️⃣ 전역 변수는 어디에서든 접근 가능하여 오류 없이 출력된다.</li>
<li>5️⃣ <code>innerVal</code> 은 외부에선 접근할 수 없어 주석 해제 시 오류 발생한다.</li>
<li>6️⃣ <code>innerFn</code>은 <code>outer</code>의 지역변수를 기억하는 클로저로 동작한다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><p>커링(currying)</p>
<ul>
<li><p>여러개의 인자를 받는 함수를 단일 인자를 받는 <code>함수의 체인</code>으로 호출하도록 바꾸는 함수형 프로그래밍 기법 중 하나</p>
<ul>
<li><code>sum(x, y) -&gt; sum(x)(y)</code></li>
</ul>
</li>
<li><p>함수형 프로그래밍 언어에 많은 공헌을 한 미국의 수학자, <strong>논리학자인 하스켈 커리의 이름에서 따옴</strong></p>
</li>
<li><p>함수의 <code>가독성</code>, <code>재사용</code>이 좋아짐.</p>
</li>
<li><p>마지막 인자가 입력될 때까지 함수의 실행 타이밍을 조절할 수 있음.</p>
</li>
<li><p>ex04-03.js</p>
<pre><code class="language-jsx">function sum(a, b, c) {
  return a + b + c;
}
console.log(sum(10, 20, 30));

// 함수 선언식
let currySum = function (a) {
  return function (b) {
    return function (c) {
      return a + b + c;
    };
  };
};

// 화살표 함수
currySum = (a) =&gt; (b) =&gt; (c) =&gt; a + b + c; 
// 실행 할 코드가 a, b, c 각각 하나이기 때문에
// 중괄호 생략 가능함

console.log(currySum(10)(20)(30));</code></pre>
<p>  📌 정리된 호출 구조</p>
<pre><code class="language-r">  currySum(10)
     └──&gt; returns (b) =&gt; (c) =&gt; a + b + c

  currySum(10)(20)
     └──&gt; returns (c) =&gt; a + b + c

  currySum(10)(20)(30)
     └──&gt; returns 60</code></pre>
</li>
<li><p>ex04-04.js, index.html</p>
<pre><code class="language-html">  &lt;script src=&quot;https://unpkg.com/lodash@4.17.21/lodash.js&quot;&gt;&lt;/script&gt;</code></pre>
<p>lodash 라이브러리의 유틸 함수들을 웹에서 바로 사용하기 위해 추가한다. ✅</p>
<pre><code class="language-jsx">const sum = function (x, y) {
  return x + y;
};

const currySum = _.curry(sum);

console.log(sum(10, 20));

console.log(currySum(30)(40));
</code></pre>
<p>앞서 03에서 열심히 함수를 리턴하는 방식으로 커링을 직접 만들었지만,
lodash의 _.curry를 쓰면 이런 코드를 자동으로 커링 함수로 변환해준다.</p>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><p>캡슐화</p>
<ul>
<li><p>객체 내부에서만 접근 가능한 속성을 만들어 사용하고 외부에서는 해당 속성을 직접 접근하지 못하도록 만드는 객체지향 언어의 특징(C++, Java에서는 private 키워드로 지정가능)</p>
</li>
<li><p>함수 내부에서 선언한 지역변수는 외부에서 접근하지 못하는 반면 내부 메서드인 클로저에서는 접근 가능하다는 특징을 이용해서 구현</p>
</li>
<li><p>ES2019에서 class 정의시 속성명이나 메서드명 앞에 #을 붙이면 해당 class 내부에서만 접근 가능한 private 속성과 메서드 정의 기능이 추가됨</p>
</li>
<li><p>ex04-02.js</p>
<pre><code class="language-jsx">// count 속성과 ride(), getCount() 메서드 작성
const Counter = function () {
  this.count = 0;
  this.getCount = function () {
    return this.count;
  };
  this.ride = function () {
    this.count++;
  };
};

const c = new Counter();
c.ride();
c.ride();

c.count += 40;

console.log(&quot;전체 탑승자&quot;, c.getCount()); </code></pre>
<ul>
<li><p>✅ 현재 코드의 주요 문제점</p>
<ol>
<li><p><strong><code>count</code>를 외부에서 직접 수정 가능함 (<code>캡슐화 위반</code>)</strong></p>
<ul>
<li>아래 코드처럼 외부에서 <code>count</code>를 직접 조작할 수 있어:<pre><code class="language-jsx">c.count += 40;</code></pre>
</li>
<li>이렇게 되면 <code>ride()</code> 메서드를 우회해서 값을 변경하는 게 가능하니까,내부 로직의 신뢰성을 깨뜨리게 돼.</li>
<li>예를 들어 누군가 실수로 <code>c.count = -999</code>처럼 바꾸면 전체 로직이 무너짐.</li>
</ul>
</li>
<li><p><strong>객체의 상태 관리가 허술함</strong></p>
<ul>
<li><code>ride()</code> 메서드는 <code>count</code>를 1씩 증가시키는 역할인데,외부에서 직접 <code>count</code>를 바꿔버리면 <code>ride()</code> 호출 여부와 무관해짐.</li>
<li>즉, 내부 동작 추적이나 디버깅이 어려워지고, &quot;진짜 몇 번 탔는가?&quot;를 보장할 수 없음.</li>
</ul>
</li>
</ol>
</li>
</ul>
<hr>
<pre><code class="language-jsx">  // 계선점
  // count 속성과 ride(), getCount() 메서드 작성
  const Counter = function () {
    let count = 0;
    this.getCount = function () {
      return count;
    };
    this.ride = function () {
      if (count &lt; 40) {
        count++;
      } else {
        console.log(&quot;정원이 초과되었습니다.!&quot;);
      }
    };
  };

  const c = new Counter();
  c.ride();
  c.ride();

  for (let i = 0; i &lt; 40; i++) {
    c.ride();
  }

  console.log(&quot;전체 탑승자&quot;, c.getCount());
</code></pre>
<ul>
<li><p>✅ 개선된 점</p>
<ol>
<li><p><strong><code>count</code>가 클로저로 보호됨 (은닉화 성공)</strong></p>
<ul>
<li><code>let count = 0;</code>이 생성자 함수 내부에 선언되어,외부에서는 <code>count</code>에 <strong>직접 접근하거나 수정할 수 없음</strong>.</li>
<li>이제 <code>c.count += 40</code> 같은 조작은 불가능하고, 오직 메서드로만 조작 가능함.</li>
</ul>
</li>
<li><p><strong>불필요한 전역 변수 사용 제거됨</strong></p>
<ul>
<li><code>for</code>문에서 <code>let i = 0</code>을 사용해, <code>i</code>가 <strong>블록 스코프 변수</strong>가 되었음.</li>
<li>이전에는 <code>i</code>가 전역 변수로 암묵 선언되어 다른 코드에 영향을 줄 수 있었지만,이젠 안전하게 해당 블록 안에서만 동작함.</li>
</ul>
</li>
<li><p><strong>정원 제한 기능 추가로 안정성 향상</strong></p>
<ul>
<li><code>ride()</code> 메서드에 <code>count &lt; 40</code> 조건이 생겨, <strong>최대 탑승 인원 제한 가능</strong>.</li>
<li>초과 탑승 시 <code>&quot;정원이 초과되었습니다.!&quot;</code> 메시지를 출력하고 증가하지 않음.</li>
<li>실세계 조건(예: 엘리베이터 인원제한 등)과 유사하게 제어 가능함.</li>
</ul>
</li>
<li><p><strong>캡슐화 + 로직 제어 동시 적용</strong></p>
<ul>
<li>내부 상태는 외부에서 숨기면서, 탑승 조건까지 논리적으로 제어함.</li>
<li>코드의 <strong>일관성, 안정성, 유지보수성</strong> 모두 향상됨.</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><p>Partial application</p>
<ul>
<li><p>기존 함수의 매개변수 중 일부를 미리 채워둔 상태의 함수</p>
</li>
<li><p>커링된 함수를 일부 단계까지만 호출한 후 반환받은 함수를 나중에 나머지 인자를 전달해서 실행</p>
</li>
<li><p>ex02-17-05.js</p>
<pre><code class="language-jsx">// 기존 ex02-17-05.js
var count = 0;
const myObj = {
  count: 0,
  visit: function(){
    // 방문자를 한명 증가시킨다.
    this.count++; // this = myObj
    const visit2 = function(){
      this.count++; // this = window
    };
    visit2();
  },
};

myObj.visit(); // this = myObj
myObj.visit();
console.log(&#39;방문자수&#39;, myObj.count); // 2</code></pre>
<pre><code class="language-jsx">// 변경된 ex02-17-05.js
var count = 0;
const myObj = {
  count: 0,
  visit: function () {
    // 방문자를 한명 증가시킨다.
    this.count++; // this = myObj
    const visitN = function (n) {
      this.count += n; // this = window
    };
    visitN.call(this, 2); // count를 2명 증가 =&gt; 1 + 2 = 3
    visitN.call(this, 2); // count를 2명 증가 =&gt; 3 + 2 = 5

    const visit3 = visitN.bind(this, 3);
    visit3(); // conut를 3명 증가 =&gt; 5 + 3 = 8 
    visit3(); // conut를 3명 증가 =&gt; 8 + 3 =&gt; 11 
  },
};

myObj.visit(); // this = myObj =&gt; 11
myObj.visit(); 
// 11 → 12(11 + 1) → 14(12 + 2) → 16(14 + 2) → 19(16 + 3) → 22(19 +3) 
console.log(&quot;방문자수&quot;, myObj.count); // 22</code></pre>
<ul>
<li><p>✅ 어떻게 바뀌었는가?</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>왼쪽 코드</th>
<th>오른쪽 코드</th>
</tr>
</thead>
<tbody><tr>
<td>내부 함수 이름</td>
<td><code>visit2</code> (매개변수 없음)</td>
<td><code>visitN</code> (매개변수 <code>n</code> 사용 가능)</td>
</tr>
<tr>
<td>호출 방식</td>
<td>그냥 호출 (<code>visit2()</code>)</td>
<td><code>call</code>, <code>bind</code> 사용해 <code>this</code> 명확하게 설정</td>
</tr>
<tr>
<td>this 바인딩 문제</td>
<td>내부 함수에서 <code>this</code>는 <code>window</code> (또는 <code>undefined</code>)</td>
<td><code>call</code>, <code>bind</code>로 <code>this</code>를 명시적으로 <code>myObj</code>로 설정</td>
</tr>
<tr>
<td>유연성</td>
<td>방문자 1명씩 증가만 가능</td>
<td><code>n</code>명씩 유동적으로 증가 가능</td>
</tr>
<tr>
<td>재사용성</td>
<td>없음</td>
<td>있음 → 함수 재사용 가능 (<code>visitN</code>, <code>visit3</code>)</td>
</tr>
</tbody></table>
<hr>
<ul>
<li><p><strong>💡 어떤 점이 좋은가?</strong></p>
<ol>
<li><p><strong>this 바인딩 문제 해결</strong></p>
<ul>
<li>왼쪽에서는 <code>visit2()</code>를 일반 함수처럼 호출해서 <code>this</code>가 <code>myObj</code>가 아님</li>
<li>오른쪽에서는 <code>call</code>, <code>bind</code>를 사용해 <code>this</code>를 <code>myObj</code>로 고정시켜 문제 해결됨</li>
</ul>
</li>
<li><p><strong>유연한 매개변수 처리</strong></p>
<ul>
<li>왼쪽은 무조건 1씩 증가</li>
<li>오른쪽은 <code>n</code>을 전달할 수 있어, 1명, 2명, 3명 등 자유롭게 설정 가능 → <code>visitN(this, 2)</code> → 방문자 2명 증가</li>
</ul>
</li>
<li><p><strong>재사용성 향상</strong></p>
<ul>
<li>오른쪽의 <code>visitN</code>은 범용 함수로 여러 상황에서 재사용 가능</li>
<li><code>bind</code>로 미리 <code>this</code> 고정해 만든 <code>visit3</code>은 나중에 반복 호출하기도 쉬움</li>
</ul>
</li>
<li><p><strong>코드 확장성 향상</strong></p>
<ul>
<li>함수 하나만 바꾸면 여러 상황에 적용 가능 → 유지보수 쉬워짐</li>
<li>이후 방문 수를 로그에 저장하거나 조건부로 제한할 때도 유용함</li>
</ul>
</li>
</ol>
</li>
</ul>
<hr>
<ul>
<li><strong>📌 한줄 요약</strong>
👉 <code>this</code> 바인딩 문제를 해결하고, <strong>매개변수를 받아 유연하고 재사용 가능한 함수 구조</strong>로 개선한 점이 핵심!</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>  ---

  - ✅ `bind()`란?
    `bind()`는 **함수의 `this` 값을 고정**해서 **새로운 함수를 반환**하는 메서드야.
    단, **바로 실행되지는 않고** 고정된 `this`를 가진 **새 함수만 리턴**해!

    ---

    - **🧠 핵심 개념 정리**

    - `bind()`는 기존 함수를 **복제**하면서 `this`를 지정한 함수로 만듦
    - 원본 함수는 변하지 않음
    - **언제 쓰냐면?**
        - 나중에 호출할 때 `this`가 바뀌지 않도록 미리 고정하고 싶을 때
        - 이벤트 핸들러나 콜백 함수에 넘길 때 `this`가 꼬이는 걸 막기 위해

    - **📌 한줄 요약 (강화 버전)**
    &gt; bind()는 함수의 this를 특정 객체로 고정한 새로운 함수를 반환해, 나중에 호출할 때도 this가 바뀌지 않도록 보장한다.</code></pre><hr>
<ul>
<li><p>메모이제이션</p>
<ul>
<li><p>클로저가 필요 없음</p>
</li>
<li><p>메모이제이션 예제</p>
</li>
<li><p>ex02-23.js, ex04-05.js</p>
<pre><code class="language-jsx">// ex02-23.js
const isPrime = function (num) {
  isPrime._cache = isPrime._cache || {};

  if (isPrime._cache[num] !== undefined) {
    return isPrime._cache[num];
  }

  let prime = &quot;맞음&quot;;
  for (let i = 2; i &lt;= Math.sqrt(num); i++) {
    if (num % i === 0) {
      prime = &quot;아님&quot;;
      break;
    }
  }
  isPrime._cache[num] = prime;
  return prime;
};

console.time(&quot;소요시간&quot;);
console.log(&quot;3 -&gt; &quot;, isPrime(3));
console.log(&quot;4 -&gt; &quot;, isPrime(4));
console.log(&quot;5 -&gt; &quot;, isPrime(5));
console.log(&quot;6 -&gt; &quot;, isPrime(6));
console.log(&quot;7 -&gt; &quot;, isPrime(7));
console.log(&quot;8 -&gt; &quot;, isPrime(8));
console.log(&quot;9 -&gt; &quot;, isPrime(9));
console.log(&quot;1000000007 -&gt; &quot;, isPrime(1000000007));
console.log(&quot;1000000007 -&gt; &quot;, isPrime(1000000007));
console.log(&quot;1000000007 -&gt; &quot;, isPrime(1000000007));
console.timeEnd(&quot;소요시간&quot;);
</code></pre>
<pre><code class="language-jsx">// ex04-05.js
Function.prototype.memo = function (key) {
  this._cache = this._cache || {};

  if (this._cache[key] !== undefined) {
    return this._cache[key];
  } else {
    return (this._cache[key] = this(key));
  }
};

const isPrime = function (num) {
  let prime = &quot;맞음&quot;;

  for (let i = 2; i &lt; num; i++) {
    if (num % i === 0) {
      prime = &quot;아님&quot;;
      break;
    }
  }

  return prime;
};

console.time(&quot;소요시간&quot;);
console.log(&quot;3 -&gt; &quot;, isPrime(3));
console.log(&quot;4 -&gt; &quot;, isPrime(4));
console.log(&quot;5 -&gt; &quot;, isPrime(5));
console.log(&quot;6 -&gt; &quot;, isPrime(6));
console.log(&quot;7 -&gt; &quot;, isPrime(7));
console.log(&quot;8 -&gt; &quot;, isPrime(8));
console.log(&quot;9 -&gt; &quot;, isPrime(9));
console.log(&quot;1000000007 -&gt; &quot;, isPrime.memo(1000000007)); // 첫번째 캐싱
console.log(&quot;1000000007 -&gt; &quot;, isPrime.memo(1000000007)); // 2번째 캐싱
console.log(&quot;1000000007 -&gt; &quot;, isPrime.memo(1000000007)); // 3번째 캐싱
console.timeEnd(&quot;소요시간&quot;);
</code></pre>
<pre><code class="language-markdown">isPrime.memo(3)
│
├─&gt; memo 메서드 실행
│    ├─&gt; 캐시 확인/초기화
│    ├─&gt; 캐시에 3이 없으므로
│    │    └─&gt; isPrime(3) 실행
│    │         └─&gt; 소수 판별 후 true 반환
│    └─&gt; 캐시에 저장 후 true 반환
│
isPrime(3)
└─&gt; isPrime 함수 바로 실행
      └─&gt; 소수 판별 후 true 반환</code></pre>
<ul>
<li><p>✅ 개선된 점 요약</p>
<ol>
<li><p><strong>메모이제이션 로직을 함수 밖으로 분리 (재사용 가능성 증가)</strong></p>
<ul>
<li>🔽 왼쪽: <code>isPrime</code> 함수 안에서 <code>_cache</code> 관리</li>
<li>🔼 오른쪽: <code>Function.prototype.memo</code>로 메모이제이션을 <strong>유틸리티 함수화</strong> → 다른 함수에서도 <code>.memo()</code> 호출만으로 캐시 기능을 간편하게 쓸 수 있음</li>
</ul>
</li>
<li><p><strong>관심사의 분리 (기능 분리로 가독성 향상)</strong></p>
<ul>
<li>왼쪽은 <strong>소수 판별 로직 + 캐시 로직이 뒤섞여</strong> 있음</li>
<li>오른쪽은 <code>isPrime</code>은 오직 <strong>소수 판별만</strong>, <code>memo</code>는 <strong>캐싱만 처리</strong>해서 코드 역할이 명확히 나뉨</li>
</ul>
</li>
<li><p><strong>코드 재사용성 증가</strong></p>
<ul>
<li><p><code>Function.prototype.memo</code>를 모든 함수에서 사용할 수 있음:</p>
<pre><code class="language-jsx">const slowFn = (x) =&gt; { ... };
slowFn.memo(x); // 캐싱 자동 처리</code></pre>
</li>
</ul>
</li>
<li><p><strong>함수 정의가 더 순수해짐 (Pure Function화)</strong></p>
<ul>
<li><code>isPrime</code>은 캐시나 외부 상태 없이 <strong>오직 인자만으로 동작</strong></li>
<li>이로 인해 테스트, 디버깅, 재사용이 훨씬 쉬워짐</li>
</ul>
</li>
<li><p><strong>코드의 확장성 향상</strong></p>
<ul>
<li>이후 <code>memo()</code>에 만료 시간, 캐시 크기 제한 같은 기능도 쉽게 추가 가능</li>
<li>개별 함수 수정 없이 메모이제이션 정책을 전역에서 관리할 수 있음</li>
</ul>
</li>
</ol>
<p>📌 한 줄 요약</p>
<blockquote>
<p>기능 분리 + 재사용성 + 유지보수성 + 확장성까지 모두 좋아진 구조!</p>
</blockquote>
</li>
<li><p>설명</p>
<pre><code class="language-jsx">// ex04-05.js
Function.prototype.memo = function (key) {
  this._cache = this._cache || {};

  if (this._cache[key] !== undefined) {
    return this._cache[key];
  } else {
    return (this._cache[key] = this(key));
  }
};

const isPrime = function (num) {
  let prime = &quot;맞음&quot;;
  for (let i = 2; i &lt; num; i++) {
    if (num % i === 0) {
      prime = &quot;아님&quot;;
      break;
    }
  }
  return prime;
};

const sayHello = function (name) {
  return &quot;Hello&quot; + name;
};

console.log(sayHello(&quot;캐싱 안함&quot;));
console.log(sayHello.memo(&quot;캐싱 함&quot;));
console.log(sayHello.memo(&quot;캐싱 함&quot;));

console.time(&quot;소요시간&quot;);

console.log(&quot;3 -&gt; &quot;, isPrime(3));
console.log(&quot;4 -&gt; &quot;, isPrime(4));
console.log(&quot;5 -&gt; &quot;, isPrime(5));
console.log(&quot;6 -&gt; &quot;, isPrime(6));
console.log(&quot;7 -&gt; &quot;, isPrime(7));
console.log(&quot;8 -&gt; &quot;, isPrime(8));
console.log(&quot;9 -&gt; &quot;, isPrime(9));

console.log(&quot;1000000007 -&gt; &quot;, isPrime.memo(1000000007));
console.log(&quot;1000000007 -&gt; &quot;, isPrime.memo(1000000007));
console.log(&quot;1000000007 -&gt; &quot;, isPrime.memo(1000000007));

console.timeEnd(&quot;소요시간&quot;);
</code></pre>
<ul>
<li><p>1️⃣ 1. <code>Function.prototype.memo = function (key) { ... }</code></p>
<p>📌 핵심 기능</p>
<p><strong>모든 함수에 공통적으로 사용할 수 있는 메모이제이션 기능</strong>을 추가함</p>
<p><code>this._cache</code>를 통해 <strong>함수 단위로 캐시 객체를 저장</strong></p>
<h2 id="같은-입력이-들어오면-결과를-다시-계산하지-않고-캐시된-값-반환">같은 입력이 들어오면 결과를 <strong>다시 계산하지 않고 캐시된 값 반환</strong></h2>
</li>
<li><p>2️⃣ <code>sayHello.memo(&quot;캐싱 함&quot;)</code></p>
<p>📌 역할</p>
<ul>
<li><code>sayHello(&quot;캐싱 함&quot;)</code>을 최초 한 번 계산 후 캐시에 저장</li>
<li>두 번째부터는 <strong>새로 계산하지 않고 저장된 결과를 반환</strong></li>
</ul>
<p>🧩 포인트</p>
<ul>
<li><code>&quot;캐싱 함&quot;</code> → 내부적으로 <code>sayHello._cache[&quot;캐싱 함&quot;]</code>에 저장됨</li>
<li>결과적으로 <strong>불필요한 계산을 줄여 성능 향상</strong></li>
</ul>
<hr>
</li>
<li><p>3️⃣ <code>isPrime.memo(1000000007)</code></p>
<p>📌 역할
소수 판별 함수 <code>isPrime</code>에 대해 <strong>고비용 계산을 메모이제이션으로 최적화</strong></p>
<p><code>1000000007</code>은 매우 큰 수이므로 <strong>첫 계산에 시간이 오래 걸림</strong></p>
<p>이후 동일한 입력에 대해선 즉시 캐시된 값 반환</p>
</li>
</ul>
<hr>
<p>🧩 정리: 강조된 부분의 의미</p>
<table>
<thead>
<tr>
<th>번호</th>
<th>코드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>1️⃣</td>
<td><code>Function.prototype.memo</code></td>
<td>모든 함수에 캐시 기능 부여</td>
</tr>
<tr>
<td>2️⃣</td>
<td><code>sayHello.memo(...)</code></td>
<td>단순 문자열 반환 함수도 캐싱 가능</td>
</tr>
<tr>
<td>3️⃣</td>
<td><code>isPrime.memo(...)</code></td>
<td>고비용 연산의 캐싱 효과를 보여주는 사례</td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li><p>index.html <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/index.html">커링(currying) 기법 라이브러리 스크립트 등록</a></p>
</li>
<li><p>ex02</p>
<ul>
<li>17-05 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-17-05.js">bind 메서드</a></li>
<li>23 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-23.js">반쪽자리 메모이제이션 적용해보기</a></li>
</ul>
</li>
<li><p>ex03</p>
<ul>
<li>02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch03/ex03-02.js">prototype을 사용하지 않고 생성자 함수 내부에 메서드 작성</a></li>
<li>03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch03/ex03-03.js">prototype으로 메서드 작성</a></li>
<li>04 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch03/ex03-04.js">프로토타입 체인을 이용한 상속 기능 구현</a></li>
<li>05 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch03/ex03-05.js">create, 중간자 함수 사용</a></li>
<li>06 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch03/ex03-06.js">프로토타입 체인을 이용한 상속 기능 구현</a></li>
</ul>
</li>
<li><p>ex04</p>
<ul>
<li>01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch04/ex04-01.js">closure 첫만남</a></li>
<li>02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch04/ex04-02.js">closure 외부 스코프에서 count의 값을 올리지 못하게 막는 예제 </a></li>
<li>03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch04/ex04-03.js">커링(currying) 기법 사용하기</a></li>
<li>04 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch04/ex04-04.js">커링(currying) 기법 사용하기</a></li>
<li>05 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch04/ex04-05.js">prototype으로 여러 함수를 캐시 시키도록 수정 </a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>아..오늘 배웠던거 너무 어렵다... 선생님께서 오늘 배운거 어려운 개념이라고 하는데 진짜<del>~</del> 너무 어려웠다... 질문도 막 하고 싶은데 아직 지식이 없는지 질문이 떠오르진 않았다..</li>
</ul>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://ko.javascript.info/prototype-inheritance">상속과 프로토타입 | javascript.info</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">상속과 프로토타입 | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Classes">class | mdn</a></li>
<li><a href="https://ko.javascript.info/class">class | 모던자바스크립트</a></li>
<li><a href="https://ko.javascript.info/closure">closure | javascript.info</a></li>
<li><a href="https://poiemaweb.com/js-closure">closure | 모던자바스크립트</a></li>
<li><a href="https://velog.io/@tap_kim/memoization-in-js-ts">메모이제이션 | TapK의 velog</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bind | mdn</a></li>
<li><a href="https://ko.javascript.info/currying-partials">커링 (Currying) | javascript.info</a></li>
<li><a href="https://relieved-mandolin-d86.notion.site/1905b56ad8d38056b86bf234f3009b03">노션 정리 링크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[📆 2025.04.21 ‐ 2025.04.22 ‐ Function invocation [멋쟁이사자처럼부트캠프 프론트엔드13기]]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.21-2025.04.22-Function-invocation-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025.04.21-2025.04.22-Function-invocation-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Tue, 22 Apr 2025 13:08:16 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<ul>
<li><h3 id="함수로-호출">함수로 호출</h3>
<ul>
<li><p>일반적인 함수 호출 방법</p>
</li>
<li><p><code>함수();</code></p>
</li>
<li><p>this 는 window 객체</p>
<ul>
<li>window 객체는 어디서나 참조 가능하므로 this를 사용할 필요 없음</li>
</ul>
<pre><code class="language-jsx">function f1(){
  console.log(this);
  this.alert();
  window.alert();
  alert();
};
f1();

const f2 = function(){
  console.log(this);
};
f2();</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="메서드">메서드</h3>
<ul>
<li><p>메서드로 호출</p>
<ul>
<li><p><strong>객체에 정의된 메서드를 호출할 때</strong></p>
</li>
<li><p>객체 메서드명</p>
</li>
<li><p>this 는 메서드를 정의한 객체</p>
<ul>
<li>this 는 생성된 객체를 참조하므로 객체에 종속적인 속성을 부여하는게가능</li>
<li>함수를 하나만 정의하고 여러 객체에서 메서드로 사용</li>
<li>자바스크립트로 객체지향 프로그래밍을 가능하게 하는 중요한 특징</li>
</ul>
<pre><code class="language-jsx">window.name = &quot;global&quot;; // window 브라우저가 가지고 있는 전역 객체
global.name = &quot;global&quot;; // node.js가 가지고 있는 전역 객체
globalThis.name = &quot;global&quot;; // 브라우저면 window로 인식하고 node.js는 global로 인식함</code></pre>
</li>
</ul>
</li>
<li><p>화살표 함수 호출</p>
<ul>
<li>일반 함수나 메서드와 동일하게 호출하지만 함수 내부에 <code>arguments</code> 나 <code>this</code> 가 생성되지 않고 상위 컨텍스트의 arguments, this 를 사용하게 됨</li>
</ul>
<pre><code class="language-jsx">const getPingName = () =&gt; {
  console.log(this);
  return this.name;
};

const ping1 = { name: &#39;바로핑&#39;, age: 11, getName: getPingName };
const ping2 = { name: &#39;라라핑&#39;, age: 9, getName: getPingName };

console.log(baro.age, baro.getName());
console.log(rara.age, rara.getName());</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="apply-call">apply(), call()</h3>
<ul>
<li><p>apply(), call() 메서드로 호출</p>
<ul>
<li>함수에 정의된 메서드</li>
<li>함수명.apply(), 함수명.call() 형태로 호출</li>
<li><strong>this 는 apply(), call() 메소드의 <code>첫번째 인자</code>로 전달되는 객체</strong></li>
<li>this 를 명시적으로 지정할 수 있음</li>
<li>콜백 함수 호출 시 주로 사용</li>
</ul>
</li>
<li><p>apply(p1, p2)</p>
<ul>
<li><p>두 개의 매개변수를 가짐</p>
</li>
<li><p>첫 번째 매개변수 (p1) 에는 this 로 사용할 객체를 전달 ⇒ 생략가능</p>
</li>
<li><p>두 번째 매개변수 (p2) 에는 함수에 전달할 인자값 배열 ⇒ 생략가능</p>
</li>
<li><p>단 매개변수가 2개 이상으로 들어가야할때는 p2를 배열로 전달한다</p>
<ul>
<li><p>ex02-05.js</p>
<pre><code class="language-jsx">function add(x, y) {
  console.log(this);
  return x + y;
}

console.log(add.apply({ name: &quot;apply&quot; }, [100, 10])); // this는 {name: &quot;apply&quot;}
// 출력 결과 {name: &quot;apply&quot;}
// x= 100, y=10 =&gt; x + y = 100 + 10 = 110</code></pre>
<p><img src="https://github.com/user-attachments/assets/53f9e562-5e24-4a99-80da-a94567c34898" alt="image"></p>
</li>
<li><p>ex02-15.js</p>
<pre><code class="language-jsx">globalThis.name = &quot;global&quot;; // 브라우저면 window로 인식하고 node.js는 global로 인식함

const getPingName = function () {
  return this.name;
};

const baro = new Object();
baro.name = &quot;바로핑&quot;;
baro.age = 9;
baro.getName = getPingName;

const rara = {
  name: &quot;라라핑&quot;,
  age: 8,
  getName: getPingName,
};

// 함수 호출하는 방법 1 - 일반 함수로 호출(this는 window)
console.log(getPingName());

// 함수 호출하는 방법 2 - 메서드로 호출(this는 메서드를 정의한 객체, this는 baro )
console.log(baro.age, baro.getName()); // getName의 this는 baro
console.log(rara.age, rara.getName()); // getName의 this는 rara

console.log(&quot;=========================================&quot;);
console.log(baro.getName(), baro.getName.apply(rara)); 
// this는 각각     baro,     rara</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><p>call(<code>p1</code>, p2, p3, …)</p>
<ul>
<li><p><strong>여러 개의 매개변수를 가짐</strong></p>
</li>
<li><p>첫 번째 매개변수 (p1) 에는 <code>this</code> 로 사용할 객체를 전달</p>
</li>
<li><p>두 번째 이후의 매개변수 (p2, p3, …) 에는 <code>함수에 전달할 인자값</code>을 차례대로지정</p>
<ul>
<li><p>ex02-05.js</p>
<pre><code class="language-jsx">function add(x, y) {
  console.log(this);
  return x + y;
}
console.log(add.call({ name: &quot;call&quot; }, 60, 10)); // this는 {name: &quot;call&quot;}
// 출력 결과 {name: call}
// x= 60, y=10 =&gt; x + y = 60 + 10 = 70</code></pre>
<p><img src="https://github.com/user-attachments/assets/cdb84fc9-d095-44d1-ae5f-1b2227d511e1" alt="image"></p>
</li>
<li><p>ex02-15.js</p>
<pre><code class="language-jsx">globalThis.name = &quot;global&quot;; // 브라우저면 window로 인식하고 node.js는 global로 인식함

const getPingName = function () {
  return this.name; // 호출한 객체의 name 속성을 반환함
};

const baro = new Object(); // 바로라는 이름을 가진 새로운 객체 생성
baro.name = &quot;바로핑&quot;; // name 속성 설정
baro.age = 9; // age 속성 설정
baro.getName = getPingName; // getPingName 함수를 메서드로 할당

const rara = { // rara라는 이름을 가진 새로운 배열을 만듦
  name: &quot;라라핑&quot;, // 이름
  age: 8, // 나이
  getName: getPingName, // 나의 이름
};

// 함수 호출하는 방법 1 - 일반 함수로 호출(this는 window)
console.log(getPingName());  // this.name =&gt; global

// 함수 호출하는 방법 2 - 메서드로 호출(this는 메서드를 정의한 객체, this는 baro )
console.log(baro.age, baro.getName()); // getName의 this는 baro
console.log(rara.age, rara.getName()); // getName의 this는 rara

// call을 사용하여 this를 명시적으로 지정
console.log(&quot;=========================================&quot;);
console.log(getPingName(), getPingName.call(baro), getPingName.call(rara));
// this는  window,                          baro,                   rara</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><p>배열의 <code>push()</code> 메서드 기능</p>
<ul>
<li>배열의 마지막에 지정한 요소를 추가한다.</li>
<li><code>this</code>로 지정된 Array 객체의 <code>length</code> 속성값에 해당하는 속성을 만들고 지정한 요소를 저장한 후 <code>length</code>를 하나 증가시킨다.</li>
</ul>
</li>
<li><p>Array의 <code>push()</code> 메서드를 이용하여 객체를 배열처럼 동작시키기</p>
<ul>
<li><code>length</code> 속성 추가</li>
<li>Array.prototype.push.call(<code>객체</code>, 추가할 요소) ⇒ ex01-28.js</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="생성자-함수">생성자 함수</h3>
<ul>
<li><p>생성자 함수 (객체지향 언어의 클래스와 비슷) 호출</p>
<ul>
<li>함수를 생성자로 사용할 경우<ul>
<li><code>new 함수명()</code></li>
<li><code>this</code>는 <strong>생성자를 통해 생성된 객체</strong></li>
</ul>
</li>
</ul>
</li>
<li><p>생성자로 호출될 때의 내부 동작 (<a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-19.js">ex02-19.js</a>)</p>
<pre><code class="language-jsx">/*
함수 호출 방법 4 생성자 함수
*/

globalThis.name = &quot;global&quot;; // 브라우저면 window로 인식하고 node.js는 global로 인식함

const getPingName = function () {
  return this.name;
  // 화살표 함수를 만들면 this를 생성하지 않음
};

// 객체를 생성해서 반환하는 함수(생성자)
function Ping(name, age) {
  this.name = name;
  this.age = age;
  this.getName = function () {
    return this.name;
  };
}

/**
 * new의 동작
  * 1. 빈 객체를 참조하는 this 생성
  * 2. this를 생성자 함수에 전달
  * 3. 생성자 함수가 아무것도 리턴하지 않는다면 this를 자동으로 리턴
  */
const baro = new Ping(&quot;바로핑&quot;, 7);
const rara = new Ping(&quot;라라핑&quot;, 8);
const copyPing = new Ping(&quot;카피핑&quot;, 12);

baro.age++;
rara.age++;

console.log(&quot;이 핑의 이름은:&quot;, baro.getName(), &quot;| 나이는:&quot;, baro.age); // getName의 this는 baro
console.log(&quot;이 핑의 이름은:&quot;, rara.getName(), &quot;| 나이는:&quot;, rara.age); // getName의 this는 rara
console.log(&quot;이 핑의 이름은:&quot;, copyPing.getName(), &quot;| 나이는:&quot;, copyPing.age); // getName의 this는 copyPing
</code></pre>
<ul>
<li><strong>비어있는 객체를 새로 생성</strong></li>
</ul>
<pre><code class="language-jsx">const baro = new Ping(&quot;바로핑&quot;, 7);</code></pre>
<blockquote>
<p>new Ping(...)을 호출하면, 자바스크립트는 내부적으로</p>
<p><code>this = {}</code> 와 같은 <strong>비어 있는 객체</strong>를 먼저 생성한다.</p>
</blockquote>
<hr>
<ul>
<li><strong>새로 생성된 객체는 <code>this</code> 매개변수로 생성자 함수에 전달</strong></li>
</ul>
<pre><code class="language-jsx">function Ping(name, age) {
  this.name = name;
  this.age = age;
  this.getName = function () {
    return this.name;
  };
}</code></pre>
<blockquote>
<p>위에서 만들어진 this = {}는</p>
<p><code>Ping</code> 함수 안으로 <strong><code>this</code>라는 이름으로 들어감</strong></p>
<p>그런 다음 <code>this.name</code>, <code>this.age</code> 같은 속성들이 <strong>채워짐</strong></p>
</blockquote>
<hr>
<ul>
<li><strong>명시적으로 반환하는 객체가 없다면 생성된 객체를 반환</strong></li>
</ul>
<pre><code class="language-jsx">// Ping 함수에는 return이 없음</code></pre>
<blockquote>
<p>Ping 함수는 명시적으로 return을 하지 않음 →</p>
<p>그래서 자바스크립트는 자동으로 <strong>채워진 <code>this</code> 객체를 리턴</strong>함</p>
<p>즉, <code>baro</code> 변수에는 <code>{ name: &quot;바로핑&quot;, age: 7, getName: function }</code>이 저장됨</p>
</blockquote>
<hr>
<ul>
<li><strong>객체지향 프로그램의 <code>new</code> 연산자와 비슷한 동작</strong><pre><code class="language-jsx">const baro = new Ping(&quot;바로핑&quot;, 7);</code></pre>
</li>
</ul>
<blockquote>
<p>이 전체 흐름은 Java, C++ 같은 <strong>객체지향 언어에서의 new</strong>와 유사함</p>
<p>즉, <code>new</code>는 객체 생성 + 초기화 + 반환까지 한 번에 해주는 키워드야</p>
</blockquote>
</li>
<li><p>생성자를 작성할 때 고려해야 할 것들</p>
<ul>
<li>일반 함수처럼 호출할 수 있지만, 이럴 경우 생성자 내부의 <code>this</code>는 <code>window</code> 객체를 가리키므로 객체에 종속적인 값을 지정할 수 없으므로 의미가 없다.</li>
<li><strong>명명(naming) 규칙</strong><ul>
<li>일반 함수: 작업한 동작을 나타내는 <strong>동사</strong>로 이름 짓고 소문자로 시작</li>
<li>생성자: 생성할 객체를 나타내는 <strong>명사</strong>로 이름 짓고 대문자로 시작</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li>ex02-14 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-14.js">this는 window 객체</a></li>
<li>ex02-15 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-15.js">메서드-function</a></li>
<li>ex02-16 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-16.js">메서드-function 화살표 함수</a></li>
<li>ex02-17-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-17-01.js">카운터 예제 - visit2 함수 호출 실패</a></li>
<li>ex02-17-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-17-02.js">카운터 예제 - visit2 함수 호출 (변수선언)</a></li>
<li>ex02-17-03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-17-03.js">카운터 예제 - visit2 함수 호출 (call)</a></li>
<li>ex02-17-04 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-17-04.js">카운터 예제 - visit2 함수 호출 (화살표 함수)</a></li>
<li>ex02-17-05 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-17-05.js">카운터 예제 - visit2 함수 호출 실패</a></li>
<li>ex02-18-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-18-01.js">최소값을 반환 - apply사용</a></li>
<li>ex02-18-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-18-02.js">최소값을 반환 - 전개 연산자(...) 사용</a></li>
<li>ex02-19 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-19.js">생성자 함수</a></li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>this...그놈의 this... 딥다이브 열심히 보면서 해결해야겠다... </li>
</ul>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://hoya-kim.github.io/2021/10/02/globalThis/">전역 객체 | hoya&#39;s dev blog</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/globalThis">globalThis | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/this">this | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/call">call | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/apply">apply | mdn</a></li>
<li><a href="https://relieved-mandolin-d86.notion.site/1905b56ad8d38056b86bf234f3009b03">노션 정리 링크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[📆 2025.04.21 ‐ JavaScript Function Deep Dive [멋쟁이사자처럼부트캠프 프론트엔드13기]]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.21-JavaScript-Function-Deep-Dive-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025.04.21-JavaScript-Function-Deep-Dive-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Mon, 21 Apr 2025 08:45:01 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<ul>
<li><h3 id="first-class-object">First class object</h3>
<ul>
<li><strong>일급 객체</strong><ul>
<li>변수 , 배열 엘리먼트 , 다른 객체의 프로퍼티에 <code>할당</code> 될 수 있다
<img src="https://github.com/user-attachments/assets/80b3e27c-cf66-42f1-a1f1-f164b27bde9f" alt="image"></li>
<li>함수의 <code>인자로 전달</code> 될 수 있다</li>
<li>함수의 결과 값으로 <code>반환</code> 될 수 있다</li>
<li>리터럴로 생성될 수 있다</li>
<li>동적으로 생성된 프로퍼티를 가질 수 있다</li>
</ul>
</li>
<li>자바스크립트의 함수(function) 는 일급객체 이다 <br>
함수 ==  호출 + 객체</li>
<li>함수가 일급 객체라서 가능한 일<ul>
<li>콜백 함수 (Callback function)<ul>
<li>다른 함수에 인자로 전달되어 어떤 작업의 결과로 호출되는 함수</li>
</ul>
</li>
<li>고차 함수 (Higher order function)<ul>
<li>함수를 인자로 받거나 반환 하는 함수</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
</li>
<li><h3 id="함수-생성">함수 생성</h3>
<ul>
<li><p>선언문</p>
<pre><code class="language-jsx">// 기명함수 add라는 이름이 있음
function add(x, y){
  const result = x + y;
  return result;
}
// 익명함수, 함수 이름이 없다
function () {}</code></pre>
<ul>
<li>function 키워드로 시작하는 함수 정의</li>
<li>함수 이름<ul>
<li>유효한 식별자이어야 함</li>
<li><code>생략 가능</code></li>
</ul>
</li>
<li>매개변수 목록<ul>
<li>쉼표로 구분된 매개변수 목록과 그 매개변수 목록을 둘러싸고 있는 괄호</li>
<li>매개변수는 <code>생략 가능</code> , 괄호는 필수</li>
</ul>
</li>
<li>함수 본문<ul>
<li>중괄호로 둘러싸여 있는 자바스크립트 구문</li>
<li><code>본문은 생략 가능 , 중괄호는 필수</code></li>
</ul>
</li>
</ul>
</li>
<li><p>표현식</p>
<ul>
<li><p>함수 정의를 변수에 할당</p>
<ul>
<li>변수명을 함수명처럼 사용</li>
</ul>
</li>
<li><p>변수에 익명함수를 지정 </p>
<pre><code class="language-jsx">const add = function (x,y){
  const result = x + y;
  return result;
};
add(10 , 20)</code></pre>
</li>
<li><p>변수에 기명함수를 지정</p>
<ul>
<li>변수명을 함수명처럼 사용</li>
<li>함수명을 통한 접근은 해당 함수 내부에서만 사용 가능 (재귀 함수)</li>
</ul>
<pre><code class="language-jsx">const f = function factorial(n){
  if( n == 1 ){
  return 1
  }
  return n * factorial(n - 1);
};
console.log(f(5)); // 
console.log(factorial(5)); // 정삭 작동 안됨</code></pre>
</li>
</ul>
</li>
<li><p>Function 생성자 함수</p>
<ul>
<li>함수 객체를 생성해서 반환<pre><code class="language-jsx">const add = new Function(&#39;x&#39;, &#39;y&#39;, &#39;let result = x + y; return result;&#39;);
//    변수 = 새로운 함수 (매개변수1, 매개변수 2, 실행할 코드)</code></pre>
</li>
<li>가독성이 안 좋아서 진짜 잘 안쓰임</li>
</ul>
</li>
<li><p>화살표 함수 표현식</p>
<ul>
<li>함수 표현식의 대안으로 간결하게 함수 정의</li>
<li>익명 함수로만 정의 가능</li>
<li>실행할 코드가 하나만 있다면 함수 본문의 중괄호 생략 가능</li>
<li>함수 본문의 중괄호가 생략될 경우 함수의 코드가 자동으로 리턴값으로 사용됨</li>
<li>매개 변수가 하나만 있다면 매개변수의 괄호 생략 가능</li>
</ul>
<pre><code class="language-jsx">// 기존 함수
let add = function (x, y) {
  return x + y;
};

// 화살표 함수
add = (x, y) =&gt; {
  return x + y;
};

// 화살표 함수 축약 =&gt; 실행할 코드가 단 한개면 가능
add = (x, y) =&gt; x + y;

// add 출력문
console.log(add(10, 20)); // 출력시 10 + 20 = 30</code></pre>
<pre><code class="language-jsx">// 기존 함수
let add10 = function (x) {
  return x + 10;
};

// 화살표 함수
add10 = (x) =&gt; {
  return x + 10;
};

// 화살표 함수 축약 =&gt; 실행할 코드가 단 한개면 가능
add10 = (x) =&gt; x + 10;
add10 = x =&gt; x + 10; // 매개 변수가 하나만 있다면 매개변수의 괄호 생략 가능

// add10 출력문
console.log(add10(100)); // 100 + 10 = 110</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="호이스팅">호이스팅</h3>
<ul>
<li><p>함수 호이스팅</p>
<ul>
<li><code>선언문 형태로 정의한 함수</code> 의 유효 범위가 코드의 맨 처음부터 시작하 게 되는 자바스크립트의 동작 방식</li>
<li>특정 블럭의 코드가 자바스크립트 엔진에 의해 실행 되기 전에 호이스팅 단계를 거치는데 이때 선언문 형태의 함수가 생성 되므로 함수 선언 코드보다 먼저 호출하는 코드를 작성하는게 가능</li>
</ul>
<pre><code class="language-jsx">console.log(&quot;실행 순서 2&quot;, add(10, 20));

function add(x, y) {
  return x + y;
}

console.log(&quot;실행 순서 3&quot;, add(10, 20));</code></pre>
<p> <img src="https://github.com/user-attachments/assets/6d11bc32-fa02-4a3b-a20a-b091dd41b197" alt="image"></p>
</li>
<li><p>변수 호이스팅</p>
<ul>
<li>호이스팅 단계에서 <code>var</code> 로 선언한 변수 의 경우 선언만 되고 그 값은 undefined 로 초기화 됨</li>
<li><code>let, const</code> 로 선언한 변수 의 경우 호이스팅 단계에서 선언은 되지만 초기화가 되지 않기 때문에 선언 전에 접근하면 에러 발생 
(undefined 값도 할당되지 않은 상태)</li>
</ul>
<pre><code class="language-jsx">console.log(a);
console.log(b); // ReferenceError: Cannot access &#39;b&#39; before initialization
console.log(c); // ReferenceError: Cannot access &#39;c&#39; before initialization

var a = 10; // 호이스팅 단계에서 undefinde로 초기화가 돼있음 =&gt; 그래서 에러 안남
let b = 20; // 호이스팅 단계에서 선언만 되고 초기화가 안됨 =&gt; 그래서 에러남
const c = 30; // 호이스팅 단계에서 선언만 되고 초기화가 안됨 =&gt; 그래서 에러남

console.log(a); // 정상적으로 출력 됨
console.log(b); // 정상적으로 출력 됨
console.log(c); // 정상적으로 출력 됨</code></pre>
<pre><code class="language-jsx">console.log(add(10, 20)); 
// TypeError: add is not a function
// var 변수는 호이스팅되지만 초기화는 안되므로 이 시점에서 add는 undefined임

// 표현식 방식의 함수 정의
var add = function (x, y) {
  return x + y;
};

console.log(add(10, 20)); // 정상적으로 30으로 출력됨</code></pre>
</li>
<li><p>TDZ(Temporal Dead Zone)</p>
<ul>
<li>호이스팅 단계에서 변수가 선언된 이후 실제 초기화가 이루어지기 전까지의 구간</li>
<li>변수를 초기화 하기 이전에 변수에 접근할 수 없는 일시적인 영역으로 무분별한 변수 사용을 막고 예측 가능한 코드를 만들기 위한 장치</li>
</ul>
<pre><code class="language-jsx">var add; // 호이스팅 시 선언되고 undefined로 초기화됨

// 본 코드 실행 단계 (아직 함수 할당 전)
console.log(add); 
// 출력 결과: undefined 
// 에러는 아님. 다만 아직 함수가 아님 =&gt; 실행 불가능

// 표현식 방식의 함수 정의 (함수를 변수에 할당)
var add = function (x, y) {
  return x + y;
};

console.log(add(10, 20)); // 30 출력됨
</code></pre>
<ul>
<li><p><strong><a href="">ex01-38.js</a> gpt 설명</strong></p>
<h3 id="🔍-코드-설명">🔍 코드 설명</h3>
<pre><code class="language-jsx">  function max(n1, n2) {
    let result; // 지역 변수 선언 (블록 스코프)

    if (n1 &gt; n2) {
      result = n1;
    } else {
      result = n2;
    }

    return result;
  }
</code></pre>
<hr>
<ul>
<li><p>✅ 주요 포인트 설명</p>
<table>
<thead>
<tr>
<th><strong>항목</strong></th>
<th><strong>설명</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>함수 이름</strong></td>
<td><code>max</code> — 두 수 중 최대값을 반환</td>
</tr>
<tr>
<td><strong>매개변수</strong></td>
<td><code>n1</code>, <code>n2</code> — 비교할 두 숫자</td>
</tr>
<tr>
<td><strong>지역 변수</strong></td>
<td><code>result</code> — 함수 내부에서만 사용되는 변수</td>
</tr>
<tr>
<td><strong>스코프</strong></td>
<td><code>let</code>으로 선언된 <code>result</code>는 <strong>함수 내부(지역)</strong>에서만 유효함</td>
</tr>
<tr>
<td><strong>호이스팅</strong></td>
<td><code>let</code>은 <strong>호이스팅은 되지만 TDZ(Temporal Dead Zone)</strong> 때문에 초기화 전 접근 불가능주석에 <code>var</code>로 바꾸면 호이스팅 학습 예시로 적절함</td>
</tr>
</tbody></table>
</li>
</ul>
<hr>
<ul>
<li><p>🧠 예시로 보는 지역 변수 vs 전역 변수</p>
</li>
<li><p><code>result</code>는 함수 <strong>내부에서만</strong> 선언되었기 때문에 <strong>외부에서 접근 불가능</strong></p>
</li>
<li><p>예시:</p>
<pre><code class="language-jsx">console.log(result); // ReferenceError: result is not defined</code></pre>
</li>
</ul>
<hr>
<ul>
<li><p>💡 <code>var</code>와 <code>let</code>의 차이 예시</p>
<pre><code class="language-jsx">function max(n1, n2) {
// var result; // 호이스팅으로 함수 최상단에 선언된 것처럼 작동
let result;     // let은 TDZ 영향 → 선언 전 접근 불가

if (n1 &gt; n2) {
  result = n1;
} else {
  result = n2;
}

return result;
}
</code></pre>
</li>
<li><p><code>var</code>로 선언하면, 함수 시작 시점에 <code>undefined</code>로 초기화됨</p>
</li>
<li><p><code>let</code>은 선언 시점까지 TDZ에 있으므로, 선언 전 접근 시 ReferenceError</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="매개변수">매개변수</h3>
<ul>
<li><p><strong>기본값 매개변수</strong> (Default parameters)</p>
<ul>
<li>함수 호출시 인자값을 전달하지 않으면 undefined가 전달됨</li>
<li>값이 전달되지 않거나 undefined를 인자값으로 전달한 경우 지정한 매개변수를 기본값으로 초기화</li>
</ul>
</li>
<li><p><strong>나머지 매개변수</strong> (Rest parameters)</p>
<ul>
<li>정해지지 않은 수의 매개변수를 배열로 전달받음</li>
<li>함수의 마지막 매개변수 앞에 <strong><code>...</code></strong>을 붙임</li>
<li>나머지 매개변수의 특징<ul>
<li>배열로 수집: 모든 인수를 배열로 수집합니다.</li>
<li>마지막 매개변수로만 사용: 함수 정의에서 나머지 매개변수를 사용한다.</li>
<li>일반 매개변수와 함께 사용가능: 다른 매개변수와 함께 사용할 수 있습니다.</li>
</ul>
</li>
</ul>
</li>
<li><p>인자수 <br>
<strong>함수에 정의한 매개변수와 함수 호출에 사용되는 인자의 수가 달라도 에러가 발생하지는 않음</strong></p>
<ul>
<li><p>매개변수 &gt; 인자</p>
<ul>
<li>부족한 인자에 대한 매개변수에는 undefined 가 지정됨</li>
<li>다른 강형 언어에서는 매개변수를 호출안해주면 숫자 + 숫자 + undefined라서 NaN이 뜸</li>
</ul>
<pre><code class="language-jsx">function add(x, y, z) {
  console.log(z); // undefined
  return x + y;
}
console.log(add(3, 4)); // 7 =&gt; z값은 알아서 무시</code></pre>
</li>
<li><p>매개변수 &lt; 인자</p>
<ul>
<li>남는 인자에 대해서는 처리할 매개변수가 없기 때문에 무시됨</li>
</ul>
<pre><code class="language-jsx">function add(x, y) {
  return x + y;
}
console.log(add(3 , 4 , 5)); // 7 =&gt; 5는 알아서 무시</code></pre>
</li>
</ul>
</li>
<li><p>암묵적 매개변수</p>
<ul>
<li>모든 함수에서 명시적으로 선언하지 않고 암묵적으로 사용할 수 있는 매개변수</li>
<li><code>arguments</code><ul>
<li>함수 내에서 <strong>arguments</strong> 변수로 접근 가능</li>
<li>함수에 전달된 모든 인자들을 담고 있는 컬렉션 유사 배열 객체</li>
<li>배열과 비슷하게 length 속성과 index로 각 인자에 접근 가능</li>
<li>arguments 대신 ES6 의 나머지 매개변수(<code>…</code>) 사용을 권장</li>
</ul>
</li>
<li><code>this</code><ul>
<li>함수 내에서 this 키워드로 접근 가능</li>
<li>함수 컨텍스트 객체</li>
<li>함수를 호출한 객체 에 대한 참조</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li><p>ch01</p>
<ul>
<li>ex01-38 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-38.js">전역 변수와 지역 변수 - 호이스팅</a></li>
<li>ex01-42 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-42.js">기본 매개변수</a></li>
<li>ex01-43 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-43.js">나머지 매개변수</a></li>
</ul>
</li>
<li><p>ch02</p>
<ul>
<li>ex02-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-01.js">일급 객체</a></li>
<li>ex02-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-02.js">함수의 인자</a></li>
<li>ex02-03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-03.js">함수의 결과 값</a></li>
<li>ex02-04 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-04.js">동적으로 생성된 프로퍼티</a></li>
<li>ex02-05 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-05.js">함수 생성 - 선언문)</a></li>
<li>ex02-06 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-06.js">함수 생성 - 표현식-1</a></li>
<li>ex02-07 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-07.js">함수 생성 - 표현식-2-1</a></li>
<li>ex02-08 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-08.js">함수 생성 - 표현식-2-2 (펙토리얼 구하기)</a></li>
<li>ex02-09 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-09.js">함수 생성 - 표현식-3(Function 생성자 함수) =&gt; 잘 안씀</a></li>
<li>ex02-10-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-10.js">함수 생성 - 화살표 함수</a></li>
<li>ex02-11-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-11-01.js">함수 호이스팅 - 선언문 방식</a></li>
<li>ex02-11-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-11-02.js">함수 호이스팅 - 선언문 방식</a></li>
<li>ex02-12-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-12-01.js">변수 호이스팅</a></li>
<li>ex02-12-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-12-02.js">변수 호이스팅 - 표현식 방식</a></li>
<li>ex02-12-03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-12-03.js">변수 호이스팅 - 표현식 방식</a></li>
<li>ex02-13-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-13-01.js">매개변수 - arguments</a></li>
<li>ex02-13-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch02/ex02-13-02.js">매개변수 - 나머지(...)</a></li>
</ul>
</li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li><h3 id="함수에-대해서-생각보다-모르는게-좀-많았고-호이스팅-관련해서-이해도가-떨어지는것-같아-보인다-파일을-다시-한번-살펴보고-책도-읽으면서-정리해야겠다">함수에 대해서 생각보다 모르는게 좀 많았고 호이스팅 관련해서 이해도가 떨어지는것 같아 보인다. 파일을 다시 한번 살펴보고 책도 읽으면서 정리해야겠다.</h3>
</li>
</ul>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Glossary/First-class_Function">First-class_Function | mbn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions">Functions | mdn</a></li>
<li><a href="https://www.learn-js.org/en/Functions">Functions | Learn-js</a></li>
<li><a href="https://javascript.info/function-basics">Functions | javascript.info</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Glossary/Hoisting">Hoisting | mbn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Functions/Default_parameters">매개변수 | mbn</a></li>
<li><a href="https://www.notion.so/4-21-1dc73873401a8002ad2fda20aef536a0?pvs=4">노션 정리 링크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[📆 2025.04.15 ‐ DOM manipulation, event [멋쟁이사자처럼부트캠프 프론트엔드13기]]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.15-DOM-manipulation-event-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025.04.15-DOM-manipulation-event-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Tue, 15 Apr 2025 08:35:46 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<blockquote>
<p>오늘 공부하면서 인사이트, 개념 요약 등</p>
</blockquote>
<ul>
<li><h3 id="요소-노드의-내부-컨텐츠-제어">요소 노드의 내부 컨텐츠 제어</h3>
<pre><code class="language-html">&lt;!-- 기본 코드 --&gt;
&lt;ul id=&quot;purchases&quot; class=&quot;list&quot;&gt;
  &lt;li&gt; 두부 &lt;/li&gt;
  &lt;li&gt; 계란 &lt;/li&gt;
  &lt;li&gt; 라면 &lt;/li&gt;
&lt;/ul&gt;</code></pre>
<ul>
<li><p>elem.<code>innerHTML</code></p>
<ul>
<li>elem 의 내부 HTML 코드의 값을 조회하거나 수정</li>
<li><strong>elem 자신은 제외</strong></li>
</ul>
<pre><code class="language-jsx">const shoppingList = document querySelector(&#39;#purchases&#39;);
console.log(shoppingList.innerHTML)</code></pre>
<pre><code class="language-html">&lt;!-- 출력결과 --&gt;
\n&lt;li&gt;두부&lt;/li&gt;\n&lt;li&gt;계란&lt;/li&gt;\n&lt;li&gt;라면&lt;/li&gt;\n</code></pre>
</li>
<li><p>elem.<code>outerHTML</code></p>
<ul>
<li>elem 의 내부 HTML 코드의 값을 조회하거나 수정</li>
<li><strong>elem 자신을 포함</strong></li>
</ul>
<pre><code class="language-jsx">const shoppingList = document querySelector(&#39;#purchases&#39;);
console.log(shoppingList.innerHTML)</code></pre>
<pre><code class="language-html">&lt;!-- 출력결과 --&gt;
&lt;ul id=&quot;purchases&quot; class=&quot;list&quot;&gt;&gt;\n&lt;li&gt;두부&lt;/li&gt;\n&lt;li&gt;계란&lt;/li&gt;\n&lt;li&gt;라면&lt;/li&gt;\n&lt;/ul&gt;</code></pre>
</li>
<li><p>elem.<code>textContent</code></p>
<ul>
<li>elem 의 내부 텍스트 노드의 값을 조회하거나 수정</li>
<li><strong>소스코드의 값 그대로 조회</strong></li>
</ul>
<pre><code class="language-jsx">const secondLi = document.querySelector (&#39;#purchases &gt; li:nth-child(2)&#39;)
console.log(secondLi.textContent); //계란✔️</code></pre>
<pre><code class="language-html">&lt;!-- 코드 --&gt;
&lt;ul id=&quot;&quot; class=&quot;&quot;&gt;
  &lt;li&gt;두부&lt;span&gt; ✔️ &lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;계란 &lt;span&gt;✔️&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;라면 &lt;span&gt;✔️&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</code></pre>
</li>
<li><p>elem.<code>innerText</code></p>
<ul>
<li>elem 의 내부 텍스트 노드의 값을 조회하거나 수정</li>
<li><strong>브라우저에 의해서 실제 보이는 값으로 조회</strong></li>
<li><strong>화면에 보이지 않는 요소는 제외 (hidden)</strong></li>
</ul>
<pre><code class="language-jsx">const secondLi = document.querySelector(&quot;#purchases &gt; li:nth-child(2)&quot;);
console.log(secondLi.innerText); // 계란</code></pre>
<pre><code class="language-html">&lt;!-- 코드 --&gt;
&lt;ul id=&quot;&quot; class=&quot;&quot;&gt;
  &lt;li&gt;두부&lt;span&gt; ✔️ &lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;계란 &lt;span hidden&gt;✔️&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;라면 &lt;span&gt;✔️&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="노드-생성">노드 생성</h3>
<p>document 객체의 createXxx () 메소드를 이용</p>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>createElement(nodeName)</code></td>
<td>지정한 태그명으로 요소노드 생성</td>
</tr>
<tr>
<td><code>createTextNode(nodeValue)</code></td>
<td>지정한 내용으로 텍스트노드 생성</td>
</tr>
<tr>
<td><code>createAttribute(attributeName)</code></td>
<td>지정한 이름으로 속성노드 생성</td>
</tr>
</tbody></table>
<pre><code class="language-jsx">const newLiNode = document.createElement(&quot;li&quot;);     // li 요소 노드 생성
const newTextNode = document.createTextNode(&quot;우유&quot;); // &quot;우유&quot; 텍스트 노드 생성</code></pre>
<ul>
<li>🌲 노드 추가 전<pre><code>document
└── html
  └── body
      └── ul (id=&quot;purchases&quot;)
          ├── li → &#39;두부&#39;
          ├── li → &#39;계란&#39;
          └── li → &#39;라면&#39;</code></pre></li>
</ul>
<hr>
<ul>
<li>🌳 노드 추가 후<pre><code>document
└── html
  └── body
      └── ul (id=&quot;purchases&quot;)
          ├── li → &#39;두부&#39;
          ├── li → &#39;계란&#39;
          ├── li → &#39;라면&#39;
          └── li → &#39;우유&#39;</code></pre></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="노드-추가">노드 추가</h3>
<ul>
<li><p>요소노드.<code>appendChild</code>(childNode)</p>
</li>
<li><p>지정한 노드를(childNode) 요소노드의 <strong>마지막</strong> 자식노드로 추가</p>
</li>
<li><p>설명코드(<a href="https://github.com/FEBC-13/JS/blob/main/workspace-ins/ch05/ex05-03.html">ex05-03.html</a>)</p>
<pre><code class="language-jsx">const shopingList = document.getElementById(&quot;purchases&quot;);
const newLi = document.createElement(&quot;li&quot;); // li요소를 생성한다
const newTxt = document.createTextNode(&quot;우유&quot;); // 우유라는 텍스트를 생성한다

// ⚠️ 추가 전 상태 확인
console.log(&quot;추가하기 전: &quot;, newLi.childNodes, newLi.firstChild, newLi.lastChild); // (자식 노드들, 첫 번째 자식 노드, 마지막 자식 노드)
console.log(&quot;추가하기 전: &quot;, newLi.childNodes, &quot;(자식요소)&quot;); // li 요소 안에 있는 자식 노드 리스트
console.log(&quot;추가하기 전: &quot;, newLi.firstChild, &quot;(첫번째 자식)&quot;); // 첫 번째 자식 노드 (없음 → null)
console.log(&quot;추가하기 전: &quot;, newLi.lastChild, &quot;(마지막 자식)&quot;); // 마지막 자식 노드 (없음 → null)

// ⚙️ 텍스트 노드를 li에 추가
newLi.appendChild(newTxt);

// ✅ 추가 후 상태 확인
console.log(&quot;추가한 후: &quot;, newLi.childNodes, newLi.firstChild, newLi.lastChild); // (자식 노드들, 첫 번째 자식 노드, 마지막 자식 노드)
console.log(&quot;추가한 후: &quot;, newLi.childNodes, &quot;(자식요소)&quot;); // 텍스트 노드 &quot;우유&quot;가 들어간 자식 노드 리스트
console.log(&quot;추가한 후: &quot;, newLi.firstChild, &quot;(첫번째 자식)&quot;); // 첫 번째 자식 노드 → 텍스트 노드 &quot;우유&quot;
console.log(&quot;추가한 후: &quot;, newLi.lastChild, &quot;(마지막 자식)&quot;); // 마지막 자식 노드도 동일 → 텍스트 노드 &quot;우유&quot;

// 🧺 쇼핑 목록에 li를 추가
shopingList.appendChild(newLi);</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="노드-삽입">노드 삽입</h3>
<ul>
<li>요소노드 <code>insertBefore</code>(newNode, targetNode)</li>
<li>지정한 노드를(newNode) targetNode 앞에 삽입</li>
</ul>
<pre><code class="language-jsx">const purchases = document.getElementById(&quot;purchases&quot;)
purchases.insertBefore(newLiNode, purchases.firstChild);</code></pre>
<ul>
<li><p>pdf 를 바탕으로 트리구조</p>
<ul>
<li>노드 추가 전<pre><code>document
└── html
└── body
    └── ul (id=&quot;purchases&quot;)
        ├── li → &#39;두부&#39;
        ├── li → &#39;계란&#39;
        └── li → &#39;라면&#39;</code></pre></li>
</ul>
<hr>
<ul>
<li>노드 추가 후 (맨 앞에 &#39;우유&#39; 추가됨)<pre><code>document
└── html
└── body
    └── ul (id=&quot;purchases&quot;)
        ├── li → &#39;우유&#39;
        ├── li → &#39;두부&#39;
        ├── li → &#39;계란&#39;
        └── li → &#39;라면&#39;</code></pre></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="노드-삭제">노드 삭제</h3>
<ul>
<li>요소노드.removeChild(childNode)</li>
<li>지정한 노드를(childNode) 삭제한다.</li>
</ul>
<pre><code class="language-jsx">btn3.addEventListener(&quot;click&quot;, function () {
  const targetList = document.querySelectorAll(&quot;.list&quot;);
  for (let i = 0; i &lt; targetList.length; i++) {
    //i=0, &lt;li&gt;두부&lt;/li&gt;, i=1 &lt;li&gt;어벤저스&lt;/li&gt;
    const firstLi = targetList[i].firstElementChild;
    //해당 노드를 삭제한다
    // 첫번째 항목이 존제하면 삭제
    if (addFirstLi) addFirstLi.remove(); // if 문 사용

    firstLi?.remove(); //옵셔널 체이닝

    // 나를 기준으로 내 부모(엄마)
    firstLi?.parentNode.removeChild(firstLi); //비권장, 에전에는 이것밖에 지원을 안했음 지금은 그냥 위에 remove()쓰면된다.
  }
});</code></pre>
</li>
</ul>
<hr>
<ul>
<li><h3 id="이벤트-처리ex05-04html">이벤트 처리(<a href="https://github.com/FEBC-13/JS/blob/main/workspace-ins/ch05/ex05-04.html">ex05-04.html</a>)</h3>
<pre><code class="language-html">&lt;h1&gt;쇼핑 목록&lt;/h1&gt;
&lt;div&gt;
&lt;!-- 1️⃣ --&gt;
  &lt;button onclick=&quot;console.log(&#39;여기여기&#39;)&quot;&gt;눌러보쇼&lt;/button&gt;
&lt;/div&gt;
&lt;script&gt;
  const btn = document.querySelector(&quot;button&quot;);
  // 이벤트 등록
  // 1. elem.on&lt;이벤트&gt; 속성에 이밴트 핸들러 추가
  // DOM Level 0 방식(비표준 방식)
  // 2️⃣
  btn.onclick = () =&gt; {
    console.log(&quot;눌렀어&quot;);
  };
  // 3️⃣
  btn.onclick = () =&gt; {
    console.log(&quot;눌렀어요?&quot;);
  };

  // 3. addEventListener() 메서드로 이벤트 등록
  // add라서 이벤트가 추가됨
  // DOM Level 2 방식(표준 방식)
  // 4️⃣
  btn.addEventListener(&quot;click&quot;, () =&gt; {
    console.log(&quot;눌렀습니다.&quot;);
  });
  // 5️⃣
  btn.addEventListener(&quot;click&quot;, () =&gt; {
    console.log(&quot;눌렀슴다.&quot;);
  });
&lt;/script&gt;</code></pre>
<ul>
<li>진행 순서 <ul>
<li>1️⃣: 버튼 클릭 시 <code>&quot;여기여기&quot;</code> 출력됨 (HTML의 <code>onclick</code>)</li>
<li>2️⃣:  JS에서 <code>onclick</code>으로 <code>&quot;눌렀어&quot;</code> 등록 → 기존 <code>&quot;여기여기&quot;</code> 덮어씀</li>
<li>3️⃣:  다시 <code>onclick</code>으로 <code>&quot;눌렀어요?&quot;</code> 등록 → <code>&quot;눌렀어&quot;</code>도 덮어씀</li>
<li>4️⃣: <code>addEventListener</code>로 <code>&quot;눌렀습니다.&quot;</code> 추가됨</li>
<li>5️⃣: <code>addEventListener</code>로 <code>&quot;눌렀슴다.&quot;</code> 또 추가됨</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li>ex05-03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-03.html">쇼핑목록 만들기</a></li>
<li>ex05-04 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-04.html">이벤트 처리</a></li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>한번 딴 짓 좀 했다고 따라가기 힘드네.. 내일 진짜 열씸히 공부한다</li>
<li>코드를 많이 써보고 쓴 것을 바탕으로 질문을 하자..너무 질문 안하더라</li>
</ul>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/API/Document/createElement"> createElement | mdn </a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/API/Document/createTextNode"> createTextNode | mdn </a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/API/Node/appendChild"> appendChild | mdn </a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild"> removeChild | mdn </a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore"> insertBefore | mdn </a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Learn_web_development/Core/Scripting/Events"> Events | mdn </a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Optional_chaining"> Optional chaining | mdn </a></li>
<li><a href="https://www.notion.so/a0f2b124fce8401d9e18d5e13503f736?pvs=4">노션 정리 링크</a></li>
</ul>
<hr>
<div align="center">

<h2 id="📅-페이지-이동">📅 페이지 이동</h2>
<p><a href="https://github.com/koo-rogie/js-start/wiki/%F0%9F%93%86-2025.04.14--%E2%80%90-client%E2%80%90side-JS,-DOM,-node-types">◀ 이전날</a> | <a href="...">다음날 ▶</a></p>
</div>]]></description>
        </item>
        <item>
            <title><![CDATA[📆 2025.04.14 - client‐side JS, DOM, node types [멋쟁이사자처럼부트캠프 프론트엔드13기]]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.14-clientside-JS-DOM-node-types-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025.04.14-clientside-JS-DOM-node-types-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Tue, 15 Apr 2025 08:35:11 GMT</pubDate>
            <description><![CDATA[<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<blockquote>
<p>오늘 공부하면서 인사이트, 개념 요약 등</p>
</blockquote>
<ul>
<li><h3 id="클라이언트-사이드-자바스크립트란">클라이언트 사이드 자바스크립트란?</h3>
<ul>
<li><p>웹 브라우저에서 실행되는 자바스크립트 환경
ECMAScript: 자바스크립트 언어에 대한 표준
<a href="https://ecma-international.org/publications-and-standards/standards/ecma-262">patrick Charollais | ECMA-262 - Ecma lnternational</a></p>
</li>
<li><p>DOM(Document Object Model): 웹페이지 제어를 위한 표준</p>
<ul>
<li><a href="https://dom.spec.whatwg.org/">https://dom.spec.whatwg.org</a></li>
<li>window.document 등</li>
<li>Event</li>
</ul>
</li>
<li><p>BOM(Browser Object Model): 웹페이지 외부의 브라우저 기능 제어를 위한 표준</p>
<ul>
<li>HTML 표준 : <a href="https://html.spec.whatwg.org/">https://html.spec.whatwg.org</a></li>
<li>window. navigator: 브라우저와 운영체제에 대한 정보 제공</li>
<li>window.location: 현재 페이지의 URL 에 대한 제어 읽기 , 수정</li>
<li>window.history: 브라우저의 과거 페이지 이동 정보에 대한 제어 읽기 , 수정</li>
<li>alert, setTimeout 등</li>
</ul>
</li>
<li><p>Web APIs: 브라우저가 제공하는 웹 기능을 위한 표준</p>
<ul>
<li><p><a href="https://spec.whatwg.org/">https://spec.whatwg.org</a></p>
</li>
<li><p>XMLHttpRequest: 서버와 통신에 사용되는 객체 (Ajax)</p>
</li>
<li><p>Web Storage, Notifications API, WebSocket 등 <br>
<img src="https://github.com/user-attachments/assets/fc676598-6274-49fd-a78c-67a49c402c89" alt="image"></p>
</li>
<li><ol>
<li>DOM / 2. BOM / 3. WEB APls</li>
</ol>
</li>
<li><p><strong>서버 사이드 vs 클라이언트 사이드</strong></p>
<ul>
<li><p><strong>🌐 클라이언트 사이드 (Client-side)</strong><br></p>
<ul>
<li><p><strong>✅ 정의</strong><br>
클라이언트는 <strong>사용자가 직접 보는 브라우저 쪽</strong>에서 동작하는 부분이에요.
즉, <strong>HTML, CSS, JavaScript</strong>가 브라우저에서 실행되어, 화면에 보이고 사용자의 행동에 반응하는 거예요.</p>
</li>
<li><p><strong>✅ 특징</strong></p>
<ul>
<li><strong>브라우저에서 실행</strong>됨</li>
<li><strong>즉각적인 반응</strong> 제공 (예: 버튼 클릭 → 팝업 열기)</li>
<li>주로 <strong>UI 처리</strong>, <strong>입력 검증</strong>, <strong>애니메이션</strong> 등을 담당</li>
</ul>
</li>
<li><p><strong>✅ 예시</strong></p>
<blockquote>
<p>쇼핑몰 웹사이트에서 제품 목록을 보고, &quot;장바구니 담기&quot; 버튼을 누르면 숫자가 올라가는 기능</p>
<p>→ 이건 브라우저에서 JavaScript가 실행된 결과 = <strong>클라이언트 사이드</strong></p>
</blockquote>
</li>
</ul>
<hr>
</li>
<li><p><strong>🖥️ 서버 사이드 (Server-side)</strong></p>
<ul>
<li><strong>✅ 정의</strong></li>
</ul>
<p>서버사이드는 <strong>브라우저와는 떨어진 서버에서 실행되는 코드</strong>예요.</p>
<p>Node.js 같은 백엔드 기술이 여기에 해당돼요. 브라우저가 서버에 요청(request)을 보내면, 서버는 데이터를 가공해서 응답(response)을 돌려줘요.</p>
<ul>
<li><p><strong>✅ 특징</strong></p>
<ul>
<li>서버에서 실행</li>
<li>데이터베이스 조회, 로그인 처리, 파일 저장 등 <strong>보안이나 데이터 처리</strong>에 강함</li>
<li>사용자는 서버 코드에 직접 접근할 수 없음</li>
</ul>
</li>
<li><p>✅ 예시</p>
<blockquote>
<p>로그인 버튼을 눌렀을 때, 입력한 이메일과 비밀번호가 서버에 전달되고, 서버가 데이터베이스를 확인한 후 로그인 성공 여부를 돌려주는 것</p>
<p>→ 이건 서버에서 Node.js가 동작한 결과 = <strong>서버 사이드</strong></p>
</blockquote>
</li>
</ul>
<hr>
<ul>
<li>🎯 비유로 이해해보기 <table>
<thead>
<tr>
<th>역할</th>
<th>설명</th>
<th>비유</th>
</tr>
</thead>
<tbody><tr>
<td>클라이언트사이드</td>
<td>사용자에게 보이는 화면을 꾸미고 반응</td>
<td>레스토랑의 메뉴판과 종업원</td>
</tr>
<tr>
<td>서버사이드</td>
<td>사용자의 주문을 처리하고 요리를 제공</td>
<td>주방에서 요리를 만드는 셰프와 주방 시스템</td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="domdocument-object-model">DOM(Document Object Model)</h3>
<ul>
<li>문서 객체 모델</li>
<li>HTML, XML 등의 문서를 제어 하기 위한 방법을 정의</li>
<li>JavaScript로 HTML을 조작할 수 있게 해주는 인터페이스</li>
<li>텍스트 기반의 HTML, XML <strong>문서</strong>를 일정한 규칙에 의해 <strong>객체</strong>로 만들고 이를 이용하여 문서를 제어 특정 요소를 추출 , 삽입 , 삭제 , 이동 등</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="노드의-종류">노드의 종류</h3>
<p>노드 (Node)
DOM 트리구조는 모든 구성원이 각각의 객체로 인식되며 이러한 객체 하나 하나를 노드라고 함</p>
<ul>
<li><p>노드의 종류 주로 사용되는 노드</p>
<ul>
<li>문서노드 (document Node)</li>
<li>요소 노드 (element Node)</li>
<li>속성 노드 (attribute Node)</li>
<li>텍스트 노드 (text Node)</li>
</ul>
<table>
<thead>
<tr>
<th><strong>종류</strong></th>
<th><strong>설명</strong></th>
<th><strong><code>nodeName</code></strong></th>
<th><strong>nodeType</strong></th>
<th><strong>nodeValue</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>문서 노드</strong></td>
<td>문서</td>
<td><strong><code>#document</code></strong></td>
<td>9</td>
<td>null</td>
</tr>
<tr>
<td><strong>요소 노드</strong></td>
<td>태그</td>
<td><strong><code>태그의 이름</code></strong></td>
<td>1</td>
<td>null</td>
</tr>
<tr>
<td><strong>속성 노드</strong></td>
<td>요소의 속성</td>
<td><strong><code>속성의 이름</code></strong></td>
<td>2</td>
<td>속성의 값</td>
</tr>
<tr>
<td><strong>텍스트 노드</strong></td>
<td>요소의 내용</td>
<td><strong><code>#text</code></strong></td>
<td>3</td>
<td>문자열 값</td>
</tr>
</tbody></table>
</li>
<li><p>노드 찾기</p>
<ul>
<li><p>태그의 id 를 이용하여 노드 찾기
document.getElementById (id): id 속성값에 해당하는 노드객체를 반환</p>
<pre><code class="language-jsx">const purchases = document.getElementById(&quot;purchases&quot;);</code></pre>
</li>
<li><p><strong>태그명</strong>을 이용하여 노드 찾기
요소노드 getElementsByTagName(tagName)
지정한 요소노드의 하위 모든 요소를 대상으로 태그명 (tagName) 에 해당하는 요소노드를 배열로 반환 tagName 에 “*”을 지정하면 모든 요소를 배열로 반환</p>
<pre><code class="language-jsx">const liList = purchases.getElementsByTagName(&quot;li&quot;);</code></pre>
</li>
<li><p>트리구조를 이용하여 노드 찾기</p>
<ul>
<li><p>부모 자식 노드 찾기</p>
<table>
<thead>
<tr>
<th>요소노드의 속성</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>childNodes</td>
<td><strong>자식 노드가 배열 형태</strong>로 저장 ⇒ 유사 배열 객체</td>
</tr>
<tr>
<td>firstChild</td>
<td>첫번째 자식 노드(요소, 텍스트, 주석)</td>
</tr>
<tr>
<td>firstElementChild</td>
<td>첫번째 자식 요소 노드</td>
</tr>
<tr>
<td>lastChild</td>
<td>마지막 자식 노드(요소, 텍스트, 주석)</td>
</tr>
<tr>
<td>lastElementChild</td>
<td>마지막 자식 요소 노드</td>
</tr>
<tr>
<td>parentNode</td>
<td>부모 노드</td>
</tr>
<tr>
<td>```jsx</td>
<td></td>
</tr>
<tr>
<td>const purchases = document.getElementById(&#39;purchases&#39;); // id를 추출하는 코드</td>
<td></td>
</tr>
<tr>
<td>const firstItem = purchases.firstElementChild; // 첫번째 자식만 선택함</td>
<td></td>
</tr>
<tr>
<td>const lastItem = purchases.lastElementChild; // 마지막 자식만 선택</td>
<td></td>
</tr>
<tr>
<td>const liList = purchases.childNodes; // 유사배열 객체 추출</td>
<td></td>
</tr>
<tr>
<td>```</td>
<td></td>
</tr>
</tbody></table>
<ul>
<li><p>형제 노드 찾기</p>
<table>
<thead>
<tr>
<th>속성</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>previousSibling</td>
<td>바로 앞의 형제 노드(요소, 텍스트, 주석)</td>
</tr>
<tr>
<td>previousElementSibling</td>
<td>바로 앞의 형제 <strong>요소 노드</strong></td>
</tr>
<tr>
<td>nextSibling</td>
<td>바로 뒤의 형제 노드(요소, 텍스트, 주석)</td>
</tr>
<tr>
<td>nextElementSibling</td>
<td>바로 뒤의 형제 <strong>요소 노드</strong></td>
</tr>
</tbody></table>
<pre><code class="language-jsx">const purchases = document.getElementById(&quot;purchases&quot;);
const secondItem = purchases.childNodes[3];
const firstItem = secondItem.previousElementSibling;
const lastItem = secondItem.nextElementSibling;
</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><p>class 속성으로 노드 찾기
document.getElementsByClassName(className): class 속성값이 className 인 요소 노드의 목록을 반환</p>
<pre><code class="language-jsx">const purchases = document.getElementsByClassName(&quot;list&quot;)[0];</code></pre>
</li>
<li><p>CSS 셀렉터 이용</p>
<ul>
<li>Selector: CSS 에서 사용하는 노드 선택 구문<ul>
<li><a href="https://www.w3.org/TR/selectors-3/">https://www.w3.org/TR/selectors-3/</a></li>
</ul>
</li>
<li>document.querySelector (selector)<ul>
<li>지정한 selector 구문에 매칭되는 노드 목록 중 첫번째 노드를 반환</li>
</ul>
</li>
<li>document.querySelectorAll (selector)<ul>
<li>지정한 selector 구문에 매칭되는 노드 목록을 반환</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">var purchases = document.querySelector(&quot;.list&quot;);
var purchases = document.querySelector(&quot;#purchases&quot;);
var purchases = document.querySelectorAll(&quot;ul&quot;)[0];</code></pre>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li>ex05-01.html <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-01.html">쇼핑목록</a></li>
<li>ex05-01-02.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-01-02.js">첫번째 구매 항목 출력(두부)</a></li>
<li>ex05-01-03.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-01-03.js">첫번째와 마지막 구매 항목을 출력</a></li>
<li>ex05-01-04.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-01-04.js">querySelector 이용</a></li>
<li>ex05-02.html <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-02.html">숫자 올리기</a></li>
<li>ex05-02-01.js <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch05/ex05-02-01.js">숫자 올리기 JS</a></li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>오늘은 그래도 아는 내용이라서 수업을 대충대충 들었던 기분이었다 내일은 좀 더 집중해서 들어야지</li>
</ul>
<hr>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://www.w3.org/TR/selectors-3/"> css 선택자 | w3 </a></li>
<li><a href="https://www.notion.so/a0f2b124fce8401d9e18d5e13503f736?pvs=4">노션 정리 링크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[📆 2025.04.11] reference types, scope, let const, array methods - [멋쟁이사자처럼부트캠프 프론트엔드13기]]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.11-reference-types-scope-let-const-array-methods-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025.04.11-reference-types-scope-let-const-array-methods-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Fri, 11 Apr 2025 08:47:09 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-오늘-공부한-내용">📚 오늘 공부한 내용</h2>
<ul>
<li>참조 타입의 특징</li>
<li>변수 스코프</li>
<li>ES6 - 변수 선언문</li>
<li>오늘 배운 배열 메소드</li>
</ul>
<hr>
<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<blockquote>
<p>오늘 공부하면서 인사이트, 개념 요약 등</p>
</blockquote>
<ul>
<li><h3 id="참조-타입의-특징">참조 타입의 특징</h3>
<ul>
<li><p>기본 데이터 타입은 실제 데이터를 저장하고 다룸</p>
<ul>
<li>함수 호출 방식: 값에 의한 호출 (Call by Value) ⇒ 원시타입</li>
</ul>
</li>
<li><p>참조형 데이터 타입은 실제 데이터가 있는 위치의 주소를 저장하고 다룸</p>
<ul>
<li><p>함수 호출 방식: 참조에 의한 호출 (Call by Reference) ⇒ 참조타입</p>
</li>
<li><p>예제코드<br>
<a href="https://velog.io/@code-bebop/JS-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0">js 메모리 구조</a></p>
<pre><code class="language-jsx">function add10(data1, data2) {
  data1 += 10;
  data2[0] += 10;
  console.log(&quot;함수 내부에서 호출&quot;, data1, data2[0]);
}

let d1 = 80; // =&gt; 원시타입, Number
let d2 = [80]; // =&gt; 참조타입, array(object)

console.log(&quot;함수 호출 이전&quot;, d1, d2[0]);

add10(d1, d2);

console.log(&quot;함수 호출 이후&quot;, d1, d2[0]);</code></pre>
</li>
<li><p>call stack</p>
<ul>
<li><p>모든 변수는 여기에 적용됨</p>
</li>
<li><p>밑에서 부터 데이터가 하나씩 쌓이는 곳</p>
</li>
<li><p>함수가 끝나면 stack frame이 역순으로 사라짐 (제일 마지막에 쌓였던 것부터 사라짐)</p>
</li>
<li><p>ex01-37-02 - call stack</p>
<pre><code class="language-jsx">console.log(&quot;1. 프로그램 시작.&quot;);

function a(n1) {
  console.log(&quot;2. a 시작.&quot;, n1);
  const n2 = b(n1);
  console.log(&quot;7. a 종료.&quot;, n2);
}

function b(n3) {
  console.log(&quot;3. b 시작.&quot;, n3);
  const n4 = c(n3); // 3.5번
  console.log(&quot;6. b 종료.&quot;, n4);
  return n4;
}

function c(n5) {
  console.log(&quot;4. c 시작.&quot;, n5);
  const n6 = n5 + 10;
  console.log(&quot;5. c 종료.&quot;, n6);
  return n6;
}

a(10);

console.log(&quot;8. 프로그램 종료.&quot;);</code></pre>
</li>
</ul>
<p><strong>🧠 Call Stack 흐름 요약 (색깔 따라가기)</strong> <br></p>
<ol>
<li><strong>빨간색 (함수 진입)</strong><ul>
<li><code>프로그램 시작</code> (console.log 1)</li>
<li><code>a(10)</code> 호출 → <code>a 시작</code> (console.log 2)</li>
<li><code>b(n1)</code> 호출 → <code>b 시작</code> (console.log 3)</li>
<li><code>c(n3)</code> 호출 → <code>c 시작</code> (console.log 4)</li>
</ul>
</li>
<li><strong>파란색 (함수 내부 로직)</strong><ul>
<li><code>c()</code> 내부에서 <code>n6 = n5 + 10</code></li>
<li><code>console.log(&quot;5. c 종료.&quot;)</code> → 값 반환 (<code>n6</code>)</li>
</ul>
</li>
<li><strong>초록색 (함수 반환과 종료)</strong><ul>
<li><code>b()</code>로 돌아와서 <code>console.log(&quot;6. b 종료.&quot;)</code> → 값 반환 (<code>n4</code>)</li>
<li><code>a()</code>로 돌아와서 <code>console.log(&quot;7. a 종료.&quot;)</code> → 종료</li>
</ul>
</li>
<li><strong>보라색 (최종 종료)</strong><ul>
<li><code>console.log(&quot;8. 프로그램 종료.&quot;)</code></li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code>    **🎯 요약 비유**
    - 함수를 **빨간 화살표**로 호출하면 스택에 차곡차곡 쌓이고 (push)
    - 반환되면 **초록 화살표**로 스택에서 제거됨 (pop)
    - 결국 마지막에 스택이 비워지면 프로그램도 끝남!

- heap
  - 모든 객체가 적용됨
  - 순서가 없는 무작위로 데이터를 담음</code></pre><ul>
<li><p>🧠 메모리 구조 이해</p>
<ol>
<li><strong>d1은 원시타입(Number)</strong></li>
</ol>
<ul>
<li>값이 그대로 <code>data1</code>에 <strong>복사(pass-by-value)</strong>돼.</li>
<li>즉, <code>data1 = 80</code>이 되고, <code>data1 += 10</code>을 해도 <code>d1</code>에는 영향이 없어.</li>
<li><code>data1</code>은 함수 안에서만 90이 되고, 바깥의 <code>d1</code>은 여전히 80이야.</li>
</ul>
<ol start="2">
<li><strong><code>d2</code>는 참조타입(Array/Object)</strong></li>
</ol>
<ul>
<li><p><code>d2</code>의 참조값(주소)이 <code>data2</code>로 <strong>공유(pass-by-reference)</strong>돼.</p>
</li>
<li><p>즉, <code>data2[0] += 10</code>은 실제 배열의 값인 <code>d2[0]</code>을 바꿔.</p>
</li>
<li><p>그래서 바깥의 <code>d2[0]</code>도 같이 90으로 바뀜.</p>
</li>
<li><p>비유
<strong>🍱 도시락 비유</strong> <br>
<strong>🧍‍♂️ <code>d1</code>은 &quot;직접 가져간 도시락&quot;</strong> <br></p>
<ul>
<li>너가 친구한테 &quot;내 도시락이 이거야!&quot; 하고 <strong>도시락 사진</strong>만 줬어.</li>
<li>친구는 그걸 보고 도시락 그림에 햄버거를 하나 더 그려.</li>
<li>근데 네 진짜 도시락은 그대로야. 친구는 <strong>복사된 그림</strong>만 바꾼 거니까!
🟰 이게 바로 <code>원시타입</code>, 즉 <strong>pass-by-value (값 복사)</strong>!</li>
</ul>
<hr>
<p><strong>🧍‍♂️ <code>d2</code>는 &quot;도시락 통째로 빌려준 거&quot;</strong><br></p>
<ul>
<li>이번엔 도시락을 <strong>직접 친구한테 건넸어</strong>.</li>
<li>친구가 뚜껑 열고 안에 반찬 하나 더 넣어줬어.</li>
<li>그래서 네가 다시 도시락 받아봤을 땐, 진짜로 반찬이 바뀌어 있었던 거야.
이게 <code>참조타입</code>, 즉 <strong>pass-by-reference (참조 전달)</strong></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="변수-스코프">변수 스코프</h3>
<ul>
<li><p>전역 변수 <br>
<a href="https://developer.mozilla.org/ko/docs/Glossary/Global_object">공식 문서</a></p>
<pre><code class="language-jsx">var age = 20; // 전역 변수
(window.)year = 10; // 전역 변수
function getAge(year){ // 지역 변수
  var age = 30; // 지역 변수
  (window.)myAge = age + year; // 전역 변수
  (window.)alert(myAge);
  (window.)console.log(myAge);
}</code></pre>
<ul>
<li>함수 외부에서 선언한 변수</li>
<li>스크립트 내 어디에서나 접근 가능</li>
<li>페이지가 로딩될 때 한번 생성하여 값이 유지됨</li>
<li>모든 전역변수는 window 객체의 속성으로 지정됨</li>
<li>변수를 재할당할 경우 앞에 window가 생략되어서 사용함</li>
<li>변수선언을 안하고 써도 전역변수로 인식해서 윈도우 객체 아래에 넣어버리는것은 자바스크립트만의 특별한 동작 방식이다!</li>
<li><code>(window.)myAge = age + year;</code><br>
되도록이면 사용하지 않는 것을 추천한다. 나 혼자 보는 코드가 아니기 때문에 다른 사람들이 봤을 때 혼란스러울 수 있음 만약, 정말정말 쓰고 싶다면 앞에 <code>window.</code>을 붙여서 윈도우 객체의 아래에 있다고 명시해주자</li>
</ul>
</li>
<li><p>지역 변수</p>
<ul>
<li>함수 내부에서 선언한 변수</li>
<li>해당 함수 안에서만 접근 가능</li>
<li>함수가 호출될 때마다 새로 생성하여 값이 초기화</li>
<li><strong>함수 내부에서 선언하지 않고 바로 사용하는 변수는 전역 변수로 동작</strong></li>
</ul>
</li>
<li><p>변수 우선순위</p>
<ul>
<li>변수는 가까운 곳부터 찾는다.</li>
<li>즉 지역변수 영역에서 먼저 찾고 없을 경우 전역변수에서 찾는다.</li>
</ul>
</li>
<li><p>❗지역변수의 유효 범위
  <strong>대부분의 언어에서는</strong> 선언한 변수가 <strong>블록 단위의 유효범위를</strong> 갖지만 자바스크립트에서는 <strong>var로 선언한 변수</strong>가 <strong>함수 단위의 유효범위</strong>를 갖는다.</p>
</li>
</ul>
</li>
<li><h3 id="es6---변수-선언문">ES6 - 변수 선언문</h3>
<ul>
<li>var선언문<ul>
<li>함수 단위의 유효범위를 갖는 변수 선언문</li>
<li>대부분의 언어에서는 선언한 변수가 블록 단위의 유효범위를 갖지만 자바스크립트에서는 var로 선언한 변수가 함수 단위의 유효 범위를 갖는다.</li>
</ul>
</li>
<li>let 선언문<ul>
<li>블록 단위의 유효범위를 갖는 변수 선언문</li>
</ul>
</li>
<li>const선언문<ul>
<li>블록 단위의 유효범위를 갖는 상수 선언문</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="오늘-배운-배열-메소드">오늘 배운 배열 메소드</h3>
<ul>
<li><p>fill()
배열의 모든 요소를 지정한 값으로 채운다.</p>
<pre><code class="language-jsx">// 문법: array.fill(value, start, end)
// value: 배열을 채울 값
// start(선택): 시작 인덱스 (기본값 0)
// end(선택): 끝 인덱스 (기본값 array.length)

const arr = new Array(5);
arr.fill(7);
console.log(arr); // [7, 7, 7, 7, 7]

// 특정 구간만 채우기
const nums = [1, 2, 3, 4, 5];
nums.fill(0, 2, 4);
console.log(nums); // [1, 2, 0, 0, 5]</code></pre>
</li>
<li><p>join()
배열의 모든 요소를 연결해 하나의 문자열로 만든다.</p>
<pre><code class="language-jsx">// 문법: array.join(separator)
// separator(선택): 요소 사이에 들어갈 구분자 (기본값은 쉼표)

const fruits = [&#39;사과&#39;, &#39;바나나&#39;, &#39;딸기&#39;];
console.log(fruits.join()); // &#39;사과,바나나,딸기&#39;
console.log(fruits.join(&#39; &#39;)); // &#39;사과 바나나 딸기&#39;
console.log(fruits.join(&#39; - &#39;)); // &#39;사과 - 바나나 - 딸기&#39;</code></pre>
</li>
<li><p>split()
문자열을 지정된 구분자를 기준으로 나누어 배열로 변환한다.</p>
<pre><code class="language-jsx">// 문법: string.split(separator, limit)
// separator: 분할 기준 (문자열 또는 정규식)
// limit(선택): 반환할 분할 항목 수의 제한

const sentence = &#39;안녕하세요, 자바스크립트 공부 중입니다&#39;;
const words = sentence.split(&#39; &#39;);
console.log(words); // [&#39;안녕하세요,&#39;, &#39;자바스크립트&#39;, &#39;공부&#39;, &#39;중입니다&#39;]

const csv = &#39;김철수,30,개발자&#39;;
const person = csv.split(&#39;,&#39;);
console.log(person); // [&#39;김철수&#39;, &#39;30&#39;, &#39;개발자&#39;]

// 모든 문자를 개별 요소로
const chars = &#39;안녕하세요&#39;.split(&#39;&#39;);
console.log(chars); // [&#39;안&#39;, &#39;녕&#39;, &#39;하&#39;, &#39;세&#39;, &#39;요&#39;]</code></pre>
</li>
<li><p>includes()
배열에 특정 요소가 포함되어 있는지 확인하고 true또는 false를 반환한다.</p>
<pre><code class="language-jsx">// 문법: array.includes(searchElement, fromIndex)
// searchElement: 찾을 요소
// fromIndex(선택): 검색을 시작할 위치 (기본값 0)

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(3)); // true
console.log(numbers.includes(6)); // false

// 특정 위치부터 검색
console.log(numbers.includes(1, 2)); // false (인덱스 2부터 검색)

// 문자열 배열에서도 사용 가능
const fruits = [&#39;사과&#39;, &#39;바나나&#39;, &#39;딸기&#39;];
console.log(fruits.includes(&#39;바나나&#39;)); // true
console.log(fruits.includes(&#39;수박&#39;)); // false</code></pre>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
</li>
</ul>
</li>
<li><p>29-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-29-02.js">2차원 배열</a></p>
</li>
<li><p>37-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-37-01.js">Call by Value와 Call by Reference 차이</a></p>
</li>
<li><p>37-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-37-02.js">Call by Value와 Call by Reference 차이</a></p>
</li>
<li><p>38 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-38.js">전역 변수와 지역 변수</a></p>
</li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>오늘은 개인적으로 몸이 안 좋은 날이어서 수업을 잘 못 들은 하루였다. 제일 중요한 call stack랑 heap를 대충 들은거 같아서 내일부터 딥다이브를 보면서 머리속에 넣어야 할것 같다</li>
</ul>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://velog.io/@code-bebop/JS-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0"> JS 메모리 구조 | velog 불꽃남자 </a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Glossary/Global_object"> 전역 객체 | mdn </a></li>
<li><a href="https://www.notion.so/a0f2b124fce8401d9e18d5e13503f736?pvs=4">노션 정리 링크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[📆 2025.04.09] Array, array‐like object, two‐dimensional array, for...in, vs for...of - [멋쟁이사자처럼부트캠프 프론트엔드13기]]]></title>
            <link>https://velog.io/@koo-rogie/2025.04.09-Array-arraylike-object-twodimensional-array-for...in-vs-for...of-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025.04.09-Array-arraylike-object-twodimensional-array-for...in-vs-for...of-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Fri, 11 Apr 2025 02:34:32 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-오늘-공부한-내용">📚 오늘 공부한 내용</h2>
<ul>
<li>참조 타입</li>
<li>유사 배열 객체(Like-Array Object)</li>
<li>2차원 배열, 다차원 배열</li>
<li><code>for in</code>, <code>for of</code> </li>
</ul>
<hr>
<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<ul>
<li><h3 id="참조-타입-array-배열">참조 타입 (Array, 배열)</h3>
<ul>
<li><p>배열</p>
<ul>
<li>하나의 변수에 <strong>여러개의 값을 지정</strong>하는 데이터 구조</li>
<li>순서정보 (<code>index</code>) 를 이용하여 각 요소를 참조 <code>(0 부터 시작)</code></li>
</ul>
</li>
<li><p>생성</p>
<ul>
<li>크기를 미리 지정하지 않음</li>
<li>Array 생성자 함수 로 생성<ul>
<li><code>var score = new Array();</code></li>
</ul>
</li>
<li>JSON 표기법 이용<ul>
<li><code>var score = [];</code></li>
</ul>
</li>
</ul>
</li>
<li><p>예제  </p>
<ul>
<li><p>초기화</p>
<ul>
<li>Array 클래스로 생성 및 초기화<ul>
<li><code>var score = new Array(90, 70, 100);</code></li>
</ul>
</li>
<li>JSON 표기법으로 생성 및 초기화<ul>
<li><code>var score = [ 90 , 70 , 100];</code></li>
</ul>
</li>
</ul>
</li>
<li><p>요소추가</p>
<ul>
<li>index 나 배열 메소드 이용</li>
<li><code>score[3] = 86;</code></li>
</ul>
</li>
<li><p>요소 읽기</p>
<ul>
<li>index 나 배열 메소드 이용</li>
<li><code>score[3]</code></li>
</ul>
</li>
<li><p>배열 요소의 수</p>
<ul>
<li>length 속성</li>
</ul>
</li>
<li><p>push vs length의 차이
하드 코딩으로 5 6 7 등등 이렇게 하면 배열이 바뀌게 된다면 다시 수정을 해야 한다 그래서 알아서 찾아주는 length를 사용함, 다만 push는 기본적으로 배열의 마지막에 데이터를 추가 하는것이기 때문에 push를 사용하는게 좋다
  <strong>✅ <code>arr[arr.length] = 값</code> vs <code>arr.push(값)</code> 비교표</strong></p>
<table>
<thead>
<tr>
<th>항목</th>
<th><code>arr[arr.length] = 값</code></th>
<th><code>arr.push(값)</code></th>
</tr>
</thead>
<tbody><tr>
<td>기본 개념</td>
<td>length를 사용해 마지막에 수동으로 값 추가</td>
<td>마지막에 값을 자동으로 추가</td>
</tr>
<tr>
<td>직관성</td>
<td>❌ 덜 직관적, 가독성 낮음</td>
<td>✅ 직관적이고 가독성 좋음</td>
</tr>
<tr>
<td>다중 추가</td>
<td>❌ 불가능 (하나씩만 가능)</td>
<td>✅ 가능 (<code>arr.push(1, 2, 3)</code>)</td>
</tr>
<tr>
<td>체이닝 가능 여부</td>
<td>❌ 없음</td>
<td>✅ 가능 (<code>arr.push(1).push(2)</code>)</td>
</tr>
<tr>
<td>사용 추천도</td>
<td>❌ 가급적 지양</td>
<td>✅ 배열 마지막에 추가할 땐 적극 사용</td>
</tr>
<tr>
<td>코드 유지보수</td>
<td>❌ 인덱스를 하드코딩하면 수정 어려움</td>
<td>✅ 자동 인덱싱으로 유지보수 쉬움</td>
</tr>
<tr>
<td>- gpt 답변</td>
<td></td>
<td></td>
</tr>
<tr>
<td>결론부터 말하면 <strong><code>arr[arr.length] = 값</code></strong> 와 <strong><code>arr.push(값)</code></strong> 는 거의 같은 동작을 해.</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<pre><code>둘 다 **배열의 마지막에 값을 추가**하는 방식이야.

하지만 **약간의 차이점이 존재해!** 아래에 정리해줄게. 👇

---

## ✅ 공통점

| 항목 | 설명 |
| --- | --- |
| 동작 | 배열의 **맨 마지막 인덱스에 값을 추가**함 |
| 결과 | 배열 길이가 증가하고, 마지막에 값이 추가됨 |

예:

```jsx
let arr = [1, 2, 3];

arr[arr.length] = 500; // arr은 [1, 2, 3, 500]
arr.push(600);         // arr은 [1, 2, 3, 500, 600]
```          
---

**⚠️ 차이점**

| 구분 | `arr.push(value)` | `arr[arr.length] = value` |
| --- | --- | --- |
| 직관성 | ✅ 더 직관적이고 명확 | ❌ 덜 직관적 |
| 메서드 호출 | `push()`는 함수 호출 | 대괄호를 이용한 직접 할당 |
| 다중 추가 | 여러 값을 동시에 추가 가능 `arr.push(1, 2)` | ❌ 한 번에 하나만 추가 가능 |
| `Array.prototype` 함수 | push는 JS 내부 메서드라 **체이닝 가능** | 불가능 |

---

**✅ 예시 비교**

```jsx
let a = [1, 2];

a.push(3, 4); // 가능
console.log(a); // [1, 2, 3, 4]

a[a.length] = 5; // 가능
console.log(a); // [1, 2, 3, 4, 5]

a[a.length] = 6, 7; // 이렇게 하면 6만 들어감 (주의)
console.log(a); // [1, 2, 3, 4, 5, 6]
```

---

**👀 실무에서는?**

- **`push()`** 를 더 많이 써!
- 가독성, 직관성, 안정성 면에서 더 좋기 때문이야.</code></pre><ul>
<li>정리<ul>
<li>배열의 마지막에 값을 추가하고 싶을 때, 인덱스를 하드코딩하지 말자.<ul>
<li>예: arr[5] = 10 ← 배열이 바뀌면 다시 수정해야 하므로 비효율적이다.</li>
</ul>
</li>
<li>대신, arr.length를 사용하면 마지막 인덱스를 자동으로 찾아 추가할 수 있다.<ul>
<li>예: arr[arr.length] = 10</li>
</ul>
</li>
<li>그러나 더 직관적이고 가독성 좋은 방법은 push() 메서드를 사용하는 것이다.<ul>
<li>예: arr.push(10)</li>
</ul>
</li>
<li>push()는 다음과 같은 장점이 있다:<ul>
<li>배열 끝에 값을 자동으로 추가한다.</li>
<li>여러 값을 동시에 추가할 수 있다. (예: arr.push(1, 2, 3))</li>
<li>코드 가독성과 유지보수가 쉽다.</li>
</ul>
</li>
<li>따라서 배열의 끝에 값을 추가할 땐 push()를 사용하자!</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="유사-배열-객체like-array-object">유사 배열 객체(Like-Array Object)</h3>
<ul>
<li>유사 배열 객체란<ul>
<li><strong>배열과 비슷하게 사용할 수 있는 객체</strong></li>
<li>사용법을 보면 배열 같지만 실제 배열이 아닌 일반 객체</li>
</ul>
</li>
<li>특징<ul>
<li><strong><code>index 를 통한 접근</code></strong> : 배열처럼 index 를 사용해서 각 요소에 접근 가능</li>
<li><strong><code>length 속성</code></strong> : 배열처럼 length 속성이 있어서 for 구문을 이용하면 모든 요소 참조 가능</li>
<li><strong><code>배열 메서드 없음</code></strong> : forEach, map 등의 배열 메서드가 없음</li>
<li>arguments, NodeList, String 등의 내장 객체가 유사 배열 객체로 만들어져 있음 ⇒ 추후 배울 예정</li>
</ul>
</li>
<li>❗필요한 이유<ul>
<li>주로 읽기를 목적으로 사용되는 객체일 경우 배열 요소를 제어하는 메서드가 필요 없음</li>
<li>배열보다 더 적은 비용으로 생성 가능</li>
</ul>
</li>
<li>배열로 변환
Array.from(obj) 을 사용하면 쉽게 배열로 변환 가능</li>
</ul>
<p><strong>그치만~~ 배열대신에 유사배열 객체를 직접 만들어서 쓸 일은 많지 않다. 마치 배열인거 처럼 쓰고 있지만 알고보니 배열이 아니였다…..</strong></p>
<ul>
<li><p>예시</p>
<pre><code class="language-jsx">const arr = {
  length: 3,
  0: &quot;orange&quot;,
  1: &quot;yellow&quot;,
  2: &quot;green&quot;,
};

printArr(arr);</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><h3 id="2차원-배열-다차원-배열">2차원 배열, 다차원 배열</h3>
<ul>
<li>배열 안에 또 다른 배열들이 들어있는 배열</li>
<li>행렬이나 테이블 형식의 데이터를 표현할 수 있음</li>
</ul>
<table>
<thead>
<tr>
<th>구분 ⇒ k <br> ∨ <br> i</th>
<th><br>[0]<br></th>
<th><br>[1]<br></th>
<th><br>[2]<br></th>
<th><br>[3]<br></th>
</tr>
</thead>
<tbody><tr>
<td>[0]</td>
<td>2</td>
<td>4</td>
<td>6</td>
<td>8</td>
</tr>
<tr>
<td>[1]</td>
<td>3</td>
<td>6</td>
<td>9</td>
<td>12</td>
</tr>
<tr>
<td>[2]</td>
<td>4</td>
<td>8</td>
<td>12</td>
<td>16</td>
</tr>
<tr>
<td>[3]</td>
<td>5</td>
<td>10</td>
<td>15</td>
<td>20</td>
</tr>
</tbody></table>
<pre><code class="language-jsx">var numbers = [
  [2, 4, 6, 8 ],
  [3, 6, 9, 12],
  [4, 8, 12, 36],
  [5, 10, 15, 20]
];</code></pre>
<pre><code class="language-jsx">// 1차원 배열 출력하기
console.log(numbers[0]); // [2, 4, 6, 8 ]
console.log(numbers[1]); // [3, 6, 9, 12]
console.log(numbers[2]); // [4, 8, 12, 36]
console.log(numbers[3]); // [5, 10, 15, 20]</code></pre>
<pre><code class="language-jsx">// 2차원 배열 출력하기
console.log(numbers[0][0]); // 2
console.log(numbers[0][1]); // 4
console.log(numbers[1][0]); // 3
console.log(numbers[3][2]); // 15</code></pre>
</li>
</ul>
<hr>
<ul>
<li><h3 id="for-in-for-of"><code>for in</code>, <code>for of</code></h3>
<ul>
<li><p>for of <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for...of">관련 문서</a> <br>
<strong><code>for...of</code> 명령문은 반복가능한 객체</strong> (<code>Array</code>, <code>Map</code>, <code>Set</code>, <code>String</code>, <code>TypedArray</code>, <code>arguments</code> 객체 등을 포함)에 대해서 반복하고 각 개별 속성값에 대해 실행되는 문이 있는 사용자 정의 반복 후크를 호출하는 루프를 생성합니다.</p>
<pre><code class="language-jsx">// 객체 생성
const array1 = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];

// for of
for (const element of array1) {
  console.log(element); 
}
/*
출력 값
a, b, c
*/  </code></pre>
</li>
<li><p>for in <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for...in">관련문서</a> <br>
<strong><code>for...in</code> 문</strong>은 상속된 열거 가능한 속성들을 포함하여 객체에서 문자열로 키가 지정된 모든 열거 가능한 속성에 대해 반복합니다. (<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Symbol">Symbol</a>로 키가 지정된 속성은 무시합니다.)</p>
<pre><code class="language-jsx">  // 객체 생성
  const object = { a: 1, b: 2, c: 3 };

  for (const property in object) {
    console.log(`${property}: ${object[property]}`);
  }

/*
출력 값
&quot;a: 1&quot;
&quot;b: 2&quot;
&quot;c: 3&quot;
*/ </code></pre>
</li>
<li><p>📌 <code>for...in</code> vs <code>for...of</code></p>
<p>한줄요약: <code>for...in</code>은 <strong>객체의 이름표(키)</strong>를 하나씩 꺼낼 때 쓰고,  <code>for...of</code>는 <strong>배열이나 글자처럼 하나씩 꺼낼 수 있는 것의 내용(값)</strong>을 하나씩 꺼낼 때 써! ✅</p>
<table>
<thead>
<tr>
<th>구분</th>
<th><code>for...in</code></th>
<th><code>for...of</code></th>
</tr>
</thead>
<tbody><tr>
<td>🔍 용도</td>
<td>객체의 <strong>키(key)</strong>를 반복</td>
<td>배열, 문자열 등 <strong>이터러블(iterable)</strong>의 <strong>값(value)</strong>을 반복</td>
</tr>
<tr>
<td>🔁 반복 대상</td>
<td>객체, 배열 (키 기준)</td>
<td>배열, 문자열, Map, Set 등 (값 기준)</td>
</tr>
<tr>
<td>🔑 반환값</td>
<td><strong>속성 이름(문자열)</strong> 또는 인덱스</td>
<td><strong>값(value)</strong></td>
</tr>
<tr>
<td>⚠️ 주의사항</td>
<td>배열 순회 시 인덱스를 문자열로 반환하므로 주의 필요</td>
<td>객체에는 사용할 수 없음 (오류 발생)</td>
</tr>
</tbody></table>
<hr>
<p><strong>💡 언제 어떤 걸 써야 할까?</strong></p>
<table>
<thead>
<tr>
<th>상황</th>
<th>사용</th>
</tr>
</thead>
<tbody><tr>
<td>객체의 key를 하나씩 순회해야 한다</td>
<td><code>for...in</code></td>
</tr>
<tr>
<td>배열이나 문자열의 <strong>값</strong>만 필요하다</td>
<td><code>for...of</code></td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li>24-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-24-01.js">JSON 문법으로 코드 만들기</a></li>
<li>25 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-25.js">객체의 속성 관리</a></li>
<li>26 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-26.js">배열 생성, 읽기, 쓰기</a></li>
<li>27 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-27.js">for of, for in</a></li>
<li>28 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-28.js">유사 배열 객체</a></li>
<li>29-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-29-01.js">2차원 배열</a></li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>배열에 대해서 조금 더 자세히 알아보고 공부해야겠다...수업 중간 중간에 조금 졸았던 것 같아서 막바지에는 따라가기 힘들었던 경향이 있다. 최대한 빨리 따라잡을 수 있도록 딥다이브책이나 공식문서를 보면서 익혀가야겠다!</li>
</ul>
<hr>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array">Array 객체 | mdn</a></li>
<li><a href="https://www.howdy-mj.me/javascript/array-and-array-like-object-and-iterable">유사배열 | MJ Kim 블로그</a></li>
<li><a href="https://www.freecodecamp.org/news/javascript-2d-arrays/">n차원 배열 | freecodecamp</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/for...in">for...in | mdn</a></li>
<li><a href="https://www.notion.so/a0f2b124fce8401d9e18d5e13503f736?pvs=4">노션 정리 링크</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[2025-04-03] Object, function - [멋쟁이사자처럼부트캠프 프론트엔드13기] ]]></title>
            <link>https://velog.io/@koo-rogie/2025-04-03-Object-function-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</link>
            <guid>https://velog.io/@koo-rogie/2025-04-03-Object-function-%EB%A9%8B%EC%9F%81%EC%9D%B4%EC%82%AC%EC%9E%90%EC%B2%98%EB%9F%BC%EB%B6%80%ED%8A%B8%EC%BA%A0%ED%94%84-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C13%EA%B8%B0</guid>
            <pubDate>Thu, 10 Apr 2025 06:15:23 GMT</pubDate>
            <description><![CDATA[<h2 id="📚-오늘-공부한-내용">📚 오늘 공부한 내용</h2>
<ul>
<li>반복문을 멈추는 코드</li>
<li>Object</li>
<li>function</li>
</ul>
<hr>
<h2 id="🧠-배운-점--정리">🧠 배운 점 &amp; 정리</h2>
<ul>
<li><h3 id="반복문을-멈추는-코드">반복문을 멈추는 코드</h3>
<ul>
<li><p>break</p>
<ul>
<li>반복문 이나 switch 문을 즉시 종료</li>
<li>break 를 감싸고 있는 코드 블럭을 빠져나오고 코드 블럭 이후의 코드로 실행이 넘어감</li>
</ul>
</li>
<li><p>continue</p>
<ul>
<li>반복문 내에서 남아있는 코드를 건너뛰고 다음 반복으로 실행이 넘어감</li>
</ul>
</li>
</ul>
<p>예시코드</p>
<pre><code class="language-js">const n = 1;
const m = 10;

for (let i = n; i &lt;= m; i++) {
  if (i % 2 === 0) {
    console.log(`첫 번째 짝수: ${i}`);
    continue; // 레이블이 지정된 루프의 현재 반복에서 명령문의 실행을 종료하고 반복문의 처음으로 돌아가여 루프문의 다음 코드를 실행합니다.
  // break; / =&gt; 반복문이 몇개이든 상간없이 코드 멈추기
  }
}</code></pre>
</li>
</ul>
<hr>
<ul>
<li><h3 id="object">Object</h3>
<ul>
<li>key value 쌍의 데이터 집합 (속성, property)</li>
<li>속성의 값으로 모든 데이터 타입 지정 가능<ul>
<li>값으로 함수가 지정된 속성을 메소드 (method) 라 함</li>
</ul>
</li>
<li>여러개의 속성을 포함할 수 있음</li>
<li>원시 타입은 한 개의 변수 안에 2개의 값을 넣을 수 없었음</li>
</ul>
<p>예시코드    </p>
<pre><code class="language-jsx">  // 원시 타입
  let userName = &quot;차차핑&quot;;
  let kor = 100;
  let eng = 90;
  let math = 85;

  let sum = kor + eng + math;
  let avg = sum / 3;

  console.log(&quot;총점: &quot; + sum);
  console.log(&quot;평균: &quot; + avg);</code></pre>
<p>  ⇒ 원시 타입은 userName이라는 값에 다른 값을 넣으려면 변수를 하나 더 선언해야함</p>
<pre><code class="language-jsx">  // 객채로 만들기
  const score = new Object();
  score.userName = &quot;차차핑&quot;;
  score.kor = 100;
  score.eng = 90;
  score.math = 85;

  score.sum = kor + eng + math;
  score.avg = sum / 3;
  console.log(`${score.userName}의 총점: ${score.sum}`);
  console.log(`${score.userName}의 평균: ${score.avg}`);</code></pre>
<p>  ⇒ score이라는 변수를 새로 만들고 그 안에 변수값을 수정함</p>
</li>
</ul>
<hr>
<ul>
<li><h3 id="function">function</h3>
<ul>
<li>명령어의 묶음</li>
<li>특정 기능을 재사용 하고 싶을 때 작성</li>
<li>함수이름 , 인자목록 , 실행구문 , 반환값으로 구성됨</li>
</ul>
<p>예제</p>
<pre><code class="language-jsx">// 기본 값
function 함수명 (매개변수1, 매개변수2, ...){
실행할 구문1;
실행할 구문2;
...
return 반환값;
}</code></pre>
<p>실행구문은 함수 밑에 두나 함수 위에 두나 상관이 없음 </p>
<ul>
<li><p>하드코딩 vs 함수 사용</p>
<pre><code class="language-jsx">console.log(&quot;hello Function!&quot;);
console.log(&quot;hello Function!&quot;);
console.log(&quot;hello Function!&quot;);</code></pre>
<p>⇒ 하드코딩으로 3번 사용함</p>
<pre><code class="language-jsx">//함수 생성
function sayHello() {
  console.log(&quot;안녕 Function!&quot;);
}
//함수 호출
sayHello();</code></pre>
<p>⇒ 함수 명 사용함</p>
</li>
<li><p>매개 변수</p>
<p>매개변수는 함수에 전달되는 입력값을 받기 위한 변수이다.</p>
<pre><code class="language-jsx">function sayHello(pingName) {
                // 매개변수
  console.log(&quot;Hello &quot; + pingName);
}

sayHello(&quot;하츄핑&quot;);
        // 호출할때 괄호 안에 매개 변수 사용하기</code></pre>
<p><strong>📌 실행 순서 (디버깅 과정)</strong></p>
<p>1️⃣ <strong>함수 <code>sayHello()</code> 정의</strong></p>
<ul>
<li><p><code>function sayHello(pingName) { console.log(&quot;Hello&quot; + pingName); }</code></p>
<ul>
<li><p>하지만 함수는 실행되지 않음 (호출되기 전 단계)</p>
<p>2️⃣ <strong>첫 번째 함수 호출 <code>sayHello(&quot;하츄핑&quot;)</code></strong></p>
</li>
<li><p><code>pingName</code>에 <code>&quot;하츄핑&quot;</code>이 전달됨</p>
</li>
<li><p>실행: <code>console.log(&quot;Hello&quot; + &quot;하츄핑&quot;)</code></p>
</li>
<li><p>출력: <strong><code>Hello하츄핑</code></strong></p>
<p>3️⃣ <strong>두 번째 함수 호출 <code>sayHello(&quot;깡총핑&quot;)</code></strong></p>
</li>
<li><p><code>pingName</code>에 <code>&quot;깡총핑&quot;</code>이 전달됨</p>
</li>
<li><p>실행: <code>console.log(&quot;Hello&quot; + &quot;깡총핑&quot;)</code></p>
</li>
<li><p>출력: <strong><code>Hello깡총핑</code></strong></p>
<p>4️⃣ <strong>세 번째 함수 호출 <code>sayHello(&quot;초롱핑&quot;)</code></strong></p>
</li>
<li><p><code>pingName</code>에 <code>&quot;초롱핑&quot;</code>이 전달됨</p>
</li>
<li><p>실행: <code>console.log(&quot;Hello&quot; + &quot;초롱핑&quot;)</code></p>
</li>
<li><p>출력: <strong><code>Hello초롱핑</code></strong></p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>함수를 사용할때와 아닐때</p>
<p><strong>🧠 함수 쓸 때</strong></p>
<p>함수는 그냥 “이름 붙여놓은 코드 블록”이야. 반복되는 작업을 <strong>한 번만</strong> 쓰고 계속 <strong>불러서</strong> 쓸 수 있게 하는 거.</p>
<p><strong>예시</strong></p>
<pre><code class="language-jsx">function sayHello() {
  console.log(&quot;안녕, 감자야!&quot;);
}

sayHello(); // 실행
sayHello(); // 또 실행
</code></pre>
<p><strong>언제 쓰냐?</strong></p>
<ul>
<li><p>코드 재사용하고 싶을 때</p>
</li>
<li><p>같은 패턴이 반복될 때</p>
</li>
<li><p>코드 정리하고 싶을 때 (덜 지저분하게)</p>
</li>
<li><p>나중에 고치기 쉽게 만들고 싶을 때</p>
<p><strong>🤯 함수 안 쓸 때</strong></p>
<p>그냥 <strong>하드코딩</strong>. 필요한 작업을 그때그때 쓰는 스타일. 빠르게 테스트하거나, 짧고 단순한 코드에선 괜찮지만,</p>
<p>조금만 길어지면 바로 <strong>지옥</strong> 개장함.  ㅋㅋㅋㅋㅋㅋㅋㅋㅋ</p>
<p><strong>예시</strong></p>
<pre><code class="language-jsx">console.log(&quot;안녕, 감자야!&quot;);
console.log(&quot;안녕, 감자야!&quot;); // 중복된 코드
</code></pre>
<h2 id="🎯-비교-요약">🎯 비교 요약</h2>
<table>
<thead>
<tr>
<th>상황</th>
<th>함수 쓸 때</th>
<th>함수 안 쓸 때</th>
</tr>
</thead>
<tbody><tr>
<td>반복 작업</td>
<td>✅ 재사용 짱</td>
<td>❌ 복붙지옥</td>
</tr>
<tr>
<td>깔끔한 코드</td>
<td>✅ 구조화됨</td>
<td>❌ 혼돈의 카오스</td>
</tr>
<tr>
<td>단순 테스트</td>
<td>❌ 오바임</td>
<td>✅ 빠름</td>
</tr>
<tr>
<td>협업 코드</td>
<td>✅ 칭찬받음</td>
<td>❌ 욕먹음</td>
</tr>
</tbody></table>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="🔗-배웠던-파일">🔗 배웠던 파일</h2>
<ul>
<li>21-03 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-21-03.js">for - 구구단</a></li>
<li>22 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-22.js">반복문 - break, continue </a></li>
<li>23-01 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-23-01.js">Object - 생성자 함수로 객체 생성</a></li>
<li>23-02 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-23-02.js">Object - 총점과 평균</a></li>
<li>30 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-30.js">function - 처음</a> </li>
<li>31 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-31.js">function - 매개변수</a></li>
<li>32 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-32.js">function - 도어락</a></li>
<li>33 <a href="https://github.com/koo-rogie/js-start/blob/main/workspace/ch01/ex01-33.js">function - 반환값이 있는 함수</a></li>
</ul>
<hr>
<h2 id="❓-생긴-질문--더-알아볼-것">❓ 생긴 질문 / 더 알아볼 것</h2>
<ul>
<li>추후 배울 object의 하위 속성들?을 좀더 공부하고 개념에 대해서 더 알아보고 싶다</li>
</ul>
<hr>
<h2 id="🔗-참고-자료">🔗 참고 자료</h2>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/break">break | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/continue">continue | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object">Object | mdn</a></li>
<li><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Function">Function | mdn</a></li>
<li><a href="https://www.notion.so/a0f2b124fce8401d9e18d5e13503f736?pvs=4">노션 정리 링크</a></li>
</ul>
<hr>
]]></description>
        </item>
    </channel>
</rss>