<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>infp_pro.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 20 Jun 2026 18:07:39 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>infp_pro.log</title>
            <url>https://velog.velcdn.com/images/infp_pro/profile/33ec3a40-e6e8-45c9-a806-74f6a993ee73/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. infp_pro.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/infp_pro" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Day1-2 for문 + 대소문자 변경]]></title>
            <link>https://velog.io/@infp_pro/Day1-2-for%EB%AC%B8-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%EA%B2%BD</link>
            <guid>https://velog.io/@infp_pro/Day1-2-for%EB%AC%B8-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%EA%B2%BD</guid>
            <pubDate>Sat, 20 Jun 2026 18:07:39 GMT</pubDate>
            <description><![CDATA[<p><strong>문자열을 한 글자씩 꺼내서, 변환한 값을 바로 출력하거나 다시 저장</strong></p>
<h2 id="코드-구조">코드 구조</h2>
<pre><code class="language-java">for (int i = 0; i &lt; a.length(); i++) {
    char ch = a.charAt(i);

    if (Character.isUpperCase(ch)) {
        ch = Character.toLowerCase(ch);
    } else {
        ch = Character.toUpperCase(ch);
    }

    System.out.print(ch);
}</code></pre>
<h2 id="실수했던-부분들">실수했던 부분들</h2>
<ol>
<li>반복 범위를 <code>20</code>으로 고정함</li>
</ol>
<pre><code class="language-java">for (int i = 0; i &lt; 20; i++)</code></pre>
<p>문자열 길이는 매번 다르니까 실제 길이를 써야 했었다.</p>
<pre><code class="language-java">for (int i = 0; i &lt; a.length(); i++)</code></pre>
<p><code>charAt(i)</code>는 인덱스가 문자열 길이를 넘어가면 에러가 난다.</p>
<ol start="2">
<li>대소문자 변환 방향이 반대였음</li>
</ol>
<p>문제는:</p>
<pre><code class="language-text">대문자 -&gt; 소문자
소문자 -&gt; 대문자</code></pre>
<p>그래서:</p>
<pre><code class="language-java">if (Character.isUpperCase(ch)) {
    ch = Character.toLowerCase(ch);
} else {
    ch = Character.toUpperCase(ch);
}</code></pre>
<ol start="3">
<li><code>Character.toLowerCase(ch)</code>가 원본을 바꾸는 줄 알았음</li>
</ol>
<p>이 코드는 <code>ch</code>를 직접 바꾸지 않는다.</p>
<pre><code class="language-java">Character.toLowerCase(ch);</code></pre>
<p>변환된 값을 반환만 한다. 그래서 이렇게 써야 한다.</p>
<pre><code class="language-java">ch = Character.toLowerCase(ch);</code></pre>
<p>또는 바로 출력:</p>
<pre><code class="language-java">System.out.print(Character.toLowerCase(ch));</code></pre>
<ol start="4">
<li>마지막에 원래 문자열 <code>a</code>를 출력함</li>
</ol>
<pre><code class="language-java">System.out.println(a);</code></pre>
<p>이러면 변환 결과가 아니라 원래 입력 문자열이 출력된다.<br><code>String a</code> 자체는 바뀌지 않았기 때문</p>
<h2 id="포인트">포인트</h2>
<pre><code class="language-text">a.length() = 문자열 길이
a.charAt(i) = i번째 문자 꺼내기
Character.isUpperCase(ch) = 대문자인지 확인
Character.toLowerCase(ch) = 소문자로 바꾼 값을 반환
Character.toUpperCase(ch) = 대문자로 바꾼 값을 반환</code></pre>
<pre><code class="language-text">변환 함수는 원본을 바꾸지 않는다.
변환된 결과를 변수에 저장하거나 바로 출력해야 한다.</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Day1-1 Java 프로그램 기본 구조 + 입력 + 출력]]></title>
            <link>https://velog.io/@infp_pro/Day1-1-Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0-%EC%9E%85%EB%A0%A5-%EC%B6%9C%EB%A0%A5</link>
            <guid>https://velog.io/@infp_pro/Day1-1-Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0-%EC%9E%85%EB%A0%A5-%EC%B6%9C%EB%A0%A5</guid>
            <pubDate>Sat, 20 Jun 2026 17:44:26 GMT</pubDate>
            <description><![CDATA[<h2 id="기본-구조">기본 구조</h2>
<pre><code>import java.util.Scanner;

public class Solution {
    public static void main(String[] args) {
        // 실제 실행 코드는 여기
    }
}</code></pre><p><code>class Solution</code>은 코드가 들어가는 상자이다. 
Java는 코드를 기본적으로 클래스 안에 작성한다. 
프로그래머스는 보통 <code>Solution</code> 클래스를 기준으로 실행.</p>
<p><code>main</code>은 Java 프로그램의 시작점이다.</p>
<pre><code>public static void main(String[] args)</code></pre><p>의미는:</p>
<pre><code>public = JVM이 밖에서 접근 가능
static = 객체 생성 없이 바로 실행 가능
void = 반환값 없음
main = Java가 시작점으로 찾는 이름
String[] args = 실행할 때 외부에서 받을 수 있는 문자열 배열</code></pre><p>코딩테스트에서는 <code>args</code>는 거의 안 쓰지만, Java의 약속된 시작 함수 모양이라 넣는다.</p>
<hr>
<h2 id="static-vs-일반-메서드">static vs 일반 메서드</h2>
<blockquote>
<p>궁금증. <strong>static/dynamic 할때랑 같은 static 맞나? - 맞음</strong>
Java에서 static은 객체마다 따로 생기는 것이 아니라, 클래스가 메모리에 올라갈 때 클래스에 하나만 붙는것.</p>
<p>dynamic = 실행 중에 객체를 만들고, 객체별 상태를 가짐
static = 클래스 로딩 시점에 정해지고, 객체 없이 클래스에 붙음
static쓰면 객체 생성할 필요 없이 사용가능. 메서드 등이 클래스에 붙음
static 안 붙이면 객체를 만들 때 생성되는 인스턴스 멤버가 된다</p>
</blockquote>
<blockquote>
<p><strong>main에 static이 붙어있는 이유</strong>도
프로그램 시작 전에 Solution 객체를 만들지 않아도
JVM이 Solution.main()을 바로 호출할 수 있어야 하니까</p>
</blockquote>
<pre><code>static 메서드 = 객체 없이 클래스 이름으로 바로 호출
일반 메서드 = 객체를 만든 다음 그 객체를 통해 호출</code></pre><p>예:</p>
<pre><code>Math.max(3, 5);</code></pre><p><code>Math.max</code>는 <code>static</code>이라서 <code>new Math()</code>를 안 한다.</p>
<p>반면:</p>
<pre><code>Scanner sc = new Scanner(System.in);
sc.next();</code></pre><p><code>Scanner</code>는 실제 입력 상태를 관리해야 하니까 객체를 만들어서 사용한다.</p>
<hr>
<h2 id="scanner">Scanner</h2>
<pre><code>Scanner sc = new Scanner(System.in);</code></pre><p>뜻:</p>
<pre><code>표준 입력(System.in)을 읽는 Scanner 객체를 만들고,
그 객체를 sc라는 이름으로 쓰겠다.</code></pre><p>문자열 입력:</p>
<pre><code>String a = sc.next();</code></pre><p>정수 입력:</p>
<pre><code>int a = sc.nextInt();</code></pre><h2 id="출력">출력</h2>
<p>그냥 출력:</p>
<pre><code>System.out.println(a);</code></pre><p>문자열이랑 변수 같이 출력:</p>
<pre><code>System.out.println(&quot;a = &quot; + a);</code></pre><p><code>+</code>는 문자열과 변수를 이어 붙인다.</p>
<p>예를 들어 <code>a</code>가 <code>4</code>면:</p>
<pre><code>&quot;a = &quot; + a</code></pre><p>결과는:</p>
<pre><code>a = 4</code></pre><hr>
<pre><code>입력 도구 만들기: Scanner sc = new Scanner(System.in);
문자열 입력: sc.next()
정수 입력: sc.nextInt()
출력: System.out.println()
문자열 + 변수 출력: &quot;a = &quot; + a</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Day1-2 엔터티]]></title>
            <link>https://velog.io/@infp_pro/Day1-2-%EC%97%94%ED%84%B0%ED%8B%B0</link>
            <guid>https://velog.io/@infp_pro/Day1-2-%EC%97%94%ED%84%B0%ED%8B%B0</guid>
            <pubDate>Sat, 20 Jun 2026 16:49:38 GMT</pubDate>
            <description><![CDATA[<h2 id="정의">정의</h2>
<blockquote>
<p>엔터티란 업무에서 관리해야 할 정보의 덩어리(명사)다. 실제 테이블의 후보가 된다.</p>
</blockquote>
<p>EX. 쇼핑몰이라면 회원/상품/주문/배송 같은 명사 하나하나가 <strong>엔터티</strong>.
각 엔터티의 개별 사례 (&#39;김주안 고객&#39;)을 <strong>인스턴스</strong>라고 한다.
<img src="https://velog.velcdn.com/images/infp_pro/post/b2ea1d08-bf20-4cd6-b8a1-3f1256af9a09/image.png" alt=""></p>
<p>멤버라는 엔터티는 ORDER라는 엔터티를 여러개 만들 수 있음. 
주안 고객님은 멤버 엔터티의 인스턴스. 주안고객의 주문1,2 들은 ORDER 엔터티의 인스턴스들.</p>
<blockquote>
<p><strong>엔터티와 테이블의 차이?</strong>
엔터티는 데이터 모델링 단계, 테이블은 실제 DB 구현 단계에 해당하는 것.
즉 SQL 구문으로 뽑아내고 하는건 테이블, 추상적 개념 학생 등은 엔터티임</p>
</blockquote>
<h2 id="엔터티의-구성">엔터티의 구성</h2>
<p><img src="https://velog.velcdn.com/images/infp_pro/post/21ce6601-edfe-42b9-b028-cdf9b88e4735/image.png" alt="">
엔터티 = 테이블은 아님.
엔터티는 열과 행으로 이루어지며, 열=속성이고, 행=인스턴스임.
즉 속성을 가진 인스턴스들이 여러개가 있는것.</p>
<h2 id="엔터티의-5가지-특징">엔터티의 5가지 특징</h2>
<h3 id="1-업무에서-필요">1. 업무에서 필요</h3>
<h3 id="2-식별가능">2. 식별가능</h3>
<h3 id="3-인스턴스--2">3. 인스턴스 &gt;= 2</h3>
<h3 id="4-속성--2">4. 속성 &gt;= 2</h3>
<h3 id="5-관계보유">5. 관계보유</h3>
<pre><code>1,2,5는 당연한거고,

엔터티는 반드시 2개 이상의 인스턴스를 가져야 한다.
→ 엔터티는 개별 데이터 하나가 아니라 인스턴스들의 집합이기 때문.

엔터티는 반드시 2개 이상의 속성을 가져야 한다.
→ 엔터티는 식별되고 설명될 수 있는 업무 정보를 가져야 하기 때문.</code></pre><h2 id="엔터티의-분류">엔터티의 분류</h2>
<h3 id="유무형에-따른-분류">유무형에 따른 분류</h3>
<ol>
<li>유형 엔터티 - 물리적 존재 - 상품/사원/매장 등</li>
<li>개념 엔터티 - 개념적 존재 - 부서/조직/학과 등</li>
<li>사건 엔터티 - 행위로 발생 - 주문/결제/출입기록 등</li>
</ol>
<h3 id="발생-시점에-따른-분류">발생 시점에 따른 분류</h3>
<p>Step1. 기본 엔터티 - 다른 엔터티 없이도 성립 - 사원/부서/고객
Step2. 중심 엔터티 - 기본 엔터티에서 발생 - 주문/계약/매출
Step3. 행위 엔터티 - 2개 이상 엔터티의 관계에서 발생 - 주문상세/출고/입출금</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Day1-1 데이터 모델의 이해]]></title>
            <link>https://velog.io/@infp_pro/Day1-1-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AA%A8%EB%8D%B8%EC%9D%98-%EC%9D%B4%ED%95%B4</link>
            <guid>https://velog.io/@infp_pro/Day1-1-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AA%A8%EB%8D%B8%EC%9D%98-%EC%9D%B4%ED%95%B4</guid>
            <pubDate>Sat, 20 Jun 2026 16:41:08 GMT</pubDate>
            <description><![CDATA[<h2 id="데이터-모델의-이해">데이터 모델의 이해</h2>
<h3 id="정의">정의</h3>
<blockquote>
<p>데이터 모델이란 현실 세계의 복잡한 정보를 컴퓨터에 저장하기 위해 그린 <strong>설계 도면</strong>이다</p>
</blockquote>
<h3 id="데이터-모델링의-3단계">데이터 모델링의 3단계</h3>
<p>추상적 개념 -&gt; 구체적 구현 단계로 진행된다.
쉽게 암기 - &#39;개-논-물&#39;</p>
<p><img src="https://velog.velcdn.com/images/infp_pro/post/3ea21137-704a-4796-81dd-f31916280e1a/image.png" alt=""></p>
<p><strong>Step1. 개념적 데이터 모델링</strong>
데이터 요구 사항을 분석해, 핵심 엔터티와 그들 간의 관계를 나타내는 ERD를 생성</p>
<p><strong>Step2. 논리적 모델</strong>
속성, PK, FK 채움 + 정규화. DBMS와 무관</p>
<p><strong>Step3. 물리적 모델</strong>
CREATE TABLE + 인덱스,파티션,자료형 명시</p>
<p><strong>Step4. 데이터베이스</strong>
데이터가 차곡차곡 쌓인 상태. SQL로 조회,입력,수정</p>
<h3 id="추가-개념-알-것들---dbms-속성-pk-fk-정규화화">추가 개념 알 것들 - DBMS, 속성, PK, FK, 정규화화</h3>
<blockquote>
<p><strong>DBMS란?</strong>
<strong>DBMS = Database Management System</strong><br>말 그대로 <strong>데이터베이스를 관리해주는 소프트웨어</strong>임.
Oracle, MySQL 같은거</p>
</blockquote>
<blockquote>
<p><strong>속성, PK, FK</strong>란?
속성 = 필드/칼럼 후보. 엔터티 세부 정보. (EX. 학생의 이름, 학과, 후보 등)
PK = Primary Key = 주식별자. ID 정도로 기억해두면 됨
FK = Foreign Key = 외래식별자. 다른 테이블의 PK를 참조하는 컬럼</p>
</blockquote>
<h3 id="fk-상세-예시">FK 상세 예시</h3>
<p>학생 테이블</p>
<pre><code>학생ID(PK) | 이름
----------|------
202401    | 김철수
202402    | 이영희</code></pre><p>수강 테이블</p>
<pre><code>수강ID(PK) | 학생ID(FK) | 과목명
----------|------------|------
1         | 202401     | 데이터베이스
2         | 202402     | 운영체제
3         | 202401     | 알고리즘</code></pre><p>여기서 <code>수강.학생ID</code>는 FK.</p>
<blockquote>
<p>정규화는?
정규화 = 테이블을 잘 쪼개서 중복과 이상현상을 줄이는 과정
한 테이블에 전부 때려박지 말고, 쪼개서 별도 테이블로 나누는 것.</p>
</blockquote>
<h3 id="정규화-상세-예시">정규화 상세 예시</h3>
<p>수강정보라는 아래 테이블이 있다면</p>
<table>
<thead>
<tr>
<th>학생ID</th>
<th>학생명</th>
<th>과목ID</th>
<th>과목명</th>
<th>교수명</th>
</tr>
</thead>
<tbody><tr>
<td>202401</td>
<td>김철수</td>
<td>C001</td>
<td>데이터베이스</td>
<td>홍길동</td>
</tr>
<tr>
<td>202402</td>
<td>이영희</td>
<td>C001</td>
<td>데이터베이스</td>
<td>홍길동</td>
</tr>
<tr>
<td>202403</td>
<td>박민수</td>
<td>C002</td>
<td>운영체제</td>
<td>이몽룡</td>
</tr>
</tbody></table>
<p>이를 학생/과목/수강 테이블로 쪼갤 수 있음</p>
<p>학생</p>
<pre><code>학생ID(PK) | 학생명
----------|------
202401    | 김철수
202402    | 이영희
202403    | 박민수</code></pre><p>과목</p>
<pre><code>과목ID(PK) | 과목명       | 교수명
----------|--------------|------
C001      | 데이터베이스 | 홍길동
C002      | 운영체제     | 이몽룡</code></pre><p>수강</p>
<pre><code>학생ID(FK) | 과목ID(FK)
----------|----------
202401    | C001
202402    | C001
202403    | C002</code></pre><h3 id="정규화의-목적">정규화의 목적?</h3>
<pre><code>1. 데이터 중복 감소
2. 데이터 불일치 방지
3. 삽입 이상 방지
4. 삭제 이상 방지
5. 갱신 이상 방지</code></pre><p>1,2는 위에서 다루었고,</p>
<p>3,4,5는 </p>
<h3 id="갱신-이상">갱신 이상</h3>
<p>같은 정보가 여러 곳에 있어서 하나만 수정되면 데이터가 불일치하는 문제.</p>
<pre><code>C001 과목명이 어떤 행은 데이터베이스,어떤 행은 DB로 저장됨</code></pre><h3 id="삽입-이상">삽입 이상</h3>
<p>불필요한 정보가 없으면 필요한 정보를 넣지 못하는 문제.</p>
<pre><code>아직 수강생이 없는 과목은 등록 못 함</code></pre><h3 id="삭제-이상">삭제 이상</h3>
<p>어떤 데이터를 삭제했더니 보존해야 할 정보까지 같이 사라지는 문제.</p>
<pre><code>마지막 수강생을 삭제했더니 과목 정보도 사라짐</code></pre><h3 id="데이터-모델링의-3가지-관점">데이터 모델링의 3가지 관점</h3>
<ol>
<li>데이터 관점</li>
<li>프로세스 관점</li>
<li>상관관계 관점</li>
</ol>
<blockquote>
<p>1은 무엇을 저장할지. 어떤 테이블? 컬럼? 테이블끼리의 관계? 를 생각하는 관점
2는 어떻게 처리할지. 이건 게시판으로 따지자면 글을 쓰고 수정하고 삭제될때의 유저 플로우 관점
3은 언제 데이터가 변하는지. 1과 2가 어우러져서, 어떤 프로세스에 어떤 데이터가 CRUD 되는지 보는 것임</p>
</blockquote>
<h3 id="좋은-데이터-모델의-특징">좋은 데이터 모델의 특징</h3>
<table>
<thead>
<tr>
<th>특징</th>
<th>핵심 의미</th>
<th>키워드</th>
</tr>
</thead>
<tbody><tr>
<td><strong>완전성</strong></td>
<td>필요한 데이터가 빠지면 안 됨</td>
<td>빠짐없음</td>
</tr>
<tr>
<td><strong>중복 배제</strong></td>
<td>같은 사실을 반복 저장하면 안 됨</td>
<td>한 번만 저장</td>
</tr>
<tr>
<td><strong>업무 규칙</strong></td>
<td>업무 제약조건이 반영되어야 함</td>
<td>규칙, 제약</td>
</tr>
<tr>
<td><strong>데이터 재사용</strong></td>
<td>여러 업무에서 다시 쓸 수 있어야 함</td>
<td>재사용</td>
</tr>
<tr>
<td><strong>의사소통</strong></td>
<td>사람들이 모델로 같은 의미를 이해해야 함</td>
<td>공유, 소통</td>
</tr>
<tr>
<td><strong>통합성</strong></td>
<td>같은 데이터는 전사적으로 하나로 관리</td>
<td>통합 관리</td>
</tr>
<tr>
<td><strong>중복 배제 VS 통합성</strong></td>
<td></td>
<td></td>
</tr>
<tr>
<td>```</td>
<td></td>
<td></td>
</tr>
<tr>
<td>중복 배제</td>
<td></td>
<td></td>
</tr>
<tr>
<td>= 같은 DB/모델 안에서 동일한 사실을 반복 저장하지 말자</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>통합성
= 조직 전체에서 같은 의미의 데이터를 하나로 통합 관리하자</p>
<pre><code>**업무 규칙 vs 의사소통**</code></pre><p>업무 규칙
= 업무의 제약조건이 모델에 표현됨</p>
<p>의사소통
= 그 모델을 보고 사람들이 같은 의미로 이해함</p>
<pre><code>
### 3층 스키마 (ANSI/SPARC)</code></pre><p>3층 스키마
├─ 외부 스키마
│  └─ 사용자별 관점, View
│
├─ 개념 스키마
│  └─ 전체 DB의 논리적 구조
│
└─ 내부 스키마
   └─ 실제 저장 방식, 인덱스, 파일 구조</p>
<p>```
이것도 <strong>같은 데이터베이스를 세 가지 관점</strong>에서 본 것이다.</p>
<p>외부 -&gt; 개념 -&gt; 내부로 갈 수록 말 그대로 외부 인터페이스에서 내부 시스템으로 들어가는 것임</p>
<blockquote>
<p>외부 = 사용자별 관점
  개념 = 데이터 아키텍처
  내부 = 데이터 관계</p>
</blockquote>
<p>정도로 생각하면 된다</p>
<p><strong>데이터 독립성 2가지</strong></p>
<ol>
<li>논리적 독립성 - 개념 스키마가 변경되어도 외부 스키마는 영향이 없어야 함</li>
<li>물리적 독립성 - 내부 스키마가 변경되어도 개념/외부 스키마는 영향이 없어야 함함</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[파이썬 기초문법]]></title>
            <link>https://velog.io/@infp_pro/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EA%B8%B0%EC%B4%88%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@infp_pro/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EA%B8%B0%EC%B4%88%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Tue, 16 Jun 2026 12:35:36 GMT</pubDate>
            <description><![CDATA[<p>점프 투 파이썬 바탕
<a href="https://wikidocs.net/4307">https://wikidocs.net/4307</a></p>
<pre><code>Python 기초 문법 복구
├─ Chunk 1: 변수 / 객체 / 참조 개념
├─ Chunk 2: 숫자 / 문자열 / bool
├─ Chunk 3: list / tuple
├─ Chunk 4: dict / set
├─ Chunk 5: 조건문 / 반복문
├─ Chunk 6: 함수
├─ Chunk 7: comprehension
├─ Chunk 8: 파일 읽기 / CSV 감각
├─ Chunk 9: 예외처리
├─ Chunk 10: 클래스 아주 가볍게
├─ Chunk 11: pandas 들어가기 전 Python 패턴</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- Exclude, Extract, ReturnType (4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Exclude-Extract-ReturnType-4</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Exclude-Extract-ReturnType-4</guid>
            <pubDate>Tue, 15 Jul 2025 09:37:56 GMT</pubDate>
            <description><![CDATA[<h2 id="excludet-k">Exclude&lt;T, K&gt;</h2>
<p>Exclude 타입은 다음과 같이 <code>T</code>로부터 <code>U</code>를 제거하는 타입임.</p>
<pre><code class="language-ts">type A = Exclude&lt;string | boolean, string&gt;;
// 결과: boolean</code></pre>
<p>직접 구현하면 다음과 같음.</p>
<pre><code class="language-ts">type Exclude&lt;T, U&gt; = T extends U ? never : T;</code></pre>
<hr>
<h2 id="extractt-k">Extract&lt;T, K&gt;</h2>
<p>Extract 타입은 다음과 같이 <code>T</code>로부터 <code>U</code>를 추출하는 타입임.</p>
<pre><code class="language-ts">type B = Extract&lt;string | boolean, boolean&gt;;
// 결과: boolean</code></pre>
<p>직접 구현하면 다음과 같음.</p>
<pre><code class="language-ts">type Extract&lt;T, U&gt; = T extends U ? T : never;</code></pre>
<hr>
<h2 id="returntypet">ReturnType<T></h2>
<p>ReturnType은 타입변수 <code>T</code>에 할당된 함수 타입의 반환값 타입을 추출하는 타입임. 이 타입은 <code>infer</code>를 활용해 구현할 수 있음.</p>
<pre><code class="language-ts">type ReturnType&lt;T extends (...args: any) =&gt; any&gt; = T extends (
  ...args: any
) =&gt; infer R
  ? R
  : never;</code></pre>
<h3 id="예시">예시</h3>
<pre><code class="language-ts">function funcA() {
  return &quot;hello&quot;;
}

function funcB() {
  return 10;
}

type ReturnA = ReturnType&lt;typeof funcA&gt;;
// 결과: string

type ReturnB = ReturnType&lt;typeof funcB&gt;;
// 결과: number</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- 
Record, Pick, Omit(3)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Record-Pick-Omit3</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Record-Pick-Omit3</guid>
            <pubDate>Tue, 15 Jul 2025 09:35:44 GMT</pubDate>
            <description><![CDATA[<h1 id="pickt-k">Pick&lt;T, K&gt;</h1>
<p><strong>Pick</strong>은 특정 객체 타입에서 일부 프로퍼티만 <strong>골라내는</strong> 유틸리티 타입임.</p>
<h2 id="예제">예제</h2>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const legacyPost: Pick&lt;Post, &quot;title&quot; | &quot;content&quot;&gt; = {
  title: &quot;&quot;,
  content: &quot;&quot;,
};</code></pre>
<h2 id="직접-구현">직접 구현</h2>
<pre><code class="language-ts">type Pick&lt;T, K extends keyof T&gt; = {
  [key in K]: T[key];
};</code></pre>
<hr>
<h1 id="omitt-k">Omit&lt;T, K&gt;</h1>
<p><strong>Omit</strong>은 특정 객체 타입에서 일부 프로퍼티만 <strong>제외하는</strong> 유틸리티 타입임.</p>
<h2 id="예제-1">예제</h2>
<pre><code class="language-ts">const noTitlePost: Omit&lt;Post, &quot;title&quot;&gt; = {
  content: &quot;&quot;,
  tags: [],
  thumbnailURL: &quot;&quot;,
};</code></pre>
<h2 id="직접-구현-1">직접 구현</h2>
<pre><code class="language-ts">type Omit&lt;T, K extends keyof T&gt; = Pick&lt;T, Exclude&lt;keyof T, K&gt;&gt;;</code></pre>
<hr>
<h1 id="recordk-v">Record&lt;K, V&gt;</h1>
<p><strong>Record</strong>는 키-값 쌍을 가지는 객체 타입을 생성할 때 사용함.</p>
<h2 id="예제-2">예제</h2>
<pre><code class="language-ts">type Thumbnail = Record&lt;
  &quot;large&quot; | &quot;medium&quot; | &quot;small&quot;,
  { url: string }
&gt;;</code></pre>
<h2 id="직접-구현-2">직접 구현</h2>
<pre><code class="language-ts">type Record&lt;K extends keyof any, V&gt; = {
  [key in K]: V;
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- 
Partial, Required, Readonly(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Partial-Required-Readonly2</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-Partial-Required-Readonly2</guid>
            <pubDate>Tue, 15 Jul 2025 09:33:40 GMT</pubDate>
            <description><![CDATA[<h1 id="맵드-타입-기반-유틸리티-타입">맵드 타입 기반 유틸리티 타입</h1>
<h2 id="선요약">선요약</h2>
<p>타입스크립트의 <code>Partial&lt;T&gt;</code>, <code>Required&lt;T&gt;</code>, <code>Readonly&lt;T&gt;</code>는 <strong>맵드 타입 기반의 유틸리티 타입</strong>으로, 객체 타입의 프로퍼티를 <strong>선택적</strong>, <strong>필수</strong>, <strong>읽기 전용</strong>으로 변환함. 이들은 <strong>제네릭 + keyof + 맵드 타입</strong>의 조합으로 구현할 수 있음.</p>
<hr>
<h2 id="partialt">Partial<T></h2>
<h3 id="목적">목적</h3>
<p>객체 타입의 <strong>모든 프로퍼티를 선택적(optional)</strong>으로 변환함.</p>
<h3 id="예시">예시</h3>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const draft: Partial&lt;Post&gt; = {
  title: &quot;제목 나중에 짓자&quot;,
  content: &quot;초안...&quot;,
};</code></pre>
<h3 id="구현">구현</h3>
<pre><code class="language-ts">type Partial&lt;T&gt; = {
  [key in keyof T]?: T[key];
};</code></pre>
<hr>
<h2 id="requiredt">Required<T></h2>
<h3 id="목적-1">목적</h3>
<p>객체 타입의 <strong>모든 프로퍼티를 필수(required)</strong>로 변환함.</p>
<h3 id="예시-1">예시</h3>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const withThumbnailPost: Required&lt;Post&gt; = {
  title: &quot;한입 타스 후기&quot;,
  tags: [&quot;ts&quot;],
  content: &quot;&quot;,
  thumbnailURL: &quot;https://...&quot;,
};</code></pre>
<h3 id="구현-1">구현</h3>
<pre><code class="language-ts">type Required&lt;T&gt; = {
  [key in keyof T]-?: T[key];
};</code></pre>
<hr>
<h2 id="readonlyt">Readonly<T></h2>
<h3 id="목적-2">목적</h3>
<p>객체 타입의 <strong>모든 프로퍼티를 읽기 전용(readonly)</strong>으로 변환함.</p>
<h3 id="예시-2">예시</h3>
<pre><code class="language-ts">interface Post {
  title: string;
  tags: string[];
  content: string;
  thumbnailURL?: string;
}

const readonlyPost: Readonly&lt;Post&gt; = {
  title: &quot;보호된 게시글입니다.&quot;,
  tags: [],
  content: &quot;&quot;,
};

readonlyPost.content = &quot;해킹당함&quot;; // 오류 발생</code></pre>
<h3 id="구현-2">구현</h3>
<pre><code class="language-ts">type Readonly&lt;T&gt; = {
  readonly [key in keyof T]: T[key];
};</code></pre>
<hr>
<h2 id="마지막-요약">마지막 요약</h2>
<ul>
<li><code>Partial&lt;T&gt;</code>: 모든 프로퍼티를 선택적으로 만듦 (<code>?</code>).</li>
<li><code>Required&lt;T&gt;</code>: 모든 선택적 프로퍼티를 필수로 만듦 (<code>-?</code>).</li>
<li><code>Readonly&lt;T&gt;</code>: 모든 프로퍼티를 읽기 전용으로 만듦 (<code>readonly</code>).</li>
<li>이들 모두 <code>맵드 타입 + keyof + 제네릭</code> 조합으로 구현 가능함.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션10. 유틸리티 타입- 유틸리티 타입 소개(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%86%8C%EA%B0%9C1</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%9810.-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%9C%A0%ED%8B%B8%EB%A6%AC%ED%8B%B0-%ED%83%80%EC%9E%85-%EC%86%8C%EA%B0%9C1</guid>
            <pubDate>Tue, 15 Jul 2025 09:31:46 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>유틸리티 타입은 <strong>타입스크립트가 제공하는 특수한 타입 조합 도구</strong>임.</li>
<li>제네릭, 맵드 타입, 조건부 타입 등을 조합해 자주 쓰이는 형태의 타입을 미리 구현해둔 것임.</li>
<li>대표적인 유틸리티 타입으로는 <code>Readonly&lt;T&gt;</code>, <code>Partial&lt;T&gt;</code> 등이 있음.</li>
<li>이번 섹션에서는 이들 중 <strong>핵심적인 타입</strong>만 다루며, <strong>직접 구현</strong>도 병행함.</li>
</ul>
<hr>
<h2 id="유틸리티-타입-소개">유틸리티 타입 소개</h2>
<p>타입스크립트에서는 제네릭, 맵드 타입, 조건부 타입 등을 기반으로 실무에서 자주 사용되는 타입 조작 패턴을 미리 구현해둔 유틸리티 타입(Utility Types)을 제공함.</p>
<p>이들은 복잡한 타입을 <strong>짧고 직관적으로 표현</strong>하게 해 주며, <strong>타입 안전성과 생산성</strong>을 동시에 확보할 수 있음.</p>
<hr>
<h2 id="예시-1-readonlyt">예시 1: Readonly<T></h2>
<p><code>Readonly&lt;T&gt;</code>는 객체의 모든 프로퍼티를 <strong>읽기 전용(readonly)</strong>으로 변환함.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
}

const person: Readonly&lt;Person&gt; = {
  name: &quot;이정환&quot;,
  age: 27
};

person.name = &quot;&quot;; // ❌ 오류: 읽기 전용 프로퍼티</code></pre>
<hr>
<h2 id="예시-2-partialt">예시 2: Partial<T></h2>
<p><code>Partial&lt;T&gt;</code>는 객체의 모든 프로퍼티를 <strong>선택적(optional)</strong>으로 변환함.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
}

const person: Partial&lt;Person&gt; = {
  name: &quot;이정환&quot;
};
// age는 생략 가능</code></pre>
<hr>
<h2 id="유틸리티-타입의-핵심">유틸리티 타입의 핵심</h2>
<p>타입스크립트는 수십 가지 유틸리티 타입을 기본 제공함. 그중 자주 쓰이는 타입들부터 숙지하면 실무 적용에 큰 도움이 됨.</p>
<p>공식 문서:
👉 <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html">https://www.typescriptlang.org/docs/handbook/utility-types.html</a></p>
<hr>
<h2 id="학습-방향">학습 방향</h2>
<p>이번 섹션에서는 다음과 같은 방향으로 진행함:</p>
<ul>
<li><strong>맵드 타입 기반 유틸리티 타입</strong>: <code>Readonly&lt;T&gt;</code>, <code>Partial&lt;T&gt;</code> 등</li>
<li><strong>조건부 타입 기반 유틸리티 타입</strong>: <code>Exclude&lt;T, U&gt;</code>, <code>Extract&lt;T, U&gt;</code> 등</li>
<li><strong>직접 구현</strong>을 통해 유틸리티 타입의 원리와 작동 방식 이해</li>
</ul>
<hr>
<h2 id="🧾-마지막-요약">🧾 마지막 요약</h2>
<ul>
<li>유틸리티 타입은 타입 조작 기능의 집약체로, 복잡한 타입을 효율적으로 다룰 수 있게 함.</li>
<li>대표적인 타입으로 <code>Readonly</code>, <code>Partial</code>, <code>Exclude</code>, <code>ReturnType</code> 등이 있음.</li>
<li>다음 시간부터 실전 유틸리티 타입 구현을 병행하여 <strong>타입스크립트 고급 문법 숙련도</strong>를 높일 예정임.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션9. 조건부 타입- infer(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-infer2</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-infer2</guid>
            <pubDate>Tue, 15 Jul 2025 09:29:22 GMT</pubDate>
            <description><![CDATA[<h2 id="🧷-선요약">🧷 선요약</h2>
<ul>
<li><code>infer</code>는 조건부 타입 안에서 특정 타입을 추론할 수 있게 해주는 타입스크립트의 특수 문법임.</li>
<li><code>infer</code>는 보통 조건부 타입 내부에서 사용되며, 추론 가능한 타입이 있을 경우 해당 타입을 바탕으로 분기된 타입 결과를 생성함.</li>
<li>대표적인 활용 예시로는 <code>ReturnType&lt;T&gt;</code> 과 <code>PromiseUnpack&lt;T&gt;</code> 등의 유틸리티 타입 구현이 있음.</li>
</ul>
<hr>
<h2 id="infer로-returntypet-구현하기">infer로 ReturnType<T> 구현하기</h2>
<pre><code class="language-ts">type ReturnType&lt;T&gt; = T extends () =&gt; infer R ? R : never;</code></pre>
<p><code>infer R</code>은 함수 타입 <code>T</code>의 반환값을 추론해 <code>R</code>로 잡겠다는 의미임. 예시를 보자.</p>
<pre><code class="language-ts">type FuncA = () =&gt; string;
type FuncB = () =&gt; number;

type A = ReturnType&lt;FuncA&gt;; // string
type B = ReturnType&lt;FuncB&gt;; // number</code></pre>
<p>타입 변수 <code>T</code>에 함수 타입을 넣으면 해당 함수의 반환값 타입을 <code>infer R</code>이 추론하게 됨.<br>즉 <code>FuncA</code>는 <code>() =&gt; string</code> 타입이므로 <code>R</code>은 <code>string</code>이 되고, 따라서 <code>A</code>는 <code>string</code> 타입이 됨.</p>
<h3 id="추론-실패-시">추론 실패 시</h3>
<pre><code class="language-ts">type C = ReturnType&lt;number&gt;; // never</code></pre>
<p>이 경우에는 <code>number</code> 타입은 함수 타입이 아니므로 조건식을 만족하지 않음.<br>결과적으로 <code>ReturnType&lt;number&gt;</code>는 <code>never</code> 타입이 됨.</p>
<hr>
<h2 id="infer로-promise의-결과-타입-추출하기">infer로 Promise의 결과 타입 추출하기</h2>
<pre><code class="language-ts">type PromiseUnpack&lt;T&gt; = T extends Promise&lt;infer R&gt; ? R : never;</code></pre>
<p><code>PromiseUnpack</code>은 <code>Promise&lt;T&gt;</code> 타입으로부터 내부의 <code>T</code> 타입을 꺼내오는 유틸리티 타입임.</p>
<p>예시:</p>
<pre><code class="language-ts">type PromiseA = PromiseUnpack&lt;Promise&lt;number&gt;&gt;; // number
type PromiseB = PromiseUnpack&lt;Promise&lt;string&gt;&gt;; // string</code></pre>
<p><code>infer R</code>을 통해 <code>Promise&lt;number&gt;</code>는 <code>number</code> 타입이 추론되고, 최종적으로 <code>PromiseUnpack&lt;Promise&lt;number&gt;&gt;</code>는 <code>number</code>가 됨.</p>
<hr>
<h2 id="🧩-마지막-요약">🧩 마지막 요약</h2>
<ul>
<li><code>infer</code>는 조건부 타입 내에서 특정 타입을 <strong>추론</strong>할 때 사용함.</li>
<li>일반적으로 유틸리티 타입에서 많이 활용됨 (예: ReturnType, Parameters, PromiseUnpack 등).</li>
<li>조건식이 성립하지 않으면 <code>never</code> 타입으로 수렴됨.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션9. 조건부 타입- 분산적인 조건부 타입(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EB%B6%84%EC%82%B0%EC%A0%81%EC%9D%B8-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%851</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EB%B6%84%EC%82%B0%EC%A0%81%EC%9D%B8-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%851</guid>
            <pubDate>Tue, 15 Jul 2025 09:24:42 GMT</pubDate>
            <description><![CDATA[<h1 id="분산적인-조건부-타입">분산적인 조건부 타입</h1>
<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>조건부 타입에 유니온 타입을 넣으면 각 요소에 대해 조건이 개별로 평가되는 <strong>분산 조건부 타입</strong>이 작동함.</li>
<li>이를 이용해 <code>Exclude</code>, <code>Extract</code> 등 다양한 유틸리티 타입을 직접 구현 가능함.</li>
</ul>
<hr>
<h2 id="조건부-타입-복습">조건부 타입 복습</h2>
<pre><code class="language-ts">type StringNumberSwitch&lt;T&gt; = T extends number ? string : number;

let a: StringNumberSwitch&lt;number&gt;;  // string
let b: StringNumberSwitch&lt;string&gt;;  // number</code></pre>
<hr>
<h2 id="분산-조건부-타입의-등장">분산 조건부 타입의 등장</h2>
<pre><code class="language-ts">type StringNumberSwitch&lt;T&gt; = T extends number ? string : number;

let c: StringNumberSwitch&lt;number | string&gt;; 
// 결과: string | number</code></pre>
<h3 id="❓-왜-이런-결과가-나옴">❓ 왜 이런 결과가 나옴?</h3>
<ul>
<li>조건부 타입의 타입 변수에 <strong>Union 타입</strong>이 들어가면, 조건이 <strong>각 요소별로 분리</strong>되어 평가됨.</li>
<li>이를 <strong>분산 조건부 타입</strong>이라 함.</li>
</ul>
<h3 id="분산-과정">분산 과정:</h3>
<ol>
<li><p>타입 분해:</p>
<pre><code class="language-ts">StringNumberSwitch&lt;number&gt;     // string
StringNumberSwitch&lt;string&gt;     // number</code></pre>
</li>
<li><p>결과 결합:</p>
<pre><code class="language-ts">string | number</code></pre>
</li>
</ol>
<hr>
<h2 id="exclude-조건부-타입-구현">Exclude 조건부 타입 구현</h2>
<pre><code class="language-ts">type Exclude&lt;T, U&gt; = T extends U ? never : T;

type A = Exclude&lt;number | string | boolean, string&gt;; 
// 결과: number | boolean</code></pre>
<h3 id="계산-흐름">계산 흐름:</h3>
<ol>
<li><p>타입 분리:</p>
<pre><code class="language-ts">Exclude&lt;number, string&gt;   // number
Exclude&lt;string, string&gt;   // never
Exclude&lt;boolean, string&gt;  // boolean</code></pre>
</li>
<li><p>결과 결합:</p>
<pre><code class="language-ts">number | never | boolean → number | boolean</code></pre>
</li>
</ol>
<blockquote>
<p><code>never</code>는 공집합이므로 Union에서 자동 제거됨</p>
</blockquote>
<hr>
<h2 id="🧠-마지막-요약">🧠 마지막 요약</h2>
<ul>
<li>조건부 타입에 유니온을 전달하면 <strong>자동으로 분산 평가</strong>됨.</li>
<li>이를 활용하면 타입 연산에서 필터링, 매핑 같은 고급 기능을 구현할 수 있음.</li>
<li><code>Exclude&lt;T, U&gt;</code>는 T에서 U에 해당하는 타입만 제거함.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션9. 조건부 타입- 조건부 타입(0)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%850</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%989.-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%85-%EC%A1%B0%EA%B1%B4%EB%B6%80-%ED%83%80%EC%9E%850</guid>
            <pubDate>Tue, 15 Jul 2025 09:22:09 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<p>조건부 타입은 <code>extends</code>와 삼항 연산자(<code>? :</code>)를 활용해 타입을 상황에 따라 다르게 설정할 수 있게 해줌. 특히 제네릭과 함께 사용할 때 매우 강력하며, 값의 타입에 따라 반환 타입을 유연하게 조절할 수 있음. 타입스크립트의 타입 로직에 논리적 분기를 넣을 수 있다는 점이 핵심임.</p>
<hr>
<h2 id="1-조건부-타입-기본-문법">1. 조건부 타입 기본 문법</h2>
<pre><code class="language-ts">type A = number extends string ? number : string; 
// A → string</code></pre>
<p>number가 string의 서브타입인지 여부에 따라 결과가 달라짐. 위 예시는 false가 되어 A는 <code>string</code>이 됨.</p>
<pre><code class="language-ts">type ObjA = { a: number };
type ObjB = { a: number; b: number };

type B = ObjB extends ObjA ? number : string;
// B → number (ObjB는 ObjA의 슈퍼셋)</code></pre>
<hr>
<h2 id="2-제네릭-조건부-타입">2. 제네릭 조건부 타입</h2>
<pre><code class="language-ts">type StringNumberSwitch&lt;T&gt; = T extends number ? string : number;

let varA: StringNumberSwitch&lt;number&gt;; // string
let varB: StringNumberSwitch&lt;string&gt;; // number</code></pre>
<p>타입 변수 <code>T</code>가 number면 결과는 string, 아니면 number가 됨.</p>
<hr>
<h2 id="3-조건부-타입-실전-예제">3. 조건부 타입 실전 예제</h2>
<pre><code class="language-ts">function removeSpaces&lt;T&gt;(text: T): T extends string ? string : undefined {
  if (typeof text === &quot;string&quot;) {
    return text.replaceAll(&quot; &quot;, &quot;&quot;) as any;
  } else {
    return undefined as any;
  }
}</code></pre>
<ul>
<li><code>removeSpaces(&quot;hello world&quot;)</code> → string</li>
<li><code>removeSpaces(undefined)</code> → undefined</li>
</ul>
<p>하지만 위 방식은 <code>as any</code> 때문에 타입 안정성이 깨질 수 있음. 예를 들어 string이 아닌 값을 반환해도 타입 검사를 통과함.</p>
<hr>
<h2 id="4-함수-오버로딩으로-해결">4. 함수 오버로딩으로 해결</h2>
<pre><code class="language-ts">function removeSpaces&lt;T&gt;(text: T): T extends string ? string : undefined;
function removeSpaces(text: any) {
  if (typeof text === &quot;string&quot;) {
    return text.replaceAll(&quot; &quot;, &quot;&quot;);
  } else {
    return undefined;
  }
}

let result = removeSpaces(&quot;hi im winterlood&quot;); // string
let result2 = removeSpaces(undefined);         // undefined</code></pre>
<p>오버로딩을 사용하면 조건부 타입의 결과를 실제로 타입스크립트가 추론할 수 있게 되므로, <code>as any</code> 없이도 타입 안정성을 확보할 수 있음.</p>
<hr>
<h2 id="🔁-마지막-정리">🔁 마지막 정리</h2>
<ul>
<li>조건부 타입은 타입에 <code>if-else</code> 같은 논리를 넣을 수 있게 해주는 기능임.</li>
<li><code>A extends B ? C : D</code> 형식으로 작성하며, 특히 제네릭과 함께 강력함.</li>
<li><code>as any</code>보다는 <strong>함수 오버로딩</strong>을 통한 추론이 더 안전하고 실용적임.</li>
<li>실제 사용 예시로 입력 타입에 따라 다른 반환 타입을 가질 수 있는 함수를 구현할 수 있음.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-
템플릿 리터럴 타입(4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A6%AC%ED%84%B0%EB%9F%B4-%ED%83%80%EC%9E%854</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A6%AC%ED%84%B0%EB%9F%B4-%ED%83%80%EC%9E%854</guid>
            <pubDate>Tue, 15 Jul 2025 09:19:22 GMT</pubDate>
            <description><![CDATA[<h1 id="템플릿-리터럴-타입">템플릿 리터럴 타입</h1>
<h2 id="선요약">선요약</h2>
<p>템플릿 리터럴 타입은 문자열 패턴을 조합해 새로운 문자열 리터럴 유니온 타입을 만드는 타입스크립트의 타입 조작 기능임. 여러 문자열 유니온 타입을 조합할 때 반복적인 수작업 없이 효율적으로 조합 가능함.</p>
<hr>
<h2 id="템플릿-리터럴-타입이란">템플릿 리터럴 타입이란?</h2>
<p>템플릿 리터럴 타입은 타입 조작 기능 중 가장 단순한 기능으로, 템플릿 리터럴 문법을 이용해 특정 <strong>패턴을 갖는 문자열 타입</strong>을 만드는 기능임.</p>
<pre><code class="language-ts">type Color = &quot;red&quot; | &quot;black&quot; | &quot;green&quot;;
type Animal = &quot;dog&quot; | &quot;cat&quot; | &quot;chicken&quot;;</code></pre>
<p>위와 같은 코드에서 아래와 같이 모든 조합의 문자열 리터럴 타입을 만들고 싶다고 가정함:</p>
<pre><code class="language-ts">type ColoredAnimal =
  | &quot;red-dog&quot;
  | &quot;red-cat&quot;
  | &quot;red-chicken&quot;
  | &quot;black-dog&quot;
  | &quot;black-cat&quot;
  | &quot;black-chicken&quot;
  | &quot;green-dog&quot;
  | &quot;green-cat&quot;
  | &quot;green-chicken&quot;;</code></pre>
<p>위처럼 수작업으로 만들면 타입이 늘어날수록 불편하고 오류 가능성도 커짐. 이럴 때 템플릿 리터럴 타입을 쓰면 다음처럼 간단하게 표현 가능함:</p>
<pre><code class="language-ts">type ColoredAnimal = `${Color}-${Animal}`;</code></pre>
<ul>
<li><code>Color</code>의 모든 값과 <code>Animal</code>의 모든 값을 문자열로 조합한 유니온 타입이 자동으로 생성됨</li>
<li><code>${}</code> 안에는 타입 변수 또는 타입 이름을 넣을 수 있음</li>
</ul>
<hr>
<h2 id="예시-응용">예시 응용</h2>
<h3 id="특정-접두어-붙이기">특정 접두어 붙이기</h3>
<pre><code class="language-ts">type Prefix = &quot;pre&quot;;
type Word = &quot;load&quot; | &quot;view&quot;;

type PrefixedWord = `${Prefix}_${Word}`;
// &quot;pre_load&quot; | &quot;pre_view&quot;</code></pre>
<h3 id="이벤트-핸들러-이름-만들기">이벤트 핸들러 이름 만들기</h3>
<pre><code class="language-ts">type Event = &quot;click&quot; | &quot;hover&quot;;
type HandlerName = `on${Capitalize&lt;Event&gt;}`;
// &quot;onClick&quot; | &quot;onHover&quot;</code></pre>
<ul>
<li><code>Capitalize&lt;T&gt;</code>: 첫 글자를 대문자로 바꿔줌</li>
<li><code>Uncapitalize&lt;T&gt;</code>: 첫 글자를 소문자로 바꿔줌</li>
<li><code>Uppercase&lt;T&gt;</code>, <code>Lowercase&lt;T&gt;</code>: 대문자화, 소문자화</li>
</ul>
<hr>
<h2 id="주의사항">주의사항</h2>
<ul>
<li>템플릿 리터럴 타입은 <strong>컴파일 타임</strong>에 조합됨 → 런타임에는 영향을 주지 않음</li>
<li><code>${}</code> 내부에 값(value)을 넣는 것이 아니라 <strong>타입</strong>을 넣는 것임</li>
<li>리터럴 유니온 타입이 너무 많아지면 타입 추론이 느려질 수 있음</li>
</ul>
<hr>
<h2 id="마지막-요약">마지막 요약</h2>
<p>템플릿 리터럴 타입은 문자열 리터럴 조합을 자동화하여, 복잡한 유니온 타입을 간결하고 안전하게 생성할 수 있게 해주는 타입스크립트의 문법임. 반복적인 문자열 타입 정의를 줄이고, 패턴 기반의 타입 생성이 필요한 상황에서 특히 유용함.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-맵드 타입(3)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EB%A7%B5%EB%93%9C-%ED%83%80%EC%9E%853</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EB%A7%B5%EB%93%9C-%ED%83%80%EC%9E%853</guid>
            <pubDate>Tue, 15 Jul 2025 09:16:52 GMT</pubDate>
            <description><![CDATA[<h1 id="맵드-타입-mapped-types">맵드 타입 (Mapped Types)</h1>
<h2 id="요약">요약</h2>
<p>맵드 타입(mapped type)은 기존 객체 타입을 기반으로 <strong>새로운 객체 타입을 유연하게 생성</strong>할 수 있는 타입스크립트의 기능임. <code>keyof</code>, 인덱스드 엑세스 타입 등과 결합해 중복 없이 코드를 간결하게 유지할 수 있음.</p>
<hr>
<h2 id="기본-예시">기본 예시</h2>
<pre><code class="language-ts">interface User {
  id: number;
  name: string;
  age: number;
}

// 수정 가능한 필드를 선택적으로 만들고 싶을 때
type PartialUser = {
  [key in &quot;id&quot; | &quot;name&quot; | &quot;age&quot;]?: User[key];
};</code></pre>
<p>이 맵드 타입은 다음과 같은 결과 타입이 됨:</p>
<pre><code class="language-ts">{
  id?: number;
  name?: string;
  age?: number;
}</code></pre>
<hr>
<h2 id="keyof와-결합">&#39;keyof`와 결합</h2>
<pre><code class="language-ts">type PartialUser = {
  [key in keyof User]?: User[key];
};</code></pre>
<p><code>keyof User</code>는 <code>&quot;id&quot; | &quot;name&quot; | &quot;age&quot;</code>와 같기 때문에 위와 동일한 결과 타입이 생성됨.</p>
<hr>
<h2 id="읽기-전용-타입-만들기">읽기 전용 타입 만들기</h2>
<pre><code class="language-ts">type ReadonlyUser = {
  readonly [key in keyof User]: User[key];
};</code></pre>
<p>→ 모든 프로퍼티를 <code>readonly</code>로 변환한 새 타입이 생성됨.</p>
<hr>
<h2 id="활용-예시">활용 예시</h2>
<p>기존 타입을 기반으로:</p>
<ul>
<li>모든 프로퍼티를 <strong>선택적(optional)</strong> 으로 만들거나,</li>
<li>모든 프로퍼티를 <strong>읽기 전용(readonly)</strong> 으로 만들거나,</li>
<li>특정 키만 골라서 <strong>부분적으로 정의된 타입</strong>을 만들 수 있음.</li>
</ul>
<p>이러한 방식으로 유지보수와 확장성이 매우 뛰어난 타입 정의가 가능해짐.</p>
<hr>
<h2 id="요약-정리">요약 정리</h2>
<ul>
<li>맵드 타입은 반복되는 타입 정의를 <strong>자동화</strong>함</li>
<li><code>keyof</code>, 인덱스드 엑세스 타입 등과 함께 사용하면 <strong>강력한 타입 변환기</strong>가 됨</li>
<li><strong>실무에서 자주 사용</strong>되는 패턴임 (<code>Partial</code>, <code>Readonly</code>, <code>Pick</code>, <code>Record</code> 등이 전부 맵드 타입으로 구현되어 있음)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-keyof & typeof 연산자(2)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-keyof-typeof-%EC%97%B0%EC%82%B0%EC%9E%902</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-keyof-typeof-%EC%97%B0%EC%82%B0%EC%9E%902</guid>
            <pubDate>Tue, 15 Jul 2025 08:29:26 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<ul>
<li><code>keyof</code> 연산자는 객체 타입에서 모든 프로퍼티 키를 문자열 리터럴 유니온 타입으로 추출함.</li>
<li>수동으로 <code>&quot;name&quot; | &quot;age&quot;</code> 같은 키 목록을 명시하지 않고, 타입에서 자동 추출할 수 있어 유지보수에 용이함.</li>
<li><code>keyof</code>는 타입에만 적용 가능하며, 값에는 사용할 수 없음.</li>
<li><code>typeof</code>와 함께 사용하면 실제 변수의 타입 구조로부터 키를 추출하는 것도 가능함.</li>
</ul>
<hr>
<h1 id="keyof-연산자">Keyof 연산자</h1>
<p><code>keyof</code> 연산자는 객체 타입으로부터 프로퍼티의 모든 key들을 String Literal Union 타입으로 추출하는 연산자임.</p>
<p>다음은 <code>keyof</code> 연산자를 사용하는 예시임.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
}

function getPropertyKey(person: Person, key: &quot;name&quot; | &quot;age&quot;) {
  return person[key];
}</code></pre>
<p>이렇게 키를 명시하면 Person 타입이 바뀔 때마다 <code>&quot;name&quot; | &quot;age&quot;</code>를 함께 바꿔줘야 하는 번거로움이 생김.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
  location: string; // 추가됨
}

function getPropertyKey(person: Person, key: &quot;name&quot; | &quot;age&quot; | &quot;location&quot;) {
  return person[key];
}</code></pre>
<p>이럴 때 <code>keyof</code> 연산자를 쓰면 유지보수가 쉬워짐.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
  location: string;
}

function getPropertyKey(person: Person, key: keyof Person) {
  return person[key];
}</code></pre>
<p><code>keyof Person</code>의 결과는 <code>&quot;name&quot; | &quot;age&quot; | &quot;location&quot;</code>이 됨.</p>
<p>주의할 점: <code>keyof</code>는 <strong>값</strong>이 아닌 <strong>타입</strong>에만 적용할 수 있음.</p>
<pre><code class="language-ts">function getPropertyKey(person: Person, key: keyof person) { // ❌ 오류
  return person[key];
}</code></pre>
<hr>
<h1 id="typeof와-keyof-함께-사용하기">Typeof와 Keyof 함께 사용하기</h1>
<p><code>typeof</code> 연산자는 값을 기반으로 타입을 추론할 수 있게 해주는 타입스크립트의 기능임.</p>
<pre><code class="language-ts">const person = {
  name: &quot;이정환&quot;,
  age: 27,
  location: &quot;서울&quot;
};

type Person = typeof person;
// Person 타입은 { name: string; age: number; location: string }이 됨</code></pre>
<p>이걸 활용해 <code>keyof</code>와 함께 쓰면 다음과 같이 사용 가능함.</p>
<pre><code class="language-ts">function getPropertyKey(person: typeof person, key: keyof typeof person) {
  return person[key];
}</code></pre>
<p>이렇게 하면 <strong>변수의 구조에 따라 자동으로 키 타입이 추출되므로</strong> 더 안정적이고 유연한 타입 선언이 가능함.</p>
<hr>
<h1 id="마지막-요약">마지막 요약</h1>
<ul>
<li><code>keyof</code>는 타입으로부터 프로퍼티 키들을 추출해 유니온 타입으로 만듦.</li>
<li><code>typeof</code>는 변수로부터 타입을 추론함.</li>
<li>둘을 함께 사용하면 유지보수와 타입 안정성을 모두 챙길 수 있음.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-인덱스드 엑세스 타입(1)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EB%93%9C-%EC%97%91%EC%84%B8%EC%8A%A4-%ED%83%80%EC%9E%851</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%EC%9D%B8%EB%8D%B1%EC%8A%A4%EB%93%9C-%EC%97%91%EC%84%B8%EC%8A%A4-%ED%83%80%EC%9E%851</guid>
            <pubDate>Tue, 15 Jul 2025 08:25:31 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<ul>
<li>인덱스드 엑세스 타입은 객체, 배열, 튜플에서 특정 속성의 타입을 추출할 때 사용함.</li>
<li>문법은 <code>타입명[&quot;프로퍼티명&quot;]</code> 또는 <code>타입명[숫자]</code> 형태로 사용함.</li>
<li>객체 속성 변경 시 매개변수 타입도 자동 반영 가능함.</li>
<li>유효하지 않은 인덱스 사용 시 오류 발생함.</li>
<li>배열/튜플의 요소 타입을 추출하여 재사용하거나 제네릭화할 수 있음.</li>
</ul>
<hr>
<h1 id="인덱스드-엑세스-타입">인덱스드 엑세스 타입</h1>
<p>인덱스드 엑세스 타입은 인덱스를 이용해 다른 타입내의 특정 프로퍼티의 타입을 추출하는 타입임. 객체, 배열, 튜플에 모두 사용할 수 있음.</p>
<h2 id="객체-프로퍼티의-타입-추출">객체 프로퍼티의 타입 추출</h2>
<pre><code class="language-ts">interface Post {
  title: string;
  content: string;
  author: {
    id: number;
    name: string;
    age: number;
  };
}

function printAuthorInfo(author: Post[&quot;author&quot;]) {
  console.log(`${author.id} - ${author.name}`);
}</code></pre>
<ul>
<li><code>Post[&quot;author&quot;]</code>는 <code>Post</code> 타입에서 <code>author</code> 프로퍼티의 타입을 추출함.</li>
<li>인덱스는 <strong>문자열 리터럴 타입</strong>만 가능하며, 변수 사용은 불가함.</li>
</ul>
<pre><code class="language-ts">const authorKey = &quot;author&quot;;
function printAuthorInfo(author: Post[authorKey]) { // ❌ 오류 발생
  console.log(`${author.id} - ${author.name}`);
}</code></pre>
<ul>
<li>존재하지 않는 프로퍼티에 접근하려고 하면 오류 발생함.</li>
</ul>
<p>중첩 접근도 가능함.</p>
<pre><code class="language-ts">function printAuthorInfo(authorId: Post[&quot;author&quot;][&quot;id&quot;]) {
  console.log(authorId);
}</code></pre>
<h2 id="배열-요소-타입-추출">배열 요소 타입 추출</h2>
<pre><code class="language-ts">type PostList = Post[];
const post: PostList[number] = {
  title: &quot;게시글 제목&quot;,
  content: &quot;게시글 본문&quot;,
  author: {
    id: 1,
    name: &quot;이정환&quot;,
    age: 27,
  },
};</code></pre>
<ul>
<li><code>PostList[number]</code>는 배열의 요소 타입을 추출함.</li>
<li><code>PostList[0]</code>처럼 숫자 리터럴을 써도 동일하게 동작함.</li>
</ul>
<h2 id="튜플의-요소-타입-추출">튜플의 요소 타입 추출</h2>
<pre><code class="language-ts">type Tup = [number, string, boolean];

type Tup0 = Tup[0]; // number
type Tup1 = Tup[1]; // string
type Tup2 = Tup[2]; // boolean
type Tup3 = Tup[number]; // number | string | boolean</code></pre>
<ul>
<li>튜플에 <code>number</code> 인덱스를 넣으면 모든 요소의 유니온 타입이 추출됨.</li>
</ul>
<hr>
<h1 id="요약">요약</h1>
<ul>
<li>인덱스드 엑세스 타입은 객체나 배열/튜플에서 타입을 추출하여 재사용할 때 유용함.</li>
<li>중복 정의를 피하고 타입 변화에 유연하게 대응할 수 있음.</li>
<li>배열 요소 타입은 <code>[number]</code>, 튜플은 <code>[숫자]</code> 또는 <code>[number]</code>로 유니온 처리됨.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션8. 타입 조작하기-타입 조작이란(0)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%EC%9D%B4%EB%9E%800</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%988.-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%ED%95%98%EA%B8%B0-%ED%83%80%EC%9E%85-%EC%A1%B0%EC%9E%91%EC%9D%B4%EB%9E%800</guid>
            <pubDate>Tue, 15 Jul 2025 08:21:00 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<p>타입스크립트에서 타입 조작이란 기존 타입(기본 타입, 인터페이스, 타입 별칭 등)을 상황에 따라 동적으로 변형하는 기능을 의미함. 주요 도구로는 인덱스드 엑세스 타입, keyof 타입, 맵드 타입, 템플릿 리터럴 타입 등이 있으며, 제네릭 또한 타입 조작의 일부로 볼 수 있음. 이 기능들은 실무에서 유용하게 사용되며, 코드의 재사용성과 유연성을 크게 향상시킴.</p>
<hr>
<h1 id="타입-조작이란">타입 조작이란</h1>
<p>타입을 조작한다는 것은 기존의 기본 타입이나 별칭, 인터페이스로 만들어진 타입들을 상황에 따라 유동적으로 다른 타입으로 변형하는 기능임. 이는 타입스크립트의 강력하고 독특한 기능 중 하나임.</p>
<p>이전에 배운 제네릭 또한 함수나 인터페이스, 타입 별칭, 클래스 등에 적용해서 상황에 따라 달라지는 타입을 정의할 수 있기 때문에 타입 조작 기능의 일종임. 다만 그 내용이 방대해 따로 분리해 학습했음.</p>
<p>타입스크립트는 제네릭 외에도 여러가지 타입 조작 기능을 제공함. 이번 섹션에서는 제네릭과 다음에 다룰 조건부 타입을 제외한 4가지 대표적 타입 조작 기능을 정리함:
<img src="https://velog.velcdn.com/images/infp_pro/post/26bb41ba-8a6c-4158-9c63-bfe7b17b7212/image.png" alt=""></p>
<hr>
<h2 id="1-인덱스드-엑세스-타입">1. 인덱스드 엑세스 타입</h2>
<p>객체, 배열, 튜플 등의 타입에서 특정 프로퍼티나 요소의 타입만 추출할 수 있게 함.<br>예시: <code>type NameType = User[&quot;name&quot;]</code> → User 타입의 name 프로퍼티 타입만 따로 추출함.
<img src="https://velog.velcdn.com/images/infp_pro/post/3b4d56d7-f8c6-4909-9a46-f12847d745c0/image.png" alt=""></p>
<hr>
<h2 id="2-keyof-타입">2. keyof 타입</h2>
<p>객체 타입 내의 프로퍼티 이름들을 문자열 리터럴 유니온 타입으로 추출함.<br>예시: <code>type UserKeys = keyof User</code> → &quot;name&quot; | &quot;age&quot; | &quot;email&quot; 같은 유니온 타입이 됨.
<img src="https://velog.velcdn.com/images/infp_pro/post/94637a22-4a23-4deb-858c-9de5a30650f4/image.png" alt=""></p>
<hr>
<h2 id="3-맵드-타입">3. 맵드 타입</h2>
<p>기존 객체 타입을 기반으로 새로운 객체 타입을 정의함. 자바스크립트의 map 함수와 유사한 역할을 함.<br>예시: 모든 프로퍼티를 optional 하게 바꾸는 타입을 정의할 수 있음.<br><code>type Partial&lt;T&gt; = { [P in keyof T]?: T[P] }</code>
<img src="https://velog.velcdn.com/images/infp_pro/post/c37f1fbc-38ea-4f0f-9fff-4538354baf6e/image.png" alt=""></p>
<hr>
<h2 id="4-템플릿-리터럴-타입">4. 템플릿 리터럴 타입</h2>
<p>기존 문자열 리터럴 타입을 기반으로 정해진 패턴의 문자열만 포함하는 타입을 만들 수 있음.<br>예시:<br><code>type Color = &quot;red&quot; | &quot;blue&quot;</code><br><code>type BrightColor = \</code>bright-${Color}`<code>→ &quot;bright-red&quot; | &quot;bright-blue&quot;</code>
<img src="blob:https://velog.io/2faee308-5fb2-42b7-983f-ee2af18ca924" alt="업로드중.."></p>
<hr>
<p>이러한 기능들은 단순한 문법 외에도, 실무에서 어떤 상황에 이 기능을 써야 효과적인지를 이해하는 것이 중요함. 각 기능들은 심플하지만 실전에서 자주 쓰일 수 있는 예제들과 함께 학습할 예정임.</p>
<hr>
<h1 id="요약">요약</h1>
<ul>
<li>타입 조작이란 기존 타입들을 변형하여 새로운 타입을 만들어내는 기능임.</li>
<li>대표적 조작 도구: 인덱스드 엑세스 타입, keyof, 맵드 타입, 템플릿 리터럴 타입.</li>
<li>제네릭도 타입 조작의 일종으로 간주함.</li>
<li>이런 기능들은 코드의 유연성, 재사용성, 안전성을 높이는데 매우 유용함.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-프로미스와 제네릭(6)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4%EC%99%80-%EC%A0%9C%EB%84%A4%EB%A6%AD6</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4%EC%99%80-%EC%A0%9C%EB%84%A4%EB%A6%AD6</guid>
            <pubDate>Tue, 15 Jul 2025 08:16:41 GMT</pubDate>
            <description><![CDATA[<h1 id="선요약">선요약</h1>
<ul>
<li><code>Promise&lt;T&gt;</code>는 제네릭 클래스로, <code>resolve</code>의 결과값 타입을 <code>T</code>로 설정할 수 있다.</li>
<li><code>reject</code>의 값은 타입을 지정할 수 없으며, 기본적으로 <code>unknown</code>이다.</li>
<li><code>then()</code> 메서드는 <code>resolve</code> 값을, <code>catch()</code> 메서드는 <code>reject</code> 값을 다룬다.</li>
<li>함수의 반환 타입으로 <code>Promise&lt;타입&gt;</code>을 명시하여 비동기 작업의 결과 타입을 선언할 수 있다.</li>
</ul>
<hr>
<h1 id="promise-사용하기">Promise 사용하기</h1>
<p><code>Promise</code>는 제네릭 클래스로 구현되어 있다. 따라서 새로운 <code>Promise</code>를 생성할 때 다음과 같이 타입 변수에 할당할 타입을 직접 설정해 주면 해당 타입이 바로 <code>resolve</code> 결과값의 타입이 됨.</p>
<pre><code class="language-ts">const promise = new Promise&lt;number&gt;((resolve, reject) =&gt; {
  setTimeout(() =&gt; {
    // 결과값 : 20
    resolve(20);
  }, 3000);
});

promise.then((response) =&gt; {
  // response는 number 타입
  console.log(response);
});

promise.catch((error) =&gt; {
  if (typeof error === &quot;string&quot;) {
    console.log(error);
  }
});</code></pre>
<blockquote>
<p>❗ <code>reject</code> 함수에 전달된 값의 타입은 지정할 수 없고, 타입스크립트에서는 기본적으로 <code>unknown</code>으로 처리되므로, <code>catch</code>에서 타입 좁히기를 통해 안전하게 다뤄야 함.</p>
</blockquote>
<h2 id="함수에서-promise-반환">함수에서 Promise 반환</h2>
<p>어떤 함수가 <code>Promise</code> 객체를 반환한다면 함수의 반환 타입으로 <code>Promise&lt;타입&gt;</code>을 지정해야 함.</p>
<pre><code class="language-ts">function fetchPost() {
  return new Promise&lt;Post&gt;((resolve, reject) =&gt; {
    setTimeout(() =&gt; {
      resolve({
        id: 1,
        title: &quot;게시글 제목&quot;,
        content: &quot;게시글 본문&quot;,
      });
    }, 3000);
  });
}</code></pre>
<p>또는 더 명확하게 반환 타입을 다음과 같이 직접 명시해도 됨.</p>
<pre><code class="language-ts">function fetchPost(): Promise&lt;Post&gt; {
  return new Promise((resolve, reject) =&gt; {
    setTimeout(() =&gt; {
      resolve({
        id: 1,
        title: &quot;게시글 제목&quot;,
        content: &quot;게시글 본문&quot;,
      });
    }, 3000);
  });
}</code></pre>
<hr>
<h1 id="요약">요약</h1>
<ul>
<li><code>Promise&lt;T&gt;</code>는 비동기 작업의 성공 결과를 <code>T</code>로 선언할 수 있도록 해주는 제네릭 클래스이다.</li>
<li><code>reject()</code> 결과값은 <code>unknown</code>으로 취급되므로 타입 확인이 필요하다.</li>
<li>함수 반환 타입으로 <code>Promise&lt;타입&gt;</code>을 사용하면 타입 안정성이 높아진다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-제네릭 클래스(5)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%81%B4%EB%9E%98%EC%8A%A45</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%81%B4%EB%9E%98%EC%8A%A45</guid>
            <pubDate>Tue, 15 Jul 2025 08:12:38 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-제네릭이-없는-클래스">✅ 제네릭이 없는 클래스</h2>
<pre><code class="language-ts">class NumberList {
  constructor(private list: number[]) {}

  push(data: number) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

const numberList = new NumberList([1, 2, 3]);</code></pre>
<h2 id="❌-비효율적인-클래스-중복-정의">❌ 비효율적인 클래스 중복 정의</h2>
<p>StringList도 필요하다면 클래스 정의를 중복하게 됨.</p>
<pre><code class="language-ts">class StringList {
  constructor(private list: string[]) {}

  push(data: string) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

const numberList = new NumberList([1, 2, 3]);
const stringList = new StringList([&quot;1&quot;, &quot;2&quot;, &quot;3&quot;]);</code></pre>
<p>이렇게 되면 코드 중복이 심하고 유지보수도 어려워짐.</p>
<hr>
<h2 id="✅-제네릭-클래스로-개선하기">✅ 제네릭 클래스로 개선하기</h2>
<p>다음과 같이 제네릭을 적용해 다양한 타입의 리스트를 처리할 수 있는 범용 클래스를 만들 수 있음.</p>
<pre><code class="language-ts">class List&lt;T&gt; {
  constructor(private list: T[]) {}

  push(data: T) {
    this.list.push(data);
  }

  pop() {
    return this.list.pop();
  }

  print() {
    console.log(this.list);
  }
}

const numberList = new List([1, 2, 3]);
const stringList = new List([&quot;1&quot;, &quot;2&quot;]);</code></pre>
<h3 id="🎯-타입-명시적으로-지정하기">🎯 타입 명시적으로 지정하기</h3>
<p>타입 추론이 가능하지만 명시적으로 타입을 지정할 수도 있음.</p>
<pre><code class="language-ts">const numberList = new List&lt;number&gt;([1, 2, 3]);
const stringList = new List&lt;string&gt;([&quot;1&quot;, &quot;2&quot;]);</code></pre>
<p>이처럼 제네릭 클래스는 코드 중복을 줄이고 다양한 타입을 유연하게 처리할 수 있어 효율적.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript-섹션7. 제네릭-제네릭 인터페이스, 제네릭 타입 별칭(4)]]></title>
            <link>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD4</link>
            <guid>https://velog.io/@infp_pro/TypeScript-%EC%84%B9%EC%85%987.-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%A0%9C%EB%84%A4%EB%A6%AD-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%A0%9C%EB%84%A4%EB%A6%AD-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD4</guid>
            <pubDate>Tue, 15 Jul 2025 05:03:26 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-선요약">✅ 선요약</h2>
<ul>
<li>제네릭은 <strong>인터페이스, 타입 별칭, 함수</strong> 등에 적용 가능</li>
<li>제네릭 인터페이스는 <strong>다양한 타입을 유연하게 표현</strong>할 수 있음</li>
<li><strong>인덱스 시그니처</strong>, <strong>유니온 타입</strong>, <strong>조건 분기</strong>, <strong>함수 매개변수 제한</strong> 등 실용도가 높음</li>
<li>타입 추론은 불가하므로 <strong>반드시 타입 인자를 명시해야 함</strong></li>
</ul>
<hr>
<h2 id="📌-기본-제네릭-인터페이스">📌 기본 제네릭 인터페이스</h2>
<pre><code class="language-ts">interface KeyPair&lt;K, V&gt; {
  key: K;
  value: V;
}

let keyPair: KeyPair&lt;string, number&gt; = {
  key: &quot;key&quot;,
  value: 0,
};

let keyPair2: KeyPair&lt;boolean, string[]&gt; = {
  key: true,
  value: [&quot;1&quot;],
};</code></pre>
<hr>
<h2 id="📌-인덱스-시그니처--제네릭">📌 인덱스 시그니처 + 제네릭</h2>
<pre><code class="language-ts">interface Map&lt;V&gt; {
  [key: string]: V;
}

let stringMap: Map&lt;string&gt; = {
  key: &quot;value&quot;,
};

let booleanMap: Map&lt;boolean&gt; = {
  key: true,
};</code></pre>
<hr>
<h2 id="📌-제네릭-타입-별칭">📌 제네릭 타입 별칭</h2>
<pre><code class="language-ts">type Map2&lt;V&gt; = {
  [key: string]: V;
};

let stringMap2: Map2&lt;string&gt; = {
  key: &quot;string&quot;,
};</code></pre>
<hr>
<h2 id="✅-제네릭-인터페이스-활용-예">✅ 제네릭 인터페이스 활용 예</h2>
<h3 id="타입-정의">타입 정의</h3>
<pre><code class="language-ts">interface Student {
  type: &quot;student&quot;;
  school: string;
}

interface Developer {
  type: &quot;developer&quot;;
  skill: string;
}</code></pre>
<hr>
<h3 id="제네릭-적용-전">제네릭 적용 전</h3>
<pre><code class="language-ts">interface User {
  name: string;
  profile: Student | Developer;
}

function goToSchool(user: User) {
  if (user.profile.type !== &quot;student&quot;) {
    console.log(&quot;잘 못 오셨습니다&quot;);
    return;
  }

  const school = user.profile.school;
  console.log(`${school}로 등교 완료`);
}</code></pre>
<hr>
<h3 id="제네릭-적용-후">제네릭 적용 후</h3>
<pre><code class="language-ts">interface User&lt;T&gt; {
  name: string;
  profile: T;
}

function goToSchool(user: User&lt;Student&gt;) {
  const school = user.profile.school;
  console.log(`${school}로 등교 완료`);
}

const developerUser: User&lt;Developer&gt; = {
  name: &quot;이정환&quot;,
  profile: {
    type: &quot;developer&quot;,
    skill: &quot;TypeScript&quot;,
  },
};

const studentUser: User&lt;Student&gt; = {
  name: &quot;홍길동&quot;,
  profile: {
    type: &quot;student&quot;,
    school: &quot;가톨릭대학교&quot;,
  },
};</code></pre>
<hr>
<h2 id="✅-마무리">✅ 마무리</h2>
<p>제네릭 인터페이스는 객체 설계 시<br><strong>다양한 타입을 유연하고 안전하게 다룰 수 있게 해주는 도구</strong>다.<br>함수, 타입 별칭, 조건 분기, 인덱스 구조 등과 조합하여 쓰면 매우 강력하다.</p>
]]></description>
        </item>
    </channel>
</rss>