<?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>Tue, 23 Dec 2025 12:57:43 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[변수 이름을 어떻게 하면 잘 지을까?]]></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>