<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>snow-jun-0.log</title>
        <link>https://velog.io/</link>
        <description>Hard Trying</description>
        <lastBuildDate>Mon, 02 Mar 2026 15:50:12 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>snow-jun-0.log</title>
            <url>https://velog.velcdn.com/images/snow-jun-0/profile/ab80db3f-6fce-4162-870f-fe8ea11efbf9/social_profile.gif</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. snow-jun-0.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/snow-jun-0" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[.]]></title>
            <link>https://velog.io/@snow-jun-0/49vu6pp0</link>
            <guid>https://velog.io/@snow-jun-0/49vu6pp0</guid>
            <pubDate>Mon, 02 Mar 2026 15:50:12 GMT</pubDate>
            <description><![CDATA[<h2 id="예상-질문31순위">예상 질문3(1순위)</h2>
<p>자기 소개 및 지원 동기를 말해주세요</p>
<blockquote>
<p>&quot;
&quot;안녕하세요, &#39;기록으로 성장한는&#39; 개발자, 웹 파트 지원자, 우준영입니다.</p>
</blockquote>
<p>저는 군 복무 중 노베이스 상태에서 시작해, 매일 알고리즘 문제를 풀며 백준 실버 1을 달성한 끈기를 가지고 있습니다. 단순히 문제를 푸는 것에 그치지 않고, 해결 과정을 Velog에 체계적으로 기록하며 <strong>&#39;모르는 것을 나의 것으로 만드는 학습 매커니즘&#39;</strong>을 구축했습니다.</p>
<p>이제는 혼자만의 기록을 넘어, UMC에서 팀원들과 함께 실제 유저가 사용하는 서비스를 만들고 싶습니다. 끝까지 포기없이 10기 활동을 완주하겠습니다. &quot;</p>
<p>핵심은 기록으로 성장하는 개발자
모르는 것을 나의 것으로 만드는 학습 매커니즘을 구축
이제는 혼자만의 기록을 넘어, UMC에서 팀원들과 함께</p>
<h2 id="예상-질문52순위">예상 질문5(2순위)</h2>
<p>협업할 때 갈등이 생긴다면 어떻게 해결하실 건가요?</p>
<p>갈등이 생기면 감정보다는 객관적인 데이터에 집중하며, 제 개인의 의견 보다, 우리 팀 서비스의 &#39;완성도&#39; 라는 목표를 항상 최우선으로 두겠습니다. 
&quot;저는 감정보다는 &#39;데이터&#39;를 믿고, 제 고집보다는 &#39;팀의 목표&#39;를 믿는 개발자가 되겠습니다.&quot;</p>
<h2 id="예상-질문-1-3순위">예상 질문 1 (3순위)</h2>
<p>React를 선택한 이유는 컴포넌트 기반의 구조적 설계가 주는 효율성 때문입니다. 여기서 컴포넌트 기반의 구조적 설계가 주는 효율성은 무슨 의미인가요 ? </p>
<blockquote>
<p>컴포넌트 기반의 구조적 설계는 웹페이지를 하나의 통으로 만드는 것이 아니라, <strong>&#39;독립적인 작은 단위(Component)&#39;</strong>로 쪼개서 조립하듯 개발하는 방식입니다. 예를 들어 헤더, 버튼, 입력창 등을 각각 하나의 부품으로 만드는 것을 말합니다.</p>
</blockquote>
<blockquote>
<p>효율적인 면에서는 재사용성과 독립성, 유지보수의 용이성이 있습니다. 한번 잘 만든 컴포넌트를 재활용 한다든가, 각 기능이 컴포넌트 단위로 분리되어 있어, 코드가 섞이지 않고 깔금하며, ui에 수정사항이 생기면 해당 컴포넌트 하나만 수정하면 되는 부분입니다. </p>
</blockquote>
<h2 id="예상-질문4">예상 질문4</h2>
<p>가장 기억에 남는 프로젝트는 무엇인가요?</p>
<blockquote>
<p>아직 규모 있는 팀 프로젝트 경험은 없지만, 저는 &#39;백준 실버 1 달성&#39;을 위한 자기주도적 학습 프로젝트가 가장 기억에 남습니다.</p>
</blockquote>
<p>단순히 문제를 푸는 것을 넘어, 특정 알고리즘의 원리를 파악하고 이를 Velog에 체계적으로 문서화하는 과정을 하나의 프로젝트라고 생각하고 진행했습니다. 특히 복잡한 골드 수준의 문제를 만났을 때, 문제를 작은 단위로 쪼개고 논리적 오류를 수정해 나가는 과정은 프런트엔드에서 컴포넌트를 설계하고 디버깅하는 과정과 매우 닮아 있다고 느꼈습니다.</p>
<p>이 과정을 통해 &#39;모르는 것을 내 것으로 만드는 메커니즘&#39;을 익혔고, 이제는 이 개인적인 성취를 넘어 UMC에서 팀원들과 함께 실제 유저가 사용하는 서비스를 만드는 진짜 프로젝트에 도전하고 싶습니다.&quot;</p>
<h2 id="예상-질문6">예상 질문6</h2>
<p>Umc는 한학기+방학동안 이루어지며 3학점 짜리 전공 급시간 할애가 필요한 활동이다. 자신의 스케줄에 지장이 갈수 있는데 괜찮을지?</p>
<p>&quot;네, UMC 활동이 전공 수업 이상의 몰입이 필요한 과정이라는 점을 잘 알고 있으며, 이미 충분한 시간과 노력을 쏟을 준비가 되어 있습니다.</p>
<p>저는 어떤 가치 있는 성과를 얻기 위해서는 그에 걸맞은 &#39;절대적인 시간&#39;이 필요하다는 것을 경험으로 배운 사람입니다. 실제로 군 복무 중에도 매일 루틴을 지키며 백준 실버 1을 달성했고, 그 과정을 하나하나 Velog에 기록하며 스스로 학습 메커니즘을 구축해 왔습니다.</p>
<p>UMC는 제가 가장 원했던 React 기반의 실무 협업을 배우는 기회인 만큼, 제 최우선 순위는 UMC가 될 것입니다. 단순히 시간을 때우는 것이 아니라, 팀원들에게 피해가 가지 않도록 책임감 있게 일정을 관리하고, 기술적 난관 앞에서도 끝까지 몰입하여 결과물을 만들어내겠습니다.&quot;</p>
<h2 id="예상-질문-7">예상 질문 7</h2>
<p>마지막으로 할말(어필)</p>
<p>&quot;마지막으로 제가 꼭 UMC 10기여야만 하는 이유를 말씀드리고 싶습니다.</p>
<p>많은 개발 동아리가 있지만, 이론에 그치지 않고 <strong>&#39;실제 유저가 사용하는 서비스 런칭&#39;</strong>이라는 명확한 목표를 향해 6개월간 장기적으로 몰입하는 곳은 UMC가 유일하다고 생각합니다. 저는 그동안 혼자 공부하며 Velog에 기록해온 지식들이 실제 프로젝트에서 어떻게 생명력을 얻는지 너무나 확인하고 싶습니다.</p>
<p>저는 이미 군 복무 중에도 매일 루틴을 지키며 백준 실버 1을 달성할 만큼, 한 번 목표한 것은 끝까지 완수하는 끈기를 증명해 왔습니다. UMC 활동을 제 최우선 순위에 두고, 제가 가진 기록의 습관을 통해 팀의 지식 자산을 체계화하는 데 기여하겠습니다.</p>
<p>단순히 &#39;배우는 학생&#39;이 아니라, 프로젝트의 마지막 순간까지 팀의 결과물을 실체화하는 <strong>&#39;가장 든든한 프런트엔드 개발자&#39;</strong>가 되겠습니다. 꼭 함께 활동하고 싶습니다. 감사합니다! </p>
<h2 id="예상-질문2">예상 질문2</h2>
<p>React의 상태 관리와 훅(Hook)의 원리를 누구보다 빠르게 흡수하겠습니다. 라고 하셨는데 설명해주실 수 있으신가요?</p>
<blockquote>
<p>&quot;먼저 상태 관리는 컴포넌트 내부의 동적인 데이터를 관리하는 것입니다. 상태가 변하면 React가 UI를 자동으로 다시 그려주기 때문에, 개발자는 데이터의 변화에만 집중할 수 있어 코드의 일관성을 유지하기 좋습니다.</p>
</blockquote>
<blockquote>
<p><strong>훅(Hook)</strong>은 이러한 상태 관리나 생명주기 기능을 함수형 컴포넌트에서 쉽게 사용할 수 있게 해주는 도구입니다. 복잡한 로직을 독립적인 함수로 분리할 수 있어 코드의 가독성을 높이고 로직의 재사용성을 극대화해 줍니다.&quot;</p>
</blockquote>
<h2 id="예상-질문-8">예상 질문 8</h2>
<p>만일 백앤드, 프론트앤드 중에 하나만 선택한다면? (기출 질문)</p>
<p>&quot;저는 망설임 없이 프런트엔드를 선택하겠습니다. 그 이유는 두 가지입니다.</p>
<p>첫째, 사용자의 피드백을 가장 빠르고 직접적으로 체감할 수 있는 분야이기 때문입니다. 저는 제가 만든 결과물이 유저에게 어떤 가치를 주는지 시각적으로 확인하고, 그 반응을 바탕으로 서비스를 개선해 나가는 과정에서 큰 보람을 느낍니다.</p>
<p>둘째, 복잡한 로직을 직관적인 화면으로 설계하는 &#39;번역가&#39;의 역할이 저의 성향과 잘 맞기 때문입니다. 백엔드에서 처리된 방대한 데이터를 유저가 가장 편하게 사용할 수 있도록 컴포넌트 단위로 구조화하고, 상태 관리와 훅을 이용해 역동적인 화면을 구현하는 과정이 매우 매력적입니다.</p>
<p>물론 백엔드와의 협업을 위해 데이터 구조에 대한 이해도 꾸준히 넓혀가겠지만, 서비스의 첫인상을 결정짓고 유저의 경험을 직접 설계하는 프런트엔드 개발자로서의 전문성을 쌓는 것이 저의 확실한 목표입니다.&quot;</p>
<h2 id="어떤-개발자가-되고-싶은지">어떤 개발자가 되고 싶은지?</h2>
<p>가끔 어플리케이션을 사용하다보면 기능이 너무 복잡하거나 헷갈렸던 경험이 있습니다. 이에 저는 사용자가 쉽게 누구나 직관적으로 이해할 수 있도록 편의성을 가장 먼저 생각하는 프론트엔드 개발자가 되고 싶습니다.</p>
<h2 id="궁금한-점">궁금한 점?</h2>
<p>사실 UMC에 붙고 싶어서 블로그나, 인스타그램, 사이트를 찾아가보면서 많은 정보를 얻었습니다. 해서 궁금한 점은 딱히 없습니다!</p>
<p>만들고 싶은 서비스 (개발 동아리 면접용, 회사라면 패스)</p>
<h2 id="날-뽑아야-하는-이유--지원-동기">날 뽑아야 하는 이유 (&amp; 지원 동기)</h2>
<p>&quot;저를 뽑아야 하는 이유는 <strong>&#39;성장의 메커니즘을 스스로 구축한 지원자&#39;</strong>이기 때문입니다.</p>
<p>저는 군 복무 중에도 매일 루틴을 지키며 백준 실버 1을 달성했습니다. 단순히 문제를 푸는 것에 그치지 않고, 그 고민의 과정을 Velog에 꼼꼼히 기록하며 모르는 것을 내 것으로 만드는 법을 익혔습니다. React는 이제 시작이지만, 이런 탄탄한 기본기와 끈기를 바탕으로 상태 관리나 훅 같은 핵심 원리를 누구보다 빠르게 흡수할 자신이 있습니다.</p>
<p>또한, 저는 기록을 좋아하는 만큼 팀의 지식 자산을 체계화하는 데 진심입니다. 혼자 공부할 때 느꼈던 협업과 코드 리뷰에 대한 갈증을 UMC에서 해소하고 싶습니다. 제가 가진 꼼꼼한 기록 습관을 팀 프로젝트의 문서화와 컨벤션에 녹여내어, 저 개인의 성장뿐만 아니라 우리 팀 전체의 생산성을 높이는 든든한 프런트엔드 개발자가 되겠습니다. 6개월간의 장기 활동을 최우선 순위로 두고, 서비스 런칭까지 끝까지 책임지고 완수하겠습니다.&quot;</p>
<h2 id="목표-꼭-얻어가고-싶은-것">목표 (꼭 얻어가고 싶은 것)</h2>
<p>&quot;저는 UMC 활동을 통해 단순히 React 기술을 익히는 것을 넘어, <strong>&#39;팀 전체의 생산성에 기여하는 협업 메커니즘&#39;</strong>을 경험하고 싶습니다.</p>
<p>그동안 혼자 공부하며 백준 실버 1을 달성하고 그 과정을 Velog에 기록해왔지만, 실제 유저가 사용하는 서비스를 만드는 과정에서의 코드 리뷰나 협업 컨벤션에 대한 갈증이 컸습니다.</p>
<p>이번 활동을 통해 제가 가진 꼼꼼한 기록 습관을 팀 프로젝트의 문서화에 녹여내어, 팀원들이 제 코드를 보고 의도를 바로 파악할 수 있는 <strong>&#39;읽기 좋은 코드&#39;</strong>를 짜는 능력을 얻고 싶습니다. 또한, 기획부터 런칭까지의 전체 사이클을 경험하며, 기술적 난관 앞에서도 끝까지 몰입하여 팀의 결과물을 실체화하는 단단한 프런트엔드 개발자로 성장하는 것이 제 가장 큰 목표입니다.&quot;</p>
<h2 id="해당-직무를-선택한-이유">해당 직무를 선택한 이유</h2>
<p>&quot;제가 프론트엔드 중에서도 웹을 선택한 이유는 <strong>&#39;가장 낮은 문턱으로 가장 많은 사용자에게 가치를 전달할 수 있는 플랫폼&#39;</strong>이기 때문입니다.</p>
<p>앱처럼 설치 과정 없이 주소창에 URL 하나만 입력하면 즉시 서비스에 접속할 수 있다는 압도적인 접근성에 매력을 느꼈습니다. 저는 제가 만든 결과물을 누구나 쉽게 경험하고 피드백을 주는 과정을 즐기는데, 웹은 그런 소통의 속도가 가장 빠른 분야라고 생각합니다.</p>
<p>특히 React를 공부하며 웹이 단순한 문서 페이지를 넘어, 컴포넌트 기반의 구조적 설계를 통해 복잡한 애플리케이션 수준의 퍼포먼스를 낼 수 있다는 점에 확신을 얻었습니다. 제가 백준 실버 1을 달성하며 길러온 논리적 사고력을 바탕으로, 브라우저라는 환경 제약 안에서 최적의 상태 관리와 훅 활용을 통해 유저에게 끊김 없는 웹 경험을 제공하는 개발자가 되고 싶어 지원했습니다.&quot;<br>프런트엔드 개발은  백엔드에서 만든 것을 사용자가 이해하기 쉬운 화면으로 번역하여 전달하는 역할을 한다는 점이 매력적이라 지원하게 되었습니다. UMC에서 팀의 결과물을 실체화하는 든든한 프런트엔드 개발자가 되겠습니다!&quot; <br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[.]]></title>
            <link>https://velog.io/@snow-jun-0/cdw6exhv</link>
            <guid>https://velog.io/@snow-jun-0/cdw6exhv</guid>
            <pubDate>Tue, 24 Feb 2026 07:49:03 GMT</pubDate>
            <description><![CDATA[<p>선형 리스트는 
stack
queue
list</p>
<p>연결리스트는 
stack
queue
list
노드를 사용</p>
<p>비선형 리스트는 
tree
graph</p>
<p>연결 리스트(단순 연결 리스트, 단순 선형 연결 리스트)
LinkedList</p>
<p>data link(주소)
[ Node ]
Node의 특징
데이터를 가지고 있지 않으면 
노드로써의 의미가 없다. 
link는 주소를 저장하는 변수이고
data에는 정수, 실수, 문자, 문자 배열 등이 들어간다. </p>
<p>하나의 이름에 각기 다른 데이터 타입을 묶어서 사용할 수 있는 변수가 존재 --&gt; 구조체
c에서 자료구조를 구현하는데 사용하는 것이 구조체이다. 
노드를 선언하는데 구조체가 필수</p>
<p>preNode        CurrentNode        nextNode
data link   data link       data link
     20          30              Null
현 주소 10   20             30</p>
<p>link에는 다음 값이 있는 주소를 보관한다. </p>
<p>struct listNode{
    char data[4];
    struct listNode * link;
};</p>
<p>연결 할 수 있는 기준 노드를 생성
이 연결 할 수 있는 노드에는 데이터(x)
유일하게 가질 수 있는 것은 주소만이다. 
이러한 노드를 자료구조에서 head node 라고 한다.</p>
<p>헤드 노드 정의(기준 노드가 된다)
struct headNode{
    listNode * headNode;
};</p>
<p>연결리스트는 헤드 노드와 노드의 정의로부터 시작</p>
<p>새로운 노드를 추가하는 방법</p>
<ol>
<li>자기의 앞 노드가 될 이름이 가지고 있는 주소를 받아 온다.</li>
<li>그리고 나서 받은 주소를 통해 연결한다.</li>
<li>자기의 주소를 자신의 뒤 노드에게 전달</li>
<li>자신의 주소를 가지고 있는 뒤 노드와 연결</li>
</ol>
<p>삽입할 노드를 주닙
새 노드의 데이터 필드에 값을 저장
새 노드의 주소(링크(값을 저장
리스트의 앞 노드에 새 노드이 주소를 전달하여 연결</p>
<p>데이터를 삽입하는 위치에 따라
맨 처음, 중간, 맨 마지막 이렇게 삽입할 수 있다. 
자료구조 구현은 1. 각각의 위치에 따라서 함수를 생성하는 방법
2. 하나의 함수로 구현하는 방법이 존재 </p>
<p>&lt;InsertLinkedList.h&gt;
#pragma once</p>
<p>typedef struct ListNode {
    char data[4];
    struct ListNode* link;
} listNode;</p>
<p>typedef struct {
    listNode* head;
} linkedList_h;</p>
<p>linkedList_h* createLinkedList_h(void);
void freeLinkedList_h(linkedList_h* L);
void printList(linkedList_h* L);
void insertFirstNode(linkedList_h* L, char* x);
void insertMiddleNode(linkedList_h* L, listNode* pre, char* x);
void insertLastNode(linkedList_h* L, char* x);</p>
<p>&lt;InsertLinkedList.c&gt;
#define _CRT_SECURE_NO_WARNINGS //경고가 일어나느 부분을 사용자에게 알리지 않고 그냥 실행 </p>
<p>#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;InsertLinkedList.h&quot;</p>
<p>//메모리 할당 및 해제 함수, 출력 함수, 삽입 함수 구현
linkedList_h* createLinkedList_h(void) {
    linkedList_h* L;
    L = (linkedList_h*)malloc(sizeof(linkedList_h));
    L-&gt;head = NULL;
    return L;
}</p>
<p>//메모리 해제 함수
void freeLinkedList_h(linkedList_h* L) {
    listNode* p;
    while (L-&gt;head != NULL) {
        p = L-&gt;head;
        L-&gt;head = L-&gt;head-&gt;link;
        free(p);
        p = NULL;
    }
}</p>
<p>//출력 함수
void printList(linkedList_h* L) {
    listNode* p;
    printf(&quot;L = (&quot;);
    p = L-&gt;head;
    while (p != NULL) {
        printf(&quot;%s&quot;, p-&gt;data);
        p = p-&gt;link;
        if (p != NULL) printf(&quot;, &quot;);
    }
    printf(&quot;) \n&quot;);
}</p>
<p>//삽입 함수
void insertFirstNode(linkedList_h* L, char* x) {
    listNode* newNode;
    newNode = (listNode*)malloc(sizeof(listNode));
    strcpy(newNode-&gt;data, x);
    newNode-&gt;link = L-&gt;head;
    L-&gt;head = newNode;
}</p>
<p>//pre 노드 뒤에 삽입
void insertMiddleNode(linkedList_h* L, listNode* pre, char* x) {
    listNode* newNode;
    newNode = (listNode*)malloc(sizeof(listNode));
    strcpy(newNode-&gt;data, x);
    if (L-&gt;head == NULL) {
        newNode-&gt;link = NULL;
        L-&gt;head = newNode;
    }
    else if (pre == NULL) {
        newNode-&gt;link = L-&gt;head;
        L-&gt;head = newNode;
    }
    else {
        newNode-&gt;link = pre-&gt;link;
        pre-&gt;link = newNode;
    }
}</p>
<p>//마지막에 삽입
void insertLastNode(linkedList_h* L, char* x) {
    listNode* newNode;
    listNode* temp;
    newNode = (listNode*)malloc(sizeof(listNode));
    strcpy(newNode-&gt;data, x);
    newNode-&gt;link = NULL;
    if (L-&gt;head == NULL) {
        L-&gt;head = newNode;
        return;
    }
    temp = L-&gt;head;
    while (temp-&gt;link != NULL) temp = temp-&gt;link;
    temp-&gt;link = newNode;
}</p>
<p>&lt;sampleLink.c&gt;
#include &lt;stdio.h&gt;
#include &quot;InsertLinkedList.h&quot;</p>
<p>int main(void) {
    linkedList_h* L;
    L = createLinkedList_h();
    printf(&quot;(1) 공백 리스트 생성하기! \n&quot;);
    printList(L);</p>
<pre><code>printf(&quot;\n(2) 리스트에 [수] 노드 삽입하기! \n&quot;);
insertFirstNode(L, &quot;수&quot;);
printList(L);

printf(&quot;\n(3) 리스트 마지막에 [금] 노드 삽입하기! \n&quot;);
insertLastNode(L, &quot;금&quot;);
printList(L);

printf(&quot;\n(4) 리스트 첫 번째에 [월] 노드 삽입하기! \n&quot;);
insertFirstNode(L, &quot;월&quot;);
printList(L);

printf(&quot;\n(5) 리스트 공간을 해제하여 공백 리스트로 만들기! \n&quot;);
freeLinkedList_h(L);
printList(L);

return 0;</code></pre><p>}</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[c언어 - 자료구조 2일차]]></title>
            <link>https://velog.io/@snow-jun-0/fvui7k07</link>
            <guid>https://velog.io/@snow-jun-0/fvui7k07</guid>
            <pubDate>Tue, 24 Feb 2026 04:11:49 GMT</pubDate>
            <description><![CDATA[<h1 id="자료구조-연결-리스트linked-list-개념-정리-및-c-구현">[자료구조] 연결 리스트(Linked List) 개념 정리 및 C 구현</h1>
<h2 id="1-리스트의-분류">1. 리스트의 분류</h2>
<p>자료구조는 크게 선형과 비선형으로 나뉩니다.</p>
<h3 id="선형-리스트-linear-list">선형 리스트 (Linear List)</h3>
<ul>
<li>Stack</li>
<li>Queue</li>
<li>List</li>
</ul>
<h3 id="연결-리스트-linked-list">연결 리스트 (Linked List)</h3>
<ul>
<li>Stack, Queue, List 등을 &#39;노드(Node)&#39;를 사용하여 구현</li>
<li>단순 연결 리스트, 단순 선형 연결 리스트 등이 있음</li>
</ul>
<h3 id="비선형-리스트-non-linear-list">비선형 리스트 (Non-Linear List)</h3>
<ul>
<li>Tree</li>
<li>Graph</li>
</ul>
<hr>
<h2 id="2-연결-리스트의-구조와-노드node">2. 연결 리스트의 구조와 노드(Node)</h2>
<p>연결 리스트는 데이터와 주소(Link)를 담은 <strong>노드</strong>들의 연결로 이루어집니다.</p>
<h3 id="노드node의-특징">노드(Node)의 특징</h3>
<ul>
<li>[ data | link ] 구조로 되어 있음</li>
<li><strong>data</strong>: 실제 저장할 값 (정수, 실수, 문자열 등)</li>
<li><strong>link</strong>: 다음 노드의 주소를 저장하는 포인터 변수</li>
<li>데이터를 가지고 있지 않으면 노드로서의 의미가 없음</li>
</ul>
<h3 id="c언어에서의-구현">C언어에서의 구현</h3>
<ul>
<li>서로 다른 데이터 타입을 묶어야 하므로 <strong>구조체(struct)</strong> 사용이 필수적입니다.</li>
</ul>
<pre><code class="language-c">    struct listNode {
        char data[4];
        struct listNode* link;
    };</code></pre>
<h3 id="헤드-노드head-node">헤드 노드(Head Node)</h3>
<ul>
<li>리스트의 시작 위치를 알려주는 기준 노드입니다.</li>
<li>데이터는 저장하지 않고, 첫 번째 노드의 <strong>주소</strong>만 보관합니다.<pre><code class="language-c">  typedef struct {
      listNode* head;
  } linkedList_h;</code></pre>
</li>
</ul>
<hr>
<h2 id="3-새로운-노드-삽입-프로세스">3. 새로운 노드 삽입 프로세스</h2>
<ol>
<li>삽입할 노드를 준비하고 데이터 필드에 값을 저장합니다.</li>
<li><strong>이전 노드(pre)</strong>가 가리키던 주소를 새 노드의 링크에 저장합니다.</li>
<li>이전 노드의 링크가 새 노드를 가리키도록 업데이트합니다.</li>
</ol>
<hr>
<h2 id="4-c언어-구현-코드">4. C언어 구현 코드</h2>
<h3 id="1-헤더-파일-insertlinkedlisth">(1) 헤더 파일: InsertLinkedList.h</h3>
<pre><code class="language-c">    #pragma once

    typedef struct ListNode {
        char data[4];
        struct ListNode* link;
    } listNode;

    typedef struct {
        listNode* head;
    } linkedList_h;

    linkedList_h* createLinkedList_h(void);
    void freeLinkedList_h(linkedList_h* L);
    void printList(linkedList_h* L);
    void insertFirstNode(linkedList_h* L, char* x);
    void insertMiddleNode(linkedList_h* L, listNode* pre, char* x);
    void insertLastNode(linkedList_h* L, char* x);</code></pre>
<h3 id="2-소스-파일-insertlinkedlistc">(2) 소스 파일: InsertLinkedList.c</h3>
<pre><code class="language-c">    #define _CRT_SECURE_NO_WARNINGS
    #include &lt;stdio.h&gt;
    #include &lt;string.h&gt;
    #include &lt;stdlib.h&gt;
    #include &quot;InsertLinkedList.h&quot;

    // 리스트 생성
    linkedList_h* createLinkedList_h(void) {
        linkedList_h* L;
        L = (linkedList_h*)malloc(sizeof(linkedList_h));
        L-&gt;head = NULL;
        return L;
    }

    // 메모리 해제
    void freeLinkedList_h(linkedList_h* L) {
        listNode* p;
        while (L-&gt;head != NULL) {
            p = L-&gt;head;
            L-&gt;head = L-&gt;head-&gt;link;
            free(p);
            p = NULL;
        }
    }

    // 리스트 출력
    void printList(linkedList_h* L) {
        listNode* p;
        printf(&quot;L = (&quot;);
        p = L-&gt;head;
        while (p != NULL) {
            printf(&quot;%s&quot;, p-&gt;data);
            p = p-&gt;link;
            if (p != NULL) printf(&quot;, &quot;);
        }
        printf(&quot;) \n&quot;);
    }

    // 첫 번째 노드로 삽입
    void insertFirstNode(linkedList_h* L, char* x) {
        listNode* newNode;
        newNode = (listNode*)malloc(sizeof(listNode));
        strcpy(newNode-&gt;data, x);
        newNode-&gt;link = L-&gt;head;
        L-&gt;head = newNode;
    }

    // 중간 삽입 (pre 노드 뒤)
    void insertMiddleNode(linkedList_h* L, listNode* pre, char* x) {
        listNode* newNode;
        newNode = (listNode*)malloc(sizeof(listNode));
        strcpy(newNode-&gt;data, x);
        if (L-&gt;head == NULL) {
            newNode-&gt;link = NULL;
            L-&gt;head = newNode;
        }
        else if (pre == NULL) {
            newNode-&gt;link = L-&gt;head;
            L-&gt;head = newNode;
        }
        else {
            newNode-&gt;link = pre-&gt;link;
            pre-&gt;link = newNode;
        }
    }

    // 마지막 노드로 삽입
    void insertLastNode(linkedList_h* L, char* x) {
        listNode* newNode;
        listNode* temp;
        newNode = (listNode*)malloc(sizeof(listNode));
        strcpy(newNode-&gt;data, x);
        newNode-&gt;link = NULL;
        if (L-&gt;head == NULL) {
            L-&gt;head = newNode;
            return;
        }
        temp = L-&gt;head;
        while (temp-&gt;link != NULL) temp = temp-&gt;link;
        temp-&gt;link = newNode;
    }</code></pre>
<h3 id="3-실행-파일-samplelinkc">(3) 실행 파일: sampleLink.c</h3>
<pre><code class="language-c">    #include &lt;stdio.h&gt;
    #include &quot;InsertLinkedList.h&quot;

    int main(void) {
        linkedList_h* L;
        L = createLinkedList_h();
        printf(&quot;(1) 공백 리스트 생성하기! \n&quot;);
        printList(L);

        printf(&quot;\n(2) 리스트에 [수] 노드 삽입하기! \n&quot;);
        insertFirstNode(L, &quot;수&quot;);
        printList(L);

        printf(&quot;\n(3) 리스트 마지막에 [금] 노드 삽입하기! \n&quot;);
        insertLastNode(L, &quot;금&quot;);
        printList(L);

        printf(&quot;\n(4) 리스트 첫 번째에 [월] 노드 삽입하기! \n&quot;);
        insertFirstNode(L, &quot;월&quot;);
        printList(L);

        printf(&quot;\n(5) 리스트 공간을 해제하여 공백 리스트로 만들기! \n&quot;);
        freeLinkedList_h(L);
        printList(L);

        return 0;
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 15일차(데이터 프레임)]]></title>
            <link>https://velog.io/@snow-jun-0/o728u6td</link>
            <guid>https://velog.io/@snow-jun-0/o728u6td</guid>
            <pubDate>Sat, 21 Feb 2026 16:31:19 GMT</pubDate>
            <description><![CDATA[<h1 id="pandas-데이터프레임-조작-및-전처리-완벽-정리">[Pandas] 데이터프레임 조작 및 전처리 완벽 정리</h1>
<h2 id="1-rowcolumn-추가-및-삭제">1. Row/Column 추가 및 삭제</h2>
<h3 id="컬럼column-추가">컬럼(Column) 추가</h3>
<ul>
<li><strong>[ ] 사용</strong>: <code>df[&#39;새컬럼명&#39;] = 데이터</code> 형태로 추가 (가장 우측에 추가)<pre><code class="language-python">df[&#39;Age_Double&#39;]=df[&#39;Age&#39;]*2</code></pre>
<table>
<thead>
<tr>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
<th align="left">Age_Double</th>
</tr>
</thead>
<tbody><tr>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">A/5 21171</td>
<td align="left">7.2500</td>
<td align="left">NaN</td>
<td align="left">S</td>
<td align="left">44.0</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Cumings, Mrs. John Bradley (Florence Briggs Th...)</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">PC 17599</td>
<td align="left">71.2833</td>
<td align="left">C85</td>
<td align="left">C</td>
<td align="left">76.0</td>
</tr>
<tr>
<td align="left">3</td>
<td align="left">1</td>
<td align="left">3</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="left">female</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">STON/O2. 3101282</td>
<td align="left">7.9250</td>
<td align="left">NaN</td>
<td align="left">S</td>
<td align="left">52.0</td>
</tr>
<tr>
<td align="left">4</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath (Lily May Peel)</td>
<td align="left">female</td>
<td align="left">35.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">113803</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
<td align="left">70.0</td>
</tr>
<tr>
<td align="left">5</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="left">male</td>
<td align="left">35.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">373450</td>
<td align="left">8.0500</td>
<td align="left">NaN</td>
<td align="left">S</td>
<td align="left">70.0</td>
</tr>
<tr>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.0000</td>
<td align="left">NaN</td>
<td align="left">S</td>
<td align="left">54.0</td>
</tr>
<tr>
<td align="left">888</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="left">female</td>
<td align="left">19.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">112053</td>
<td align="left">30.0000</td>
<td align="left">B42</td>
<td align="left">S</td>
<td align="left">38.0</td>
</tr>
<tr>
<td align="left">889</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Johnston, Miss. Catherine Helen &quot;Carrie&quot;</td>
<td align="left">female</td>
<td align="left">NaN</td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">W./C. 6607</td>
<td align="left">23.4500</td>
<td align="left">NaN</td>
<td align="left">S</td>
<td align="left">NaN</td>
</tr>
<tr>
<td align="left">890</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="left">male</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">111369</td>
<td align="left">30.0000</td>
<td align="left">C148</td>
<td align="left">C</td>
<td align="left">52.0</td>
</tr>
<tr>
<td align="left">891</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">370376</td>
<td align="left">7.7500</td>
<td align="left">NaN</td>
<td align="left">Q</td>
<td align="left">64.0</td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><strong>insert() 사용</strong>: <code>df.insert(위치인덱스, &#39;컬럼명&#39;, 데이터)</code>를 사용하여 원하는 위치에 삽입<pre><code class="language-python">df.insert(3, &#39;Fare10&#39;, df[&#39;Fare&#39;] / 10 )
</code></pre>
</li>
</ul>
<p>df.head()</p>
<pre><code>| PassengerId | Survived | Pclass |Fare10 | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | Age_Double |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| 1 | 0 | 3 | 0.7250 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S | 44.0 |
| 2 | 1 | 1 | 7.1283 | Cumings, Mrs. John Bradley (Florence Briggs Th...) | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C | 76.0 |
| 3 | 1 | 3 | 0.7925 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S | 52.0 |
| 4 | 1 | 1 | 5.3100 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S | 70.0 |
| 5 | 0 | 3 | 0.8050 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S | 70.0 |


### 컬럼(Column) 삭제
* **drop() 함수**: `df.drop(&#39;컬럼명&#39;, axis=1)` (axis=1은 열 방향)
```python
# DataFrame 은 2차원 데이터,  axis= 값은 0, 1 두가지가 존재 한다
# axis=0 : row level  (default)
# axis=1 : column level

# 열 제거, 원본 변화 없다.
df.drop(&#39;Age_Double&#39;, axis=1)</code></pre><table>
<thead>
<tr>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Fare10</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">0.72500</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">A/5 21171</td>
<td align="left">7.2500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">7.12833</td>
<td align="left">Cumings, Mrs. John Bradley (Florence Briggs Th...)</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">PC 17599</td>
<td align="left">71.2833</td>
<td align="left">C85</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left">3</td>
<td align="left">1</td>
<td align="left">3</td>
<td align="left">0.79250</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="left">female</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">STON/O2. 3101282</td>
<td align="left">7.9250</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">4</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">5.31000</td>
<td align="left">Futrelle, Mrs. Jacques Heath (Lily May Peel)</td>
<td align="left">female</td>
<td align="left">35.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">113803</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">5</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">0.80500</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="left">male</td>
<td align="left">35.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">373450</td>
<td align="left">8.0500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">1.30000</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.0000</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">888</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">3.00000</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="left">female</td>
<td align="left">19.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">112053</td>
<td align="left">30.0000</td>
<td align="left">B42</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">889</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">2.34500</td>
<td align="left">Johnston, Miss. Catherine Helen &quot;Carrie&quot;</td>
<td align="left">female</td>
<td align="left">NaN</td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">W./C. 6607</td>
<td align="left">23.4500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">890</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">3.00000</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="left">male</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">113803</td>
<td align="left">30.0000</td>
<td align="left">C148</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left">891</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">0.77500</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">370376</td>
<td align="left">7.7500</td>
<td align="left">NaN</td>
<td align="left">Q</td>
</tr>
</tbody></table>
<ul>
<li><strong>원본 반영</strong>: <code>inplace=True</code> 옵션을 주어야 원본 데이터프레임이 변경됨</li>
</ul>
<h3 id="행row-추가-및-삭제">행(Row) 추가 및 삭제</h3>
<ul>
<li><strong>추가</strong>: <code>df.loc[&#39;새인덱스&#39;] = 데이터</code></li>
<li><strong>삭제</strong>: <code>df.drop([&#39;인덱스명&#39;], axis=0)</code> (axis=0은 행 방향, 기본값)<pre><code class="language-python">df2 = pd.DataFrame([
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9, 10, 11, 12]
], columns=[&#39;a&#39;,&#39;b&#39;,&#39;c&#39;,&#39;d&#39;], index = [&#39;김길동&#39;, &#39;최진수&#39;, &#39;허수민&#39;])
df2</code></pre>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="left">a</th>
<th align="left">b</th>
<th align="left">c</th>
<th align="left">d</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>김길동</strong></td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">3</td>
<td align="left">4</td>
</tr>
<tr>
<td align="left"><strong>최진수</strong></td>
<td align="left">5</td>
<td align="left">6</td>
<td align="left">7</td>
<td align="left">8</td>
</tr>
<tr>
<td align="left"><strong>허수민</strong></td>
<td align="left">9</td>
<td align="left">10</td>
<td align="left">11</td>
<td align="left">12</td>
</tr>
<tr>
<td align="left">```python</td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
<tr>
<td align="left"># 새로운 행(row) 추가</td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
<tr>
<td align="left">df2.loc[&#39;김갑수&#39;] = pd.Series([100, 200, 300, 400], index=[&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;])</td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
</tbody></table>
</li>
</ul>
<p>df2</p>
<pre><code>
| 인덱스 (Index) | a | b | c | d |
| :--- | :--- | :--- | :--- | :--- |
| **김길동** | 1 | 2 | 3 | 4 |
| **최진수** | 5 | 6 | 7 | 8 |
| **허수민** | 9 | 10 | 11 | 12 |
| **김갑수** | 100 | 200 | 300 | 400 |
```python
df2.loc[&#39;김철수&#39;] = [101, 202, 303, 404]</code></pre><table>
<thead>
<tr>
<th align="left">인덱스 (Index)</th>
<th align="left">a</th>
<th align="left">b</th>
<th align="left">c</th>
<th align="left">d</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>김길동</strong></td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">3</td>
<td align="left">4</td>
</tr>
<tr>
<td align="left"><strong>최진수</strong></td>
<td align="left">5</td>
<td align="left">6</td>
<td align="left">7</td>
<td align="left">8</td>
</tr>
<tr>
<td align="left"><strong>허수민</strong></td>
<td align="left">9</td>
<td align="left">10</td>
<td align="left">11</td>
<td align="left">12</td>
</tr>
<tr>
<td align="left"><strong>김갑수</strong></td>
<td align="left">100</td>
<td align="left">200</td>
<td align="left">300</td>
<td align="left">400</td>
</tr>
<tr>
<td align="left"><strong>김철수</strong></td>
<td align="left">101</td>
<td align="left">202</td>
<td align="left">303</td>
<td align="left">404</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 행 삭제
# drop() 사용,   axis=0 (디폴트)
df2.drop([&#39;최진수&#39;, &#39;허수민&#39;])</code></pre>
<table>
<thead>
<tr>
<th align="left">인덱스 (Index)</th>
<th align="left">a</th>
<th align="left">b</th>
<th align="left">c</th>
<th align="left">d</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>김길동</strong></td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">3</td>
<td align="left">4</td>
</tr>
<tr>
<td align="left"><strong>김갑수</strong></td>
<td align="left">100</td>
<td align="left">200</td>
<td align="left">300</td>
<td align="left">400</td>
</tr>
<tr>
<td align="left"><strong>김철수</strong></td>
<td align="left">101</td>
<td align="left">202</td>
<td align="left">303</td>
<td align="left">404</td>
</tr>
</tbody></table>
<hr>
<h2 id="2-상관관계-correlation">2. 상관관계 (Correlation)</h2>
<p>두 변수 간의 선형적 흐름이 얼마나 비슷한지를 나타내는 척도입니다.</p>
<ul>
<li><strong>범위</strong>: -1 ~ +1 사이의 값<ul>
<li><strong>+1에 가까울수록</strong>: 양의 상관관계 (같이 증가)</li>
<li><strong>-1에 가까울수록</strong>: 음의 상관관계 (한쪽이 증가하면 다른 쪽은 감소)</li>
<li><strong>0에 가까울수록</strong>: 상관관계가 거의 없음</li>
<li><strong>절대값이 클수록</strong>: 상관관계가 크다. </li>
</ul>
</li>
<li><strong>함수</strong>: <code>df.corr(numeric_only=True)</code></li>
<li><strong>주의</strong>: 상관관계가 높다고 해서 반드시 &#39;인과관계&#39;가 성립하는 것은 아님</li>
</ul>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="center">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="center">Fare</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>PassengerId</strong></td>
<td align="center">1.000000</td>
<td align="center">-0.005007</td>
<td align="center">-0.035144</td>
<td align="center">0.036847</td>
<td align="center">-0.057527</td>
<td align="center">-0.001652</td>
<td align="center">0.012658</td>
</tr>
<tr>
<td align="left"><strong>Survived</strong></td>
<td align="center">-0.005007</td>
<td align="center">1.000000</td>
<td align="center">-0.338481</td>
<td align="center">-0.077221</td>
<td align="center">-0.035322</td>
<td align="center">0.081629</td>
<td align="center">0.257307</td>
</tr>
<tr>
<td align="left"><strong>Pclass</strong></td>
<td align="center">-0.035144</td>
<td align="center">-0.338481</td>
<td align="center">1.000000</td>
<td align="center">-0.369226</td>
<td align="center">0.083081</td>
<td align="center">0.018443</td>
<td align="center">-0.549500</td>
</tr>
<tr>
<td align="left"><strong>Age</strong></td>
<td align="center">0.036847</td>
<td align="center">-0.077221</td>
<td align="center">-0.369226</td>
<td align="center">1.000000</td>
<td align="center">-0.308247</td>
<td align="center">-0.189119</td>
<td align="center">0.096067</td>
</tr>
<tr>
<td align="left"><strong>SibSp</strong></td>
<td align="center">-0.057527</td>
<td align="center">-0.035322</td>
<td align="center">0.083081</td>
<td align="center">-0.308247</td>
<td align="center">1.000000</td>
<td align="center">0.414838</td>
<td align="center">0.159651</td>
</tr>
<tr>
<td align="left"><strong>Parch</strong></td>
<td align="center">-0.001652</td>
<td align="center">0.081629</td>
<td align="center">0.018443</td>
<td align="center">-0.189119</td>
<td align="center">0.414838</td>
<td align="center">1.000000</td>
<td align="center">0.216225</td>
</tr>
<tr>
<td align="left"><strong>Fare</strong></td>
<td align="center">0.012658</td>
<td align="center">0.257307</td>
<td align="center">-0.549500</td>
<td align="center">0.096067</td>
<td align="center">0.159651</td>
<td align="center">0.216225</td>
<td align="center">1.000000</td>
</tr>
<tr>
<td align="left">```</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">상관관계가 있는 자료들</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># Fare - Pclass</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># Survived - Pclass</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># Survived - Fare</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># Age - Pclass</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># parch-SibSp</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># SibSp-Age</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h1 id="상관관계-시각화">상관관계 시각화</h1>
<p>plt.matshow(df.corr(numeric_only=True))
plt.colorbar()
plt.show()</p>
<pre><code>![](https://velog.velcdn.com/images/snow-jun-0/post/4017b652-af30-41c0-a4c2-33880c4517ca/image.png)

---

## 3. NaN (결측치) 처리

데이터에 값이 없는 상태(Not a Number)를 의미하며, 분석 전 반드시 확인해야 합니다.

* **확인**: `df.isna()` (결측치면 True), `df.info()`
```python
df.info()

# ↓ Age, Cabin, Embarked 는 결측치가 있슴을 알수 있다.
&lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB



df.isna()

# ↓ 결측치는 True 로 표시된다.</code></pre><table>
<thead>
<tr>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">...</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left">0</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">...</td>
<td align="left"><strong>True</strong></td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">...</td>
<td align="left">False</td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">...</td>
<td align="left"><strong>True</strong></td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left">888</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left">False</td>
<td align="left"><strong>True</strong></td>
<td align="left">...</td>
<td align="left"><strong>True</strong></td>
<td align="left">False</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 특정 컬럼에 대해서 확인
df[&#39;Age&#39;].isna()</code></pre>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">Age</th>
</tr>
</thead>
<tbody><tr>
<td align="left">0</td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left">888</td>
<td align="left"><strong>True</strong></td>
</tr>
<tr>
<td align="left">889</td>
<td align="left">False</td>
</tr>
<tr>
<td align="left">```python</td>
<td align="left"></td>
</tr>
<tr>
<td align="left"># 결측된 데이터만 확인 &lt;- boolean selection 활용</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">df[df[&#39;Age&#39;].isna()]</td>
<td align="left"></td>
</tr>
<tr>
<td align="left">```</td>
<td align="left"></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">PassengerId</td>
</tr>
<tr>
<td align="left">:---</td>
<td align="left">:---:</td>
</tr>
<tr>
<td align="left"><strong>5</strong></td>
<td align="left">6</td>
</tr>
<tr>
<td align="left"><strong>17</strong></td>
<td align="left">18</td>
</tr>
<tr>
<td align="left"><strong>19</strong></td>
<td align="left">20</td>
</tr>
<tr>
<td align="left"><strong>26</strong></td>
<td align="left">27</td>
</tr>
<tr>
<td align="left"><strong>28</strong></td>
<td align="left">29</td>
</tr>
<tr>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left"><strong>859</strong></td>
<td align="left">860</td>
</tr>
<tr>
<td align="left"><strong>863</strong></td>
<td align="left">864</td>
</tr>
<tr>
<td align="left"><strong>868</strong></td>
<td align="left">869</td>
</tr>
<tr>
<td align="left"><strong>878</strong></td>
<td align="left">879</td>
</tr>
<tr>
<td align="left"><strong>888</strong></td>
<td align="left">889</td>
</tr>
</tbody></table>
<ul>
<li><strong>삭제</strong>: <code>df.dropna()</code><ul>
<li><code>subset=[&#39;컬럼명&#39;]</code>: 특정 컬럼에 결측치가 있는 경우만 삭제</li>
<li><code>axis=1</code>: 결측치가 포함된 &#39;열&#39; 자체를 삭제<pre><code>df # 891 rows × 12 columns
</code></pre></li>
</ul>
</li>
</ul>
<p>df.dropna() # 183 rows × 12 columns</p>
<pre><code>|  | PassengerId | Survived | Pclass | Name | Sex | Age | ... | Fare | Cabin | Embarked |
| :--- | :---: | :---: | :---: | :--- | :---: | :---: | :--- | :---: | :---: | :---: |
| **1** | 2 | 1 | 1 | Cumings, Mrs. John Bradley... | female | 38.0 | ... | 71.2833 | C85 | C |
| **3** | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath... | female | 35.0 | ... | 53.1000 | C123 | S |
| **6** | 7 | 0 | 1 | McCarthy, Mr. Timothy J | male | 54.0 | ... | 51.8625 | E46 | S |
| **10** | 11 | 1 | 3 | Sandstrom, Miss. Marguerite Rut | female | 4.0 | ... | 16.7000 | G6 | S |
| **11** | 12 | 1 | 1 | Bonnell, Miss. Elizabeth | female | 58.0 | ... | 26.5500 | C103 | S |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| **889** | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 26.0 | ... | 30.0000 | C148 | C |    
```python
# ↑ 183개의 row 가 나온다 (891개에서 확 줄었다)
# index 나 PassengerId 를 보면 중간중간에 빠진거 확인


# dropna() 기본적으로 row 기준(axis=0)으로 동작한다
# 각 row 에서, 하나라도 NaN 값이 있으면 해당 row 를 지워버린다


# 행을 삭제하되, 특정 컬럼에 대해서만 dropna 하기

df.dropna(subset=[&#39;Age&#39;])  # 714 rows × 12 columns

# ↓Age 컬럼이 NaN 인 경우만 row 가 drop 됨 (axis=0)</code></pre><table>
<thead>
<tr>
<th align="left">인덱스</th>
<th align="center">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="left">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="left">Ticket</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>0</strong></td>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="center">male</td>
<td align="center">22.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">A/5 21171</td>
<td align="center">7.2500</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>1</strong></td>
<td align="center">2</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Cumings, Mrs. John Bradley...</td>
<td align="center">female</td>
<td align="center">38.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">PC 17599</td>
<td align="center">71.2833</td>
<td align="center">C85</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>2</strong></td>
<td align="center">3</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="center">female</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">STON/O2. 3101282</td>
<td align="center">7.9250</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>3</strong></td>
<td align="center">4</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath...</td>
<td align="center">female</td>
<td align="center">35.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">113803</td>
<td align="center">53.1000</td>
<td align="center">C123</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>4</strong></td>
<td align="center">5</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="center">male</td>
<td align="center">35.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">373450</td>
<td align="center">8.0500</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="left"><strong>886</strong></td>
<td align="center">887</td>
<td align="center">0</td>
<td align="center">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="center">male</td>
<td align="center">27.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">211536</td>
<td align="center">13.0000</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>887</strong></td>
<td align="center">888</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="center">female</td>
<td align="center">19.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">112053</td>
<td align="center">30.0000</td>
<td align="center">B42</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>889</strong></td>
<td align="center">890</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="center">male</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">111369</td>
<td align="center">30.0000</td>
<td align="center">C148</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>890</strong></td>
<td align="center">891</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="center">male</td>
<td align="center">32.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">370376</td>
<td align="center">7.7500</td>
<td align="center">NaN</td>
<td align="center">Q</td>
</tr>
<tr>
<td align="left">```</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">df.dropna(subset=[&#39;Age&#39;, &#39;Cabin&#39;])  # 185 rows × 12 columns</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">```</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"></td>
<td align="center">PassengerId</td>
<td align="center">Survived</td>
<td align="center">Pclass</td>
<td align="left">Name</td>
<td align="center">Sex</td>
<td align="center">Age</td>
<td align="center">SibSp</td>
<td align="center">Parch</td>
<td align="left">Ticket</td>
<td align="center">Fare</td>
<td align="center">Cabin</td>
<td align="center">Embarked</td>
</tr>
<tr>
<td align="left">:---</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="left">:---</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="left">:---</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="left"><strong>1</strong></td>
<td align="center">2</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Cumings, Mrs. John Bradley...</td>
<td align="center">female</td>
<td align="center">38.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">PC 17599</td>
<td align="center">71.2833</td>
<td align="center">C85</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>3</strong></td>
<td align="center">4</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath...</td>
<td align="center">female</td>
<td align="center">35.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">113803</td>
<td align="center">53.1000</td>
<td align="center">C123</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>6</strong></td>
<td align="center">7</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">McCarthy, Mr. Timothy J</td>
<td align="center">male</td>
<td align="center">54.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">17463</td>
<td align="center">51.8625</td>
<td align="center">E46</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>10</strong></td>
<td align="center">11</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="left">Sandstrom, Miss. Marguerite Rut</td>
<td align="center">female</td>
<td align="center">4.0</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">PP 9549</td>
<td align="center">16.7000</td>
<td align="center">G6</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>11</strong></td>
<td align="center">12</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Bonnell, Miss. Elizabeth</td>
<td align="center">female</td>
<td align="center">58.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">113783</td>
<td align="center">26.5500</td>
<td align="center">C103</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="left"><strong>871</strong></td>
<td align="center">872</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Beckwith, Mrs. Richard Leonard...</td>
<td align="center">female</td>
<td align="center">47.0</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">11751</td>
<td align="center">52.5542</td>
<td align="center">D35</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>872</strong></td>
<td align="center">873</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">Carlsson, Mr. Frans Olof</td>
<td align="center">male</td>
<td align="center">33.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">695</td>
<td align="center">5.0000</td>
<td align="center">B51 B53 B55</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>879</strong></td>
<td align="center">880</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Potter, Mrs. Thomas Jr...</td>
<td align="center">female</td>
<td align="center">56.0</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">11767</td>
<td align="center">83.1583</td>
<td align="center">C50</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>887</strong></td>
<td align="center">888</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="center">female</td>
<td align="center">19.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">112053</td>
<td align="center">30.0000</td>
<td align="center">B42</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>889</strong></td>
<td align="center">890</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="center">male</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">111369</td>
<td align="center">30.0000</td>
<td align="center">C148</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left">```python</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># NaN 이 있는 &#39;컬럼&#39; 삭제하기</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">df.dropna(axis=1)</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h1 id="↓-age-cabin-embarked-컬럼-삭제">↓ Age, Cabin, Embarked 컬럼 삭제!</h1>
<pre><code>|  | PassengerId | Survived | Pclass | Name | Sex | SibSp | Parch | Ticket | Fare |
| :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :--- | :---: |
| **0** | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 1 | 0 | A/5 21171 | 7.2500 |
| **1** | 2 | 1 | 1 | Cumings, Mrs. John Bradley... | female | 1 | 0 | PC 17599 | 71.2833 |
| **2** | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 0 | 0 | STON/O2. 3101282 | 7.9250 |
| **3** | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath... | female | 1 | 0 | 113803 | 53.1000 |
| **4** | 5 | 0 | 3 | Allen, Mr. William Henry | male | 0 | 0 | 373450 | 8.0500 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| **886** | 887 | 0 | 2 | Montvila, Rev. Juozas | male | 0 | 0 | 211536 | 13.0000 |
| **887** | 888 | 1 | 1 | Graham, Miss. Margaret Edith | female | 0 | 0 | 112053 | 30.0000 |
| **888** | 889 | 0 | 3 | Johnston, Miss. Catherine Helen... | female | 1 | 2 | W./C. 6607 | 23.4500 |
| **889** | 890 | 1 | 1 | Behr, Mr. Karl Howell | male | 0 | 0 | 111369 | 30.0000 |
| **890** | 891 | 0 | 3 | Dooley, Mr. Patrick | male | 0 | 0 | 370376 | 7.7500|

* **대체**: `df.fillna(값)`
    * 주로 평균값(`mean()`)이나 중앙값으로 채워 데이터의 손실을 방지함
```python
# Age 평균값
df[&#39;Age&#39;].mean()   # NaN 은 배제된 연산결과닷! 주의
#29.69911764705882 (인원수 삭제가 일어남-714명)


# 위 mean() 값은 891(전체)명에 대한 평균값이 아니라 714(Nan값 제외) 명에 대한 평균값이다
# df[&#39;Age&#39;].sum() / df[&#39;Age&#39;].count() 둘이 같음



# NaN 을 평균값으로 대체(원본에 영향 없음)
df[&#39;Age&#39;].fillna(df[&#39;Age&#39;].mean())</code></pre><hr>
<h2 id="4-데이터-타입의-이해-수치형-vs-범주형">4. 데이터 타입의 이해 (수치형 vs 범주형)</h2>
<table>
<thead>
<tr>
<th align="left">구분</th>
<th align="left">수치형 (Numerical)</th>
<th align="left">범주형 (Categorical)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>특징</strong></td>
<td align="left">연속적인 숫자</td>
<td align="left">불연속적인 값 (분류 목적)</td>
</tr>
<tr>
<td align="left"><strong>예시</strong></td>
<td align="left">나이, 운임(Fare)</td>
<td align="left">성별, 등급(Pclass), 우편번호</td>
</tr>
<tr>
<td align="left"><strong>연산</strong></td>
<td align="left">산술 연산 및 대소 비교 가능</td>
<td align="left">연산 및 대소 비교가 무의미함</td>
</tr>
</tbody></table>
<h3 id="데이터-변환-apply">데이터 변환: apply()</h3>
<p>특정 함수를 컬럼 전체에 적용하여 데이터를 변환할 때 사용합니다.
(예: 나이 숫자를 10대, 20대 등 범주형으로 변환)</p>
<pre><code class="language-python"># 23 -&gt; 20
# 43 -&gt; 40
def age_categorize(age):
  if np.isnan(age):
    return -1   # Age 값이 없으면 -1 로 처리

  return int(age / 10) * 10


age_categorize(47)  #40  



# 특정 컬럼에 apply(함수) 한다
age_span = df[&#39;Age&#39;].apply(age_categorize)
age_span</code></pre>
<table>
<thead>
<tr>
<th align="left">인덱스</th>
<th align="center">변환 결과 (Age_span)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>0</strong></td>
<td align="center"><strong>20</strong></td>
</tr>
<tr>
<td align="left"><strong>1</strong></td>
<td align="center"><strong>30</strong></td>
</tr>
<tr>
<td align="left"><strong>2</strong></td>
<td align="center"><strong>20</strong></td>
</tr>
<tr>
<td align="left"><strong>3</strong></td>
<td align="center"><strong>30</strong></td>
</tr>
<tr>
<td align="left"><strong>4</strong></td>
<td align="center"><strong>30</strong></td>
</tr>
<tr>
<td align="left">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="left"><strong>886</strong></td>
<td align="center"><strong>20</strong></td>
</tr>
<tr>
<td align="left"><strong>887</strong></td>
<td align="center"><strong>10</strong></td>
</tr>
<tr>
<td align="left"><strong>888</strong></td>
<td align="center"><strong>-1</strong></td>
</tr>
<tr>
<td align="left"><strong>889</strong></td>
<td align="center"><strong>20</strong></td>
</tr>
<tr>
<td align="left"><strong>890</strong></td>
<td align="center"><strong>30</strong></td>
</tr>
</tbody></table>
<hr>
<h2 id="5-원-핫-인코딩-one-hot-encoding">5. 원-핫 인코딩 (One-hot encoding)</h2>
<p>범주형 데이터를 머신러닝 모델이 인식할 수 있도록 숫자(0과 1)로 변환하는 기법입니다.</p>
<ul>
<li>범주의 개수만큼 컬럼을 생성하고, 해당 범주에만 1을 부여합니다.</li>
<li><strong>함수</strong>: <code>pd.get_dummies(df, columns=[&#39;컬럼명&#39;], dtype=int)</code><pre><code># 범주형 데이터는 연산이 불가하다 (혹은 의미 없다)
# 그래서 &#39;처리&#39; 가 가능하도록 데이터를 바꿔주어야 할 필요가 있다.  
</code></pre></li>
</ul>
<h1 id="범주형-테이터-컬럼한개를-범주의-개수-만큼-늘려서">범주형 테이터 컬럼한개를 &#39;범주의 개수&#39; 만큼 늘려서</h1>
<h1 id="범주에-해당하는-값에만-1-을-주고">범주에 해당하는 값에만 &#39;1&#39; 을 주고</h1>
<h1 id="나머지에는-0-을-주어-처리하는-방법">나머지에는 &#39;0&#39; 을 주어 처리하는 방법</h1>
<h1 id="---이를-one-hot-encoding-이라-합니다-----결국-1-은-한개만-등장한다">--&gt; 이를 One-hot encoding 이라 합니다  &lt;-- 결국 &#39;1&#39; 은 한개만 등장한다</h1>
<h1 id="가령">가령</h1>
<h1 id="color-란-컬럼에--red-green-blue--라는-세가지-종류의-범주값만-있다면">Color 란 컬럼에  &quot;Red&quot;, &quot;Green&quot;, &quot;Blue&quot;  라는 &#39;세가지&#39; 종류의 범주값만 있다면</h1>
<h1 id="세-개의-0-1-로-구성된-값으로-변환시키는-겁니다-1-은-한개만-등장">&#39;세 개&#39;의 &#39;0, 1 로 구성된 값&#39;으로 변환시키는 겁니다 (&#39;1&#39; 은 한개만 등장)</h1>
<h1 id="red-----1-0-0">Red -&gt;   [1, 0, 0]</h1>
<h1 id="green---0-1-0">Green -&gt; [0, 1, 0]</h1>
<h1 id="blue----0-0-1">Blue -&gt;  [0, 0, 1]</h1>
<h1 id="columns--파라미터로">columns=  파라미터로</h1>
<h1 id="one-hot-encoding-컬럼으로-만들어질-컬럼들을-지정해줄수-있다">one-hot encoding 컬럼으로 만들어질 컬럼들을 지정해줄수 있다.</h1>
<p>pd.get_dummies(df, columns=[&#39;Pclass&#39;, &#39;Sex&#39;, &#39;Embarked&#39;], dtype=int)</p>
<h1 id="dtypeint--를-주면-0-과-1-로-인코딩된다">dtype=int  를 주면, 0 과 1 로 인코딩된다.</h1>
<pre><code>| Index | PassenId | Survived | Name | Age | SibSp | Parch | Ticket | Fare | Cabin | Age_span | Pclass_1 | Pclass_2 | Pclass_3 | Sex_female | Sex_male | Embarked_C | Embarked_Q | Embarked_S |
| :--- | :---: | :---: | :--- | :---: | :---: | :---: | :--- | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| **0** | 1 | 0 | Braund, Mr. Owen Harris | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | 20 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
| **1** | 2 | 1 | Cumings, Mrs. John Bradley... | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | 30 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
| **2** | 3 | 1 | Heikkinen, Miss. Laina | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | 20 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 |
| **3** | 4 | 1 | Futrelle, Mrs. Jacques Heath... | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | 30 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
| **4** | 5 | 0 | Allen, Mr. William Henry | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | 30 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| **886** | 887 | 0 | Montvila, Rev. Juozas | 27.0 | 0 | 0 | 211536 | 13.0000 | NaN | 20 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
| **887** | 888 | 1 | Graham, Miss. Margaret Edith | 19.0 | 0 | 0 | 112053 | 30.0000 | B42 | 10 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
| **888** | 889 | 0 | Johnston, Miss. Catherine Helen... | NaN | 1 | 2 | W./C. 6607 | 23.4500 | NaN | -1 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 |
| **889** | 890 | 1 | Behr, Mr. Karl Howell | 26.0 | 0 | 0 | 111369 | 30.0000 | C148 | 20 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
| **890** | 891 | 0 | Dooley, Mr. Patrick | 32.0 | 0 | 0 | 370376 | 7.7500 | NaN | 30 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |

```python
# drop_first=True
pd.get_dummies(df, columns=[&#39;Pclass&#39;, &#39;Sex&#39;, &#39;Embarked&#39;], dtype=int, drop_first=True)

#서로 의존적인 컬럼 중 첫 번째 것을 삭제하여 데이터의 중복성을 제거하는 옵션&quot;**입니다.
#Sex_female이 0이면 당연히 Sex_male은 1이 됩니다.
#즉, 한 쪽만 알아도 나머지 값을 100% 알 수 있는 **정보의 중복(다중공선성)**이 발생합니다.</code></pre><hr>
<h2 id="6-그룹화-groupby">6. 그룹화 (Groupby)</h2>
<p>데이터를 특정 조건으로 묶어 통계량을 계산할 때 사용합니다.
(분할 Split -&gt; 적용 Apply -&gt; 병합 Combine 과정)</p>
<ul>
<li><strong>생성</strong>: <code>grouped = df.groupby(&#39;컬럼명&#39;)</code></li>
<li><strong>확인</strong>: <code>grouped.groups</code>, <code>grouped.size()</code></li>
<li><strong>연산</strong>: <code>grouped.mean()</code>, <code>grouped.sum()</code>, <code>grouped.count()</code> 등</li>
</ul>
<p>사용 예시들 모음</p>
<pre><code class="language-python">grouped_pclass = df.groupby(by=&#39;Pclass&#39;)

# groupby 객체의 속성
#   - groups -&gt; dict 형태
#   - key -&gt; 컬럼의 각 값
#   - value -&gt; 인덱스 값들의 list

# Pclass 의 값은 1, 2, 3 세 개 밖에 없었으니 그룹 개수는 3개다
grouped_pclass.groups

# groups 의 key 값은 &#39;Pclass&#39; 의 값들,
#          value 는 index 들의 list
/*
{1: [1, 3, 6, 11, 23, 27, 30, 31, 34, 35, 52, 54, 55, 61, 62, 64, 83, 88, 92, 96, 97, 102, 110, 118, 124, 136, 137, 139, 151, 155, 166, 168, 170, 174, 177, 185, 187, 194, 195, 209, 215, 218, 224, 230, 245, 248, 252, 256, 257, 258, 262, 263, 268, 269, 270, 273, 275, 284, 290, 291, 295, 297, 298, 299, 305, 306, 307, 309, 310, 311, 318, 319, 325, 329, 331, 332, 334, 336, 337, 339, 341, 351, 356, 366, 369, 370, 373, 375, 377, 380, 383, 390, 393, 412, 430, 434, 435, 438, 445, 447, ...], 
2: [9, 15, 17, 20, 21, 33, 41, 43, 53, 56, 58, 66, 70, 72, 78, 84, 98, 99, 117, 120, 122, 123, 133, 134, 135, 144, 145, 148, 149, 150, 161, 178, 181, 183, 190, 191, 193, 199, 211, 213, 217, 219, 221, 226, 228, 232, 234, 236, 237, 238, 239, 242, 247, 249, 259, 265, 272, 277, 288, 292, 303, 308, 312, 314, 316, 317, 322, 323, 327, 340, 342, 343, 344, 345, 346, 357, 361, 385, 387, 389, 397, 398, 399, 405, 407, 413, 416, 417, 418, 426, 427, 432, 437, 439, 440, 443, 446, 450, 458, 463, ...], 
3: [0, 2, 4, 5, 7, 8, 10, 12, 13, 14, 16, 18, 19, 22, 24, 25, 26, 28, 29, 32, 36, 37, 38, 39, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51, 57, 59, 60, 63, 65, 67, 68, 69, 71, 73, 74, 75, 76, 77, 79, 80, 81, 82, 85, 86, 87, 89, 90, 91, 93, 94, 95, 100, 101, 103, 104, 105, 106, 107, 108, 109, 111, 112, 113, 114, 115, 116, 119, 121, 125, 126, 127, 128, 129, 130, 131, 132, 138, 140, 141, 142, 143, 146, 147, 152, 153, 154, 156, 157, 158, 159, ...]}*/



# size()
#   각 group 별로 담겨 있는 데이터 개수 확인

grouped_pclass.size()
# Series   &lt;- df[&#39;Pclass&#39;].value_counts() 와 결과 같다</code></pre>
<table>
<thead>
<tr>
<th align="left">객실 등급 (Pclass)</th>
<th align="center">승객 수 (명)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>1등급 (1st Class)</strong></td>
<td align="center">216</td>
</tr>
<tr>
<td align="left"><strong>2등급 (2nd Class)</strong></td>
<td align="center">184</td>
</tr>
<tr>
<td align="left"><strong>3등급 (3rd Class)</strong></td>
<td align="center">491</td>
</tr>
</tbody></table>
<hr>
<h3 id="get_group">get_group()</h3>
<p>그룹별 DataFrame 리턴</p>
<pre><code class="language-python"># Pclass 가 1 인 그룹의  DataFrame
grouped_pclass.get_group(1)</code></pre>
<table>
<thead>
<tr>
<th align="left">인덱스</th>
<th align="center">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="left">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="left">Ticket</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>1</strong></td>
<td align="center">2</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Cumings, Mrs. John Bradley...</td>
<td align="center">female</td>
<td align="center">38.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">PC 17599</td>
<td align="center">71.2833</td>
<td align="center">C85</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>3</strong></td>
<td align="center">4</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath...</td>
<td align="center">female</td>
<td align="center">35.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">113803</td>
<td align="center">53.1000</td>
<td align="center">C123</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>6</strong></td>
<td align="center">7</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">McCarthy, Mr. Timothy J</td>
<td align="center">male</td>
<td align="center">54.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">17463</td>
<td align="center">51.8625</td>
<td align="center">E46</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>11</strong></td>
<td align="center">12</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Bonnell, Miss. Elizabeth</td>
<td align="center">female</td>
<td align="center">58.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">113783</td>
<td align="center">26.5500</td>
<td align="center">C103</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>23</strong></td>
<td align="center">24</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Sloper, Mr. William Thompson</td>
<td align="center">male</td>
<td align="center">28.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">113788</td>
<td align="center">35.5000</td>
<td align="center">A6</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="left"><strong>871</strong></td>
<td align="center">872</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Beckwith, Mrs. Richard Leonard...</td>
<td align="center">female</td>
<td align="center">47.0</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">11751</td>
<td align="center">52.5542</td>
<td align="center">D35</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>872</strong></td>
<td align="center">873</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">Carlsson, Mr. Frans Olof</td>
<td align="center">male</td>
<td align="center">33.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">695</td>
<td align="center">5.0000</td>
<td align="center">B51 B53 B55</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>879</strong></td>
<td align="center">880</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Potter, Mrs. Thomas Jr...</td>
<td align="center">female</td>
<td align="center">56.0</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">11767</td>
<td align="center">83.1583</td>
<td align="center">C50</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>887</strong></td>
<td align="center">888</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="center">female</td>
<td align="center">19.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">112053</td>
<td align="center">30.0000</td>
<td align="center">B42</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>889</strong></td>
<td align="center">890</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="center">male</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">111369</td>
<td align="center">30.0000</td>
<td align="center">C148</td>
<td align="center">C</td>
</tr>
</tbody></table>
<hr>
<h2 id="7-groupby-객체의-기초-연산-메소드">7. groupby 객체의 기초 연산 메소드</h2>
<ul>
<li>그룹 데이터에 적용 가능한 통계 함수(NaN은 제외하여 연산)</li>
<li>count - 데이터 개수</li>
<li>sum   - 데이터의 합</li>
<li>mean, std, var - 평균, 표준편차, 분산</li>
<li>min, max - 최소, 최대값</li>
</ul>
<pre><code># groupby() 로 쪼갬 &lt;-- split

# group 별로 count()연산 &lt;-- apply

# DataFrame 으로 합하여 리턴 &lt;-- combine    (원본과는 다른 새로운 DataFrame)
</code></pre><pre><code class="language-python">grouped_pclass.count()</code></pre>
<table>
<thead>
<tr>
<th align="left">Pclass</th>
<th align="center">Survived</th>
<th align="center">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left">*<em>1 *</em></td>
<td align="center">216</td>
<td align="center">216</td>
<td align="center">216</td>
<td align="center"><strong>186</strong></td>
<td align="center">216</td>
<td align="center">216</td>
<td align="center">216</td>
<td align="center"><strong>176</strong></td>
<td align="center">214</td>
</tr>
<tr>
<td align="left">*<em>2 *</em></td>
<td align="center">184</td>
<td align="center">184</td>
<td align="center">184</td>
<td align="center"><strong>173</strong></td>
<td align="center">184</td>
<td align="center">184</td>
<td align="center">184</td>
<td align="center"><strong>16</strong></td>
<td align="center">184</td>
</tr>
<tr>
<td align="left">*<em>3 *</em></td>
<td align="center">491</td>
<td align="center">491</td>
<td align="center">491</td>
<td align="center"><strong>355</strong></td>
<td align="center">491</td>
<td align="center">491</td>
<td align="center">491</td>
<td align="center"><strong>12</strong></td>
<td align="center">491</td>
</tr>
</tbody></table>
<pre><code class="language-python"># grouped_pclass.mean()  # 에러 .  문자열 타입도 연산하려 해서리..
grouped_pclass.mean(numeric_only=True)  # OK



# groupby 객체에 컬럼 선택 가능!
grouped_pclass[[&#39;PassengerId&#39;, &#39;Survived&#39;, &#39;Age&#39;]].mean()</code></pre>
<table>
<thead>
<tr>
<th align="left">Pclass</th>
<th align="center">PassengerId (Mean)</th>
<th align="center">Survived (Mean)</th>
<th align="center">Age (Mean)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>1 (1등석)</strong></td>
<td align="center">461.597222</td>
<td align="center"><strong>0.629630</strong></td>
<td align="center"><strong>38.233441</strong></td>
</tr>
<tr>
<td align="left"><strong>2 (2등석)</strong></td>
<td align="center">445.956522</td>
<td align="center"><strong>0.472826</strong></td>
<td align="center"><strong>29.877630</strong></td>
</tr>
<tr>
<td align="left"><strong>3 (3등석)</strong></td>
<td align="center">439.154786</td>
<td align="center"><strong>0.242363</strong></td>
<td align="center"><strong>25.140620</strong></td>
</tr>
</tbody></table>
<pre><code class="language-python"># 객식등급별 승객 나이의 평균
grouped_pclass[[&#39;Age&#39;]].mean()

# 동일 결과
grouped_pclass.mean(numeric_only=True)[[&#39;Age&#39;]]</code></pre>
<hr>
<h2 id="복수-columns로-grouping">복수 columns로 grouping</h2>
<ul>
<li>groupby에 column 리스트를 전달</li>
<li>통계함수를 적용한 결과는 multiindex를 갖는 dataframe<pre><code class="language-python">grouped_multi = df.groupby([&#39;Pclass&#39;, &#39;Sex&#39;])

</code></pre>
</li>
</ul>
<p>grouped_multi.size()</p>
<pre><code>| 객실 등급 (Pclass) | 성별 (Sex) | 승객 수 (명) |
| :--- | :--- | :---: |
| **1등급 (1st Class)** | 여성 (female) | **94** |
| | 남성 (male) | **122** |
| **2등급 (2nd Class)** | 여성 (female) | **76** |
| | 남성 (male) | **108** |
| **3등급 (3rd Class)** | 여성 (female) | **144** |
| | 남성 (male) | **347** |

```python
grouped_multi[[&#39;Survived&#39;, &#39;Age&#39;]].mean()</code></pre><table>
<thead>
<tr>
<th align="left">Pclass</th>
<th align="left">Sex</th>
<th align="center">Survived (Mean)</th>
<th align="center">Age (Mean)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>1 (1등석)</strong></td>
<td align="left"><strong>female</strong></td>
<td align="center">0.968085</td>
<td align="center">34.611765</td>
</tr>
<tr>
<td align="left"></td>
<td align="left"><strong>male</strong></td>
<td align="center">0.368852</td>
<td align="center">41.281386</td>
</tr>
<tr>
<td align="left"><strong>2 (2등석)</strong></td>
<td align="left"><strong>female</strong></td>
<td align="center">0.921053</td>
<td align="center">28.722973</td>
</tr>
<tr>
<td align="left"></td>
<td align="left"><strong>male</strong></td>
<td align="center">0.157407</td>
<td align="center">30.740707</td>
</tr>
<tr>
<td align="left"><strong>3 (3등석)</strong></td>
<td align="left"><strong>female</strong></td>
<td align="center">0.500000</td>
<td align="center">21.750000</td>
</tr>
<tr>
<td align="left"></td>
<td align="left"><strong>male</strong></td>
<td align="center">0.135447</td>
<td align="center">26.507589</td>
</tr>
</tbody></table>
<hr>
<h2 id="index를-이용한-groupbylevel">index를 이용한 groupby(level)</h2>
<ul>
<li><p>index가 있는 경우, groupby 함수에 level 사용 가능</p>
<ul>
<li>level은 index의 depth를 의미하며, 가장 왼쪽부터 0부터 증가</li>
</ul>
</li>
<li><p>set_index 함수
column 데이터를 index 레벨로 변경</p>
</li>
<li><p>reset_index 함수
인덱스 초기화</p>
</li>
</ul>
<pre><code class="language-python">df.set_index(&#39;Pclass&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/snow-jun-0/post/76312430-030a-4d49-b434-06f5329d268a/image.png" alt=""></p>
<pre><code class="language-python">
# level=0 인덱스를 기준으로 쪼갠다.
#  지금은 Embarked 가 index 이기 때문에 &#39;C&#39;, &#39;S&#39;, &#39;Q&#39; 으로 쪼개진다.

df.set_index(&#39;Embarked&#39;).groupby(level=0).size()</code></pre>
<p><img src="https://velog.velcdn.com/images/snow-jun-0/post/ff6c324f-7f6c-4219-be7d-bba68805ec46/image.png" alt=""></p>
<hr>
<h3 id="groupby함수">groupby(함수)</h3>
<ul>
<li>groupby(함수) =&gt;</li>
<li>함수의 매개변수는 index 다</li>
<li>함수가 리턴하는 값이 grouping 기준이 된다!<pre><code class="language-python"># 나이대별 생존률 구하기

</code></pre>
</li>
</ul>
<p>df.set_index(&#39;Age&#39;)</p>
<pre><code>![](https://velog.velcdn.com/images/snow-jun-0/post/37e20f10-f7e8-4101-b0ae-622a3db2896f/image.png)

```python
# groupby() 에 전달할 함수

df.set_index(&#39;Age&#39;).groupby(age_categorize).size() #연령별 분류</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/41a9afea-a542-4cdc-a809-25519f5c7b40/image.png" alt=""></p>
<pre><code class="language-python">df.set_index(&#39;Age&#39;).groupby(age_categorize)[&#39;Survived&#39;].mean() #연령별 생존자 평균 분류</code></pre>
<table>
<thead>
<tr>
<th align="center">연령대 (Age)</th>
<th align="center">생존율 (Survival Rate)</th>
</tr>
</thead>
<tbody><tr>
<td align="center">-1</td>
<td align="center">0.293785</td>
</tr>
<tr>
<td align="center">0</td>
<td align="center">0.612903</td>
</tr>
<tr>
<td align="center">10</td>
<td align="center">0.401961</td>
</tr>
<tr>
<td align="center">20</td>
<td align="center">0.350000</td>
</tr>
<tr>
<td align="center">30</td>
<td align="center">0.437126</td>
</tr>
<tr>
<td align="center">40</td>
<td align="center">0.382022</td>
</tr>
<tr>
<td align="center">50</td>
<td align="center">0.416667</td>
</tr>
<tr>
<td align="center">60</td>
<td align="center">0.315789</td>
</tr>
<tr>
<td align="center">70</td>
<td align="center">0.000000</td>
</tr>
<tr>
<td align="center">80</td>
<td align="center">1.000000</td>
</tr>
</tbody></table>
<hr>
<h2 id="도전--이름name-시작-알파벳으로-승객수-집계">도전 : 이름(Name) 시작 알파벳으로 승객수 집계</h2>
<pre><code class="language-python">
# 😎도전) 이름(Name) 시작 알파벳별로 승객수 집계
# groupby(함수) 활용
&quot;&quot;&quot;
A    51
B    72
C    69
D    43
...
...
U     1
V    15
W    33
Y     7
Z     3
&quot;&quot;&quot;
df[&#39;passenger&#39;] = 1

df.groupby(df[&#39;Name&#39;].str[0].str.upper())[&#39;passenger&#39;].sum()</code></pre>
<hr>
<h2 id="aggregate집계-함수-사용하기">aggregate(집계) 함수 사용하기</h2>
<ul>
<li>groupby 결과에 &#39;집계함수&#39;를 적용하여 그룹별 데이터 확인 가능</li>
<li>줄임형태: agg()<pre><code class="language-python"># 밑에 2개는 같은 결과
df.groupby([&#39;Pclass&#39;, &#39;Sex&#39;])[&#39;PassengerId&#39;].count()
df.groupby([&#39;Pclass&#39;, &#39;Sex&#39;])[&#39;PassengerId&#39;].aggregate(&quot;count&quot;)
</code></pre>
</li>
</ul>
<h1 id="dfgroupbypclass-sexpassengeridaggregatenpsum-오류-가능성-높음">df.groupby([&#39;Pclass&#39;, &#39;Sex&#39;])[&#39;PassengerId&#39;].aggregate(np.sum) 오류 가능성 높음</h1>
<p>df.groupby([&#39;Pclass&#39;, &#39;Sex&#39;])[&#39;PassengerId&#39;].aggregate([&quot;sum&quot;, &quot;mean&quot;, &quot;max&quot;])</p>
<pre><code>![](https://velog.velcdn.com/images/snow-jun-0/post/6fcf6080-e29c-4abf-9ac4-59d8ff4fad20/image.png)

---
## 도전: 각 객실 등급별 탑승승객인원, 생존자수, 생존률?
```python
df.groupby([&#39;Pclass&#39;]).aggregate(승객수=(&#39;passenger&#39;, &#39;sum&#39;),생존자=(&#39;Survived&#39;,&#39;sum&#39;),생존률=(&#39;Survived&#39;,&#39;mean&#39;))</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/0ead54cd-401b-4665-968e-1f280fe83e49/image.png" alt=""></p>
<hr>
<h2 id="8-정렬-및-구조-변경-pivot-stack">8. 정렬 및 구조 변경 (Pivot, Stack)</h2>
<h3 id="정렬">정렬</h3>
<ul>
<li><strong>값 기준</strong>: <code>df.sort_values(by=[&#39;컬럼1&#39;, &#39;컬럼2&#39;], ascending=[True, False])</code><pre><code class="language-python"># by=  정렬기준
#  컬럼명이나 컬럼들의 리스트
df.sort_values(by=&#39;Pclass&#39;)</code></pre>
<table>
<thead>
<tr>
<th align="center">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="left">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="center">Ticket</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
<th align="center">passenger</th>
</tr>
</thead>
<tbody><tr>
<td align="center">857</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Daly, Mr. Peter Denis</td>
<td align="center">male</td>
<td align="center">51.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">113055</td>
<td align="center">26.5500</td>
<td align="center">E17</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">858</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Swift, Mrs. Frederick Joel</td>
<td align="center">female</td>
<td align="center">48.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">17466</td>
<td align="center">25.9292</td>
<td align="center">D17</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">863</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Sage, Miss. Dorothy Edith</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">8</td>
<td align="center">2</td>
<td align="center">CA. 2343</td>
<td align="center">69.5500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">868</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">Roebling, Mr. Washington Augustus II</td>
<td align="center">male</td>
<td align="center">31.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">PC 17590</td>
<td align="center">50.4958</td>
<td align="center">A24</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">525</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">O&#39;Driscoll, Miss. Bridget</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">14311</td>
<td align="center">7.7500</td>
<td align="center">NaN</td>
<td align="center">Q</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="center">888</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="center">female</td>
<td align="center">19.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">112053</td>
<td align="center">30.0000</td>
<td align="center">B42</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">889</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Johnston, Miss. Catherine Helen</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">W./C. 6607</td>
<td align="center">23.4500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">890</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="center">male</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">111369</td>
<td align="center">30.0000</td>
<td align="center">C148</td>
<td align="center">C</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">891</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="center">male</td>
<td align="center">32.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">370376</td>
<td align="center">7.7500</td>
<td align="center">NaN</td>
<td align="center">Q</td>
<td align="center">1</td>
</tr>
</tbody></table>
</li>
</ul>
<pre><code class="language-python">#내림차순
df.sort_values(by=&#39;Pclass&#39;, ascending=False) 

# 우선 Pclass 오름차순, 그리고 Age 오름차순
df.sort_values(by=[&#39;Pclass&#39;, &#39;Age&#39;])   
</code></pre>
<table>
<thead>
<tr>
<th align="center">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="left">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="center">Ticket</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
<th align="center">passenger</th>
</tr>
</thead>
<tbody><tr>
<td align="center">306</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Allison, Master. Hudson Trevor</td>
<td align="center">male</td>
<td align="center">0.92</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">113781</td>
<td align="center">151.5500</td>
<td align="center">C22 C26</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">298</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="left">Allison, Miss. Helen Loraine</td>
<td align="center">female</td>
<td align="center">2.00</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">113781</td>
<td align="center">151.5500</td>
<td align="center">C22 C26</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">446</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Dodge, Master. Washington</td>
<td align="center">male</td>
<td align="center">4.00</td>
<td align="center">0</td>
<td align="center">2</td>
<td align="center">33638</td>
<td align="center">81.8583</td>
<td align="center">A34</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">803</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Carter, Master. William Thornton II</td>
<td align="center">male</td>
<td align="center">11.00</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">113760</td>
<td align="center">120.0000</td>
<td align="center">B96 B98</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">436</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Carter, Miss. Lucile Polk</td>
<td align="center">female</td>
<td align="center">14.00</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">113760</td>
<td align="center">120.0000</td>
<td align="center">B96 B98</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="center">860</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Razi, Mr. Raihed</td>
<td align="center">male</td>
<td align="center">NaN</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">2629</td>
<td align="center">7.2292</td>
<td align="center">NaN</td>
<td align="center">C</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">864</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Sage, Miss. Dorothy Edith &quot;Dolly&quot;</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">8</td>
<td align="center">2</td>
<td align="center">CA. 2343</td>
<td align="center">69.5500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">869</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">van Melkebeke, Mr. Philemon</td>
<td align="center">male</td>
<td align="center">NaN</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">345777</td>
<td align="center">9.5000</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">879</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Laleff, Mr. Kristo</td>
<td align="center">male</td>
<td align="center">NaN</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">349217</td>
<td align="center">7.8958</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">889</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Johnston, Miss. Catherine Helen &quot;Carrie&quot;</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">W./C. 6607</td>
<td align="center">23.4500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center"># Pclass 오름차순, Age 내림차순</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">df.sort_values(by=[&#39;Pclass&#39;, &#39;Age&#39;], ascending=[True, False])</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<pre><code>---
* **인덱스 기준**: `df.sort_index()`
```python
# sort_index() index 기준으로 정렬
df.sort_index(ascending=False)

# index 기준으로 내림차순</code></pre><table>
<thead>
<tr>
<th align="center">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="left">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="center">Ticket</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
<th align="center">passenger</th>
</tr>
</thead>
<tbody><tr>
<td align="center">891</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="center">male</td>
<td align="center">32.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">370376</td>
<td align="center">7.7500</td>
<td align="center">NaN</td>
<td align="center">Q</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">890</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="center">male</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">111369</td>
<td align="center">30.0000</td>
<td align="center">C148</td>
<td align="center">C</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">889</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Johnston, Miss. Catherine Helen</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">W./C. 6607</td>
<td align="center">23.4500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">888</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="center">female</td>
<td align="center">19.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">112053</td>
<td align="center">30.0000</td>
<td align="center">B42</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">887</td>
<td align="center">0</td>
<td align="center">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="center">male</td>
<td align="center">27.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">211536</td>
<td align="center">13.0000</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="center">5</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="center">male</td>
<td align="center">35.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">373450</td>
<td align="center">8.0500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">4</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath</td>
<td align="center">female</td>
<td align="center">35.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">113803</td>
<td align="center">53.1000</td>
<td align="center">C123</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="center">female</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">STON/O2. 3101282</td>
<td align="center">7.9250</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Cumings, Mrs. John Bradley</td>
<td align="center">female</td>
<td align="center">38.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">PC 17599</td>
<td align="center">71.2833</td>
<td align="center">C85</td>
<td align="center">C</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="center">male</td>
<td align="center">22.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">A/5 21171</td>
<td align="center">7.2500</td>
<td align="center">NaN</td>
<td align="center">S</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center"># 컬럼 이름 오름차순 정렬.</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">df.sort_index(axis=1)</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
<td align="center"></td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">Index</td>
<td align="center">Age</td>
<td align="center">Cabin</td>
<td align="left">Embarked</td>
<td align="center">Fare</td>
<td align="center">Name</td>
<td align="center">Parch</td>
<td align="center">PassengerId</td>
<td align="center">Pclass</td>
<td align="center">Sex</td>
<td align="center">SibSp</td>
<td align="center">Survived</td>
<td align="center">Ticket</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="left">:---:</td>
<td align="center">:---:</td>
<td align="center">:---</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">0</td>
<td align="center">22.0</td>
<td align="center">NaN</td>
<td align="left">S</td>
<td align="center">7.2500</td>
<td align="center">Braund, Mr. Owen Harris</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="center">male</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">A/5 21171</td>
</tr>
<tr>
<td align="center">1</td>
<td align="center">38.0</td>
<td align="center">C85</td>
<td align="left">C</td>
<td align="center">71.2833</td>
<td align="center">Cumings, Mrs. John Bradley</td>
<td align="center">0</td>
<td align="center">2</td>
<td align="center">1</td>
<td align="center">female</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="center">PC 17599</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center">26.0</td>
<td align="center">NaN</td>
<td align="left">S</td>
<td align="center">7.9250</td>
<td align="center">Heikkinen, Miss. Laina</td>
<td align="center">0</td>
<td align="center">3</td>
<td align="center">3</td>
<td align="center">female</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">STON/O2. 3101282</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">35.0</td>
<td align="center">C123</td>
<td align="left">S</td>
<td align="center">53.1000</td>
<td align="center">Futrelle, Mrs. Jacques Heath</td>
<td align="center">0</td>
<td align="center">4</td>
<td align="center">1</td>
<td align="center">female</td>
<td align="center">1</td>
<td align="center">1</td>
<td align="center">113803</td>
</tr>
<tr>
<td align="center">4</td>
<td align="center">35.0</td>
<td align="center">NaN</td>
<td align="left">S</td>
<td align="center">8.0500</td>
<td align="center">Allen, Mr. William Henry</td>
<td align="center">0</td>
<td align="center">5</td>
<td align="center">3</td>
<td align="center">male</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">373450</td>
</tr>
<tr>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="center">886</td>
<td align="center">27.0</td>
<td align="center">NaN</td>
<td align="left">S</td>
<td align="center">13.0000</td>
<td align="center">Montvila, Rev. Juozas</td>
<td align="center">0</td>
<td align="center">887</td>
<td align="center">2</td>
<td align="center">male</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">211536</td>
</tr>
<tr>
<td align="center">887</td>
<td align="center">19.0</td>
<td align="center">B42</td>
<td align="left">S</td>
<td align="center">30.0000</td>
<td align="center">Graham, Miss. Margaret Edith</td>
<td align="center">0</td>
<td align="center">888</td>
<td align="center">1</td>
<td align="center">female</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">112053</td>
</tr>
<tr>
<td align="center">888</td>
<td align="center">NaN</td>
<td align="center">NaN</td>
<td align="left">S</td>
<td align="center">23.4500</td>
<td align="center">Johnston, Miss. Catherine Helen</td>
<td align="center">2</td>
<td align="center">889</td>
<td align="center">3</td>
<td align="center">female</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="center">W./C. 6607</td>
</tr>
<tr>
<td align="center">889</td>
<td align="center">26.0</td>
<td align="center">C148</td>
<td align="left">C</td>
<td align="center">30.0000</td>
<td align="center">Behr, Mr. Karl Howell</td>
<td align="center">0</td>
<td align="center">890</td>
<td align="center">1</td>
<td align="center">male</td>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">111369</td>
</tr>
<tr>
<td align="center">890</td>
<td align="center">32.0</td>
<td align="center">NaN</td>
<td align="left">Q</td>
<td align="center">7.7500</td>
<td align="center">Dooley, Mr. Patrick</td>
<td align="center">0</td>
<td align="center">891</td>
<td align="center">3</td>
<td align="center">male</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="center">370376</td>
</tr>
</tbody></table>
<hr>
<h3 id="pivot--pivot-table">Pivot / Pivot Table</h3>
<ul>
<li><strong>pivot</strong>: 데이터 재구조화 (중복 데이터가 있으면 에러 발생)</li>
<li><strong>pivot_table</strong>: 중복 데이터가 있을 때 <code>aggfunc</code>를 통해 요약 가능 (기본값은 평균)</li>
</ul>
<h4 id="pivot">Pivot</h4>
<p><strong>예시</strong></p>
<pre><code class="language-python">df = pd.DataFrame({
    &#39;지역&#39;: [&#39;서울&#39;, &#39;서울&#39;, &#39;서울&#39;, &#39;경기&#39;, &#39;경기&#39;, &#39;부산&#39;, &#39;서울&#39;, &#39;서울&#39;, &#39;부산&#39;, &#39;경기&#39;, &#39;경기&#39;, &#39;경기&#39;],
    &#39;요일&#39;: [&#39;월요일&#39;, &#39;화요일&#39;, &#39;수요일&#39;, &#39;월요일&#39;, &#39;화요일&#39;, &#39;월요일&#39;, &#39;목요일&#39;, &#39;금요일&#39;, &#39;화요일&#39;, &#39;수요일&#39;, &#39;목요일&#39;, &#39;금요일&#39;],
    &#39;강수량&#39;: [100, 80, 1000, 200, 200, 100, 50, 100, 200, 100, 50, 100],
    &#39;강수확률&#39;: [80, 70, 90, 10, 20, 30, 50, 90, 20, 80, 50, 10]
                  })

df</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">지역</th>
<th align="center">요일</th>
<th align="center">강수량</th>
<th align="center">강수확률</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0</td>
<td align="center">서울</td>
<td align="center">월요일</td>
<td align="center">100</td>
<td align="center">80</td>
</tr>
<tr>
<td align="center">1</td>
<td align="center">서울</td>
<td align="center">화요일</td>
<td align="center">80</td>
<td align="center">70</td>
</tr>
<tr>
<td align="center">2</td>
<td align="center">서울</td>
<td align="center">수요일</td>
<td align="center">1000</td>
<td align="center">90</td>
</tr>
<tr>
<td align="center">3</td>
<td align="center">경기</td>
<td align="center">월요일</td>
<td align="center">200</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">4</td>
<td align="center">경기</td>
<td align="center">화요일</td>
<td align="center">200</td>
<td align="center">20</td>
</tr>
<tr>
<td align="center">5</td>
<td align="center">부산</td>
<td align="center">월요일</td>
<td align="center">100</td>
<td align="center">30</td>
</tr>
<tr>
<td align="center">6</td>
<td align="center">서울</td>
<td align="center">목요일</td>
<td align="center">50</td>
<td align="center">50</td>
</tr>
<tr>
<td align="center">7</td>
<td align="center">서울</td>
<td align="center">금요일</td>
<td align="center">100</td>
<td align="center">90</td>
</tr>
<tr>
<td align="center">8</td>
<td align="center">부산</td>
<td align="center">화요일</td>
<td align="center">200</td>
<td align="center">20</td>
</tr>
<tr>
<td align="center">9</td>
<td align="center">경기</td>
<td align="center">수요일</td>
<td align="center">100</td>
<td align="center">80</td>
</tr>
<tr>
<td align="center">10</td>
<td align="center">경기</td>
<td align="center">목요일</td>
<td align="center">50</td>
<td align="center">50</td>
</tr>
<tr>
<td align="center">11</td>
<td align="center">경기</td>
<td align="center">금요일</td>
<td align="center">100</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">#전치</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">df.T</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center"></td>
<td align="center">0</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center"><strong>지역</strong></td>
<td align="center">서울</td>
<td align="center">서울</td>
<td align="center">서울</td>
<td align="center">경기</td>
</tr>
<tr>
<td align="center"><strong>요일</strong></td>
<td align="center">월요일</td>
<td align="center">화요일</td>
<td align="center">수요일</td>
<td align="center">월요일</td>
</tr>
<tr>
<td align="center"><strong>강수량</strong></td>
<td align="center">100</td>
<td align="center">80</td>
<td align="center">1000</td>
<td align="center">200</td>
</tr>
<tr>
<td align="center"><strong>강수확률</strong></td>
<td align="center">80</td>
<td align="center">70</td>
<td align="center">90</td>
<td align="center">10</td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center"># pivot()</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">- dataframe의 형태를 변경</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="center">- 인덱스, 컬럼, 데이터로 사용할 컬럼을 명시</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<h1 id="pivotindexnone-columnsnone-valuesnone">pivot(index=None, columns=None, values=None)</h1>
<h1 id="index-로-지정할-컬럼">index 로 지정할 컬럼</h1>
<h1 id="column-으로-지정할-컬럼">column 으로 지정할 컬럼</h1>
<h1 id="values-나머지-채울-값들">values 나머지 채울 값들.</h1>
<h1 id="이제-지역별로index--요일별column-강수량강수확률value을-보고싶다">이제 지역별로(index)  요일별(column) 강수량/강수확률(value)을 보고싶다</h1>
<p>df.pivot(index=&#39;지역&#39;, columns=&#39;요일&#39;)</p>
<pre><code>![](https://velog.velcdn.com/images/snow-jun-0/post/8bcc317e-7a6e-49c7-bed4-f5307f03a258/image.png)
```python
# ↑ 월~ 금 &#39;요일&#39; 이 두번 들어감.  강수량, 강수확률 &lt;-- 2개의 컬럼이 있기 때문
# 부산 의 경우 금/목/수  데이터가 없다.


# &#39;지역&#39;, &#39;요일&#39; 이 같은 데이터가 중복되어 있으면 에러난다.!
df.loc[len(df)] = pd.Series([&#39;경기&#39;, &#39;금요일&#39;, 111, 11], index=[&#39;지역&#39;, &#39;요일&#39;, &#39;강수량&#39;, &#39;강수확률&#39;])
df</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/0f81b9fa-8989-47d8-abde-d0d90783be90/image.png" alt=""></p>
<pre><code class="language-python">df.pivot(index=&#39;지역&#39;, columns=&#39;요일&#39;)</code></pre>
<p><img src="https://velog.velcdn.com/images/snow-jun-0/post/2f136c63-260c-4f06-bd53-cff33ed88cb2/image.png" alt=""></p>
<hr>
<pre><code>#삭제
df.drop(12, inplace=True)
#인덱스 12인 자료 삭제

# 거꾸로 해보자
df.pivot(index=&#39;요일&#39;, columns=&#39;지역&#39;)</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/fb31ec13-9100-40c0-a3df-15e87b0ded32/image.png" alt=""></p>
<pre><code>df.pivot(index=&#39;요일&#39;, columns=&#39;지역&#39;, values=&#39;강수량&#39;)
#df.pivot(index=&#39;요일&#39;, columns=&#39;지역&#39;)[&#39;강수량&#39;] 와 같다. </code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/31cc7583-b291-4b44-a232-97d23d5b1e1a/image.png" alt=""></p>
<hr>
<h4 id="pivot_table">Pivot_table()</h4>
<ul>
<li><p>기능적으로 pivot과 동일</p>
</li>
<li><p>pivot과의 차이점</p>
<ul>
<li>중복되는 모호한 값이 있을 경우, aggregation 함수 사용하여 값을 채움<pre><code>pd.pivot_table(df, index=&#39;지역&#39;, columns=&#39;요일&#39;)  
</code></pre></li>
</ul>
<h1 id="중복데이터를-만들어-본다--서울-월요일">중복데이터를 만들어 본다.  서울-월요일</h1>
<p>df2 = pd.DataFrame({
 &#39;지역&#39;: [&#39;서울&#39;, &#39;서울&#39;, &#39;서울&#39;, &#39;경기&#39;, &#39;경기&#39;, &#39;부산&#39;, &#39;서울&#39;, &#39;서울&#39;, &#39;부산&#39;, &#39;경기&#39;, &#39;경기&#39;, &#39;경기&#39;],
 &#39;요일&#39;: [&#39;월요일&#39;, &#39;월요일&#39;, &#39;수요일&#39;, &#39;월요일&#39;, &#39;화요일&#39;, &#39;월요일&#39;, &#39;목요일&#39;, &#39;금요일&#39;, &#39;화요일&#39;, &#39;수요일&#39;, &#39;목요일&#39;, &#39;금요일&#39;],
 &#39;강수량&#39;: [100, 80, 1000, 200, 200, 100, 50, 100, 200, 100, 50, 100],
 &#39;강수확률&#39;: [80, 70, 90, 10, 20, 30, 50, 90, 20, 80, 50, 10]</p>
<pre><code>           })</code></pre></li>
</ul>
<p>df2  # 서울 - 월요일 &lt;-- 2개 있다.  </p>
<h1 id="pivot-은-중복된-엔트리가-있으면-오류발생">pivot() 은 중복된 엔트리가 있으면 오류발생</h1>
<h1 id="pivot_table-은-중복된-엔트리는-aggfunc-를-사용하여-새로운-값-대체">pivot_table() 은 중복된 엔트리는 aggfunc= 를 사용하여 새로운 값 대체</h1>
<h1 id="aggfuncmean--기본값">aggfunc=&#39;mean&#39;  (기본값)</h1>
<h1 id="서울-월요일의-평균값-으로-채워진다-디폴트">서울, 월요일의 &#39;평균값&#39; 으로 채워진다. (디폴트)</h1>
<p>pd.pivot_table(df2, index=&#39;지역&#39;, columns=&#39;요일&#39;, aggfunc=&#39;mean&#39;)</p>
<pre><code>![](https://velog.velcdn.com/images/snow-jun-0/post/add6bf09-6eb4-4548-9d95-dc4db27effd2/image.png)</code></pre><h1 id="max로-바꿀-수-있다">max로 바꿀 수 있다.</h1>
<p>pd.pivot_table(df2, index=&#39;지역&#39;, columns=&#39;요일&#39;, aggfunc=&#39;max&#39;)  </p>
<pre><code>
---
### Stack &amp; Unstack
* **stack**: 컬럼 레벨 -&gt; 인덱스 레벨 (데이터를 아래로 쌓음)
* **unstack**: 인덱스 레벨 -&gt; 컬럼 레벨 (옆으로 펼침)
  - 둘은 역의 관계에 있음
```python 
new_df = df.set_index([&#39;지역&#39;, &#39;요일&#39;])
new_df 

#컬럼 레벨 -&gt; 인덱스 레벨</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/451e4f67-1aa8-43b0-b5ea-393db09c30c8/image.png" alt=""></p>
<pre><code class="language-python"># unstack() : index(row) -&gt; column

# unstack(level=-1, fill_value=None)
#   level : 인덱스의 레벨
#            new_df 의 경우 지역 의 인덱스 레벨이 0 이다
#                 -1 은 오른쪽 끝 인덱스 &#39;요일&#39; 이 컬럼이다.

# level=-1 (디폴트) 였던 &#39;요일&#39; index 가 &#39;컬럼&#39; 으로 올라간다
new_df.unstack()
</code></pre>
<p><img src="https://velog.velcdn.com/images/snow-jun-0/post/aa1a1d41-fa19-4d0a-9b75-41a3303ffca4/image.png" alt=""></p>
<pre><code class="language-python"># level=0  인텍스가 컬럼으로 올라감
new_df.unstack(0)
</code></pre>
<p><img src="https://velog.velcdn.com/images/snow-jun-0/post/7b6d9f68-15d3-47ce-b7a1-62dd16c4d04c/image.png" alt=""></p>
<pre><code># stack() : column -&gt; index(row)
# stack(level=-1, dropna=True)
#         level : 컬럼의 레벨

df2 = new_df.unstack(0)

# level=0 의 컬럼 이 index 로 내려옴
df2.stack(0, future_stack=True)</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/bf536a7b-4b6b-4f6e-866d-ce7e5bd1d2b3/image.png" alt=""></p>
<pre><code>df2.stack(1)</code></pre><p><img src="https://velog.velcdn.com/images/snow-jun-0/post/f839a5f7-5c89-4aba-b4f6-b0b8af2979c6/image.png" alt=""></p>
<pre><code># 모든 컬럼을 다 내리면? (즉 컬럼이 없어지면) 결과는 -&gt; Series
df2.stack().stack()

# [도전]
# 두 index 위치 (level)  변경하기
new_df.unstack(0).stack()
</code></pre><hr>
<h2 id="8-데이터-병합-concat">8. 데이터 병합 (Concat)</h2>
<p>여러 데이터프레임을 하나로 합칩니다.</p>
<ul>
<li><p><strong>행 단위(axis=0)</strong>: 위아래로 이어 붙임</p>
<pre><code class="language-python"># 행 방향으로 병합 (axis=0)
pd.concat([df1, df2])</code></pre>
</li>
<li><p><strong>열 단위(axis=1)</strong>: 좌우로 옆에 붙임</p>
<pre><code class="language-python"># 열 방향 병합 (axis=1)
pd.concat([df1, df2], axis=1)</code></pre>
</li>
<li><p><strong>함수</strong>: <code>pd.concat([df1, df2], axis=0)</code></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] - 6일차(상속)]]></title>
            <link>https://velog.io/@snow-jun-0/g5wy8ov7</link>
            <guid>https://velog.io/@snow-jun-0/g5wy8ov7</guid>
            <pubDate>Thu, 19 Feb 2026 08:55:59 GMT</pubDate>
            <description><![CDATA[<h1 id="c-객체지향-프로그래밍-핵심-정리-상속-접근-제어-다형성">[C++] 객체지향 프로그래밍 핵심 정리: 상속, 접근 제어, 다형성</h1>
<p>C++에서 상속 관계를 다룰 때 가장 중요한 생성자/소멸자의 호출 순서와 멤버 변수에 대한 접근 권한, 그리고 객체지향의 꽃인 다형성(Polymorphism)에 대해 예제 코드를 통해 정리합니다.</p>
<hr>
<h2 id="1-상속-관계에서의-생성자와-소멸자-호출-순서">1. 상속 관계에서의 생성자와 소멸자 호출 순서</h2>
<p>상속 관계에서 자식 클래스의 객체가 생성될 때, 부모 클래스의 생성자는 <strong>반드시</strong> 호출됩니다. 또한, 클래스 내부에 멤버 객체(Composition)가 있다면 해당 객체의 생성자도 순서에 따라 호출됩니다.</p>
<h3 id="예제-코드-빙수-만들기">예제 코드: 빙수 만들기</h3>
<pre><code class="language-cpp">    /* - 부모 클래스 생성자 -&gt; 자식 클래스 멤버 객체 생성자 -&gt; 자식 클래스 생성자 순으로 실행
    - 소멸자는 생성자의 역순으로 실행
    */

    #include &lt;iostream&gt;
    using namespace std;

    class Ice {
    public:
        Ice() { cout &lt;&lt; &quot;Ice() 생성&quot; &lt;&lt; endl; }
        ~Ice() { cout &lt;&lt; &quot;~Ice() 소멸&quot; &lt;&lt; endl; }
    };

    class Pat {
    public:
        Pat() { cout &lt;&lt; &quot;Pat() 생성&quot; &lt;&lt; endl; }
        ~Pat() { cout &lt;&lt; &quot;~Pat() 소멸&quot; &lt;&lt; endl; }
    };

    class Bingsoo {
    public:
        Bingsoo() { cout &lt;&lt; &quot;Bingsoo() 부모 생성&quot; &lt;&lt; endl; }
        ~Bingsoo() { cout &lt;&lt; &quot;~Bingsoo() 부모 소멸&quot; &lt;&lt; endl; }
    private:
        Ice ice; // HAS-A 관계(포함관계 != 상속관계)
    };

    class PatBingsoo : public Bingsoo {
    public:
        PatBingsoo() { cout &lt;&lt; &quot;PatBingsoo() 자식 생성&quot; &lt;&lt; endl; }
        ~PatBingsoo() { cout &lt;&lt; &quot;~PatBingsoo() 자식 소멸&quot; &lt;&lt; endl; }
    private:
        Pat pat; // HAS-A 관계
    };

    int main() {
        cout &lt;&lt; &quot;== 객체 생성 시작 ==&quot; &lt;&lt; endl;
        PatBingsoo* p = new PatBingsoo();
        cout &lt;&lt; &quot;== 객체 소멸 시작 ==&quot; &lt;&lt; endl;
        delete p;
        return 0;
    }


//출력 결과
== 객체 생성 시작 ==
Ice() 생성             // 1. 부모 클래스의 멤버 객체 생성
Bingsoo() 부모 생성     // 2. 부모 클래스 생성자 실행
Pat() 생성             // 3. 자식 클래스의 멤버 객체 생성
PatBingsoo() 자식 생성  // 4. 자식 클래스 생성자 실행
== 객체 소멸 시작 ==
~PatBingsoo() 자식 소멸 // 5. 자식 클래스 소멸자 실행 (생성의 역순 시작)
~Pat() 소멸            // 6. 자식 클래스의 멤버 객체 소멸
~Bingsoo() 부모 소멸    // 7. 부모 클래스 소멸자 실행
~Ice() 소멸            // 8. 부모 클래스의 멤버 객체 소멸</code></pre>
<h2 id="c-생성자-호출-순서">[C++] 생성자 호출 순서</h2>
<p>C++에서 상속(<code>IS-A</code>)과 포함(<code>HAS-A</code>) 관계가 섞여 있을 때, 객체가 생성되는 논리적인 단계를 뜯어보겠습니다.</p>
<hr>
<h3 id="1-생성의-대원칙-기초가-있어야-집을-짓는다">1. 생성의 대원칙: &quot;기초가 있어야 집을 짓는다&quot;</h3>
<p>객체가 생성될 때 컴파일러는 내부적으로 다음의 순서를 엄격히 지킵니다.</p>
<ol>
<li><strong>부모 클래스(Base Class) 영역</strong>을 먼저 구성한다.</li>
<li>부모 영역 안에서도 <strong>멤버 변수(Has-a)</strong>들을 먼저 메모리에 올린다.</li>
<li>그 후 <strong>부모의 생성자 몸체(<code>{}</code>)</strong>를 실행한다.</li>
<li>부모가 완성되면 <strong>자식 클래스(Derived Class) 영역</strong>으로 내려온다.</li>
<li>자식의 <strong>멤버 변수(Has-a)</strong>들을 메모리에 올린다.</li>
<li>마지막으로 <strong>자식의 생성자 몸체(<code>{}</code>)</strong>를 실행한다.</li>
</ol>
<hr>
<h3 id="2-빙수-예제로-보는-상세-프로세스">2. 빙수 예제로 보는 상세 프로세스</h3>
<p>질문하신 <code>PatBingsoo</code> 객체를 생성할 때의 내부 동작을 단계별로 보겠습니다.</p>
<h4 id="1단계-부모-클래스bingsoo로-진입">1단계: 부모 클래스(Bingsoo)로 진입</h4>
<p><code>PatBingsoo</code>는 <code>Bingsoo</code>를 상속받았으므로, 자식의 몸체를 실행하기 전에 부모인 <code>Bingsoo</code>를 먼저 만들어야 합니다. 그래서 제어권이 <code>Bingsoo</code>로 넘어갑니다.</p>
<h4 id="2단계-부모의-내부-재료ice-준비-★-여기가-포인트">2단계: 부모의 내부 재료(Ice) 준비 (★ 여기가 포인트!)</h4>
<p><code>Bingsoo</code> 클래스 안을 보니 <code>Ice ice;</code>라는 멤버 변수가 있습니다. </p>
<ul>
<li><strong>논리:</strong> &quot;빙수라는 객체가 온전히 존재하려면, 그 안에 포함된 얼음(Ice)부터 메모리에 존재해야 한다.&quot; </li>
<li>따라서 <code>Bingsoo</code>의 생성자 <code>{}</code>가 실행되기 직전에, 멤버 변수인 <code>Ice</code>의 생성자가 먼저 호출됩니다.</li>
<li><strong>출력:</strong> <code>Ice() 생성</code></li>
</ul>
<h4 id="3단계-부모-클래스-생성자-실행">3단계: 부모 클래스 생성자 실행</h4>
<p>재료(Ice)가 준비되었으니 이제 <code>Bingsoo</code>의 생성자 몸체를 실행합니다.</p>
<ul>
<li><strong>출력:</strong> <code>Bingsoo() 부모 생성</code></li>
</ul>
<h4 id="4단계-자식의-내부-재료pat-준비">4단계: 자식의 내부 재료(Pat) 준비</h4>
<p>부모 영역이 완전히 만들어졌으니 다시 자식인 <code>PatBingsoo</code>로 돌아옵니다. 자식 클래스 안을 보니 <code>Pat pat;</code>이라는 멤버가 있네요.</p>
<ul>
<li><strong>논리:</strong> &quot;팥빙수가 완성되기 전에 팥(Pat)이 먼저 준비되어야 한다.&quot;</li>
<li><strong>출력:</strong> <code>Pat() 생성</code></li>
</ul>
<h4 id="5단계-자식-클래스-생성자-실행">5단계: 자식 클래스 생성자 실행</h4>
<p>이제 모든 재료가 준비되었으니 최종적으로 <code>PatBingsoo</code>의 생성자 몸체를 실행합니다.</p>
<ul>
<li><strong>출력:</strong> <code>PatBingsoo() 자식 생성</code></li>
</ul>
<hr>
<h2 id="3-한-줄-요약">3. 한 줄 요약</h2>
<blockquote>
<p><strong>&quot;부모의 멤버 -&gt; 부모의 본체 -&gt; 자식의 멤버 -&gt; 자식의 본체&quot;</strong></p>
</blockquote>
<p>소멸자는 이 과정을 정확히 <strong>거울 보듯 반대(역순)</strong>로 진행합니다. 
가장 마지막에 완성된 자식의 본체부터 부수기 시작해서, 가장 먼저 만들어졌던 부모의 재료(<code>Ice</code>)를 가장 나중에 치우는 것이죠.</p>
<hr>
<h2 id="4-왜-이렇게-설계되었을까">4. 왜 이렇게 설계되었을까?</h2>
<p>만약 부모의 본체가 실행되기 전에 부모의 멤버(<code>Ice</code>)가 생성되지 않는다면, 부모 생성자 안에서 <code>ice</code> 변수를 사용하려고 할 때 에러가 날 것입니다. C++은 <strong>&quot;사용하기 전에 반드시 완벽하게 준비시킨다&quot;</strong>는 철학을 가지고 있기 때문에 이런 순서를 가집니다.</p>
<h1 id="c-객체지향의-핵심-상속is-a과-포함has-a-관계-분석">[C++] 객체지향의 핵심: 상속(IS-A)과 포함(HAS-A) 관계 분석</h1>
<pre><code>## 1. 포함 관계(Composition)란?
포함 관계는 한 클래스가 다른 클래스의 객체를 자신의 멤버 변수로 가지는 상태를 말합니다. 
상속이 &quot;A는 B이다(IS-A)&quot;라면, 포함은 &quot;A는 B를 가지고 있다(HAS-A)&quot;는 논리입니다.

* 예제에서의 포함 관계:
    - Bingsoo 클래스는 Ice 객체를 멤버로 가짐 (빙수는 얼음을 가짐)
    - PatBingsoo 클래스는 Pat 객체를 멤버로 가짐 (팥빙수는 팥을 가짐)

## 2. 포함 관계의 특징
- 생명 주기 종속: 호스트 객체(Bingsoo)가 생성될 때 부품 객체(Ice)도 함께 생성되고, 호스트가 소멸할 때 부품도 운명을 같이합니다.
- 부품의 우선순위: 객체를 조립할 때 부품이 먼저 준비되어야 본체를 완성할 수 있듯, 생성자 호출 시 멤버 객체의 생성자가 본체 생성자보다 먼저 실행됩니다.

## 3. 전체 코드 및 실행 순서 상세

#include &lt;iostream&gt;
using namespace std;

class Ice {
public:
    Ice() { cout &lt;&lt; &quot;Ice() 부품 생성&quot; &lt;&lt; endl; }
    ~Ice() { cout &lt;&lt; &quot;~Ice() 부품 소멸&quot; &lt;&lt; endl; }
};

class Pat {
public:
    Pat() { cout &lt;&lt; &quot;Pat() 부품 생성&quot; &lt;&lt; endl; }
    ~Pat() { cout &lt;&lt; &quot;~Pat() 부품 소멸&quot; &lt;&lt; endl; }
};

class Bingsoo {
public:
    Bingsoo() { cout &lt;&lt; &quot;Bingsoo() 부모 본체 생성&quot; &lt;&lt; endl; }
    ~Bingsoo() { cout &lt;&lt; &quot;~Bingsoo() 부모 본체 소멸&quot; &lt;&lt; endl; }
private:
    Ice ice; // [포함 관계] 빙수의 부품
};

class PatBingsoo : public Bingsoo {
public:
    PatBingsoo() { cout &lt;&lt; &quot;PatBingsoo() 자식 본체 생성&quot; &lt;&lt; endl; }
    ~PatBingsoo() { cout &lt;&lt; &quot;~PatBingsoo() 자식 본체 소멸&quot; &lt;&lt; endl; }
private:
    Pat pat; // [포함 관계] 팥빙수의 부품
};

int main() {
    cout &lt;&lt; &quot;== 1. 객체 생성 과정 ==&quot; &lt;&lt; endl;
    PatBingsoo* p = new PatBingsoo();

    // 생성 순서 설명:
    // 1단계 [부모 생성 시작]: 부모의 부품(Ice) 생성 -&gt; 부모 본체(Bingsoo) 생성
    // 2단계 [자식 생성 시작]: 자식의 부품(Pat) 생성 -&gt; 자식 본체(PatBingsoo) 생성

    cout &lt;&lt; endl &lt;&lt; &quot;== 2. 객체 소멸 과정 ==&quot; &lt;&lt; endl;
    delete p;

    // 소멸 순서 설명 (생성의 역순):
    // 1단계 [자식 소멸]: 자식 본체 소멸 -&gt; 자식 부품(Pat) 소멸
    // 2단계 [부모 소멸]: 부모 본체 소멸 -&gt; 부모 부품(Ice) 소멸

    return 0;
}

## 4. 요약 및 주의사항
- 포함된 멤버 변수는 &#39;조립품&#39;과 같아서 본체 클래스의 생성자 몸체({ })가 실행되기 전에 이미 메모리에 준비를 마쳐야 합니다.
- 위 예제에서 Ice ice;는 private으로 선언되어 있으므로, PatBingsoo(자식)는 부모의 부품인 ice에 직접 접근할 수 없습니다. 이것이 상속과 포함의 결정적인 차이 중 하나입니다.</code></pre><h2 id="2-멤버-접근-제어와-생성자-초기화-리스트">2. 멤버 접근 제어와 생성자 초기화 리스트</h2>
<p>부모 클래스의 <code>private</code> 멤버는 자식 클래스에서 직접 접근할 수 없습니다. 따라서 자식 클래스의 생성자에서 부모 클래스의 생성자를 명시적으로 호출하여 초기화해야 합니다.</p>
<h3 id="예제-코드-메시지-시스템">예제 코드: 메시지 시스템</h3>
<pre><code>#include &lt;iostream&gt;
#include &lt;string&gt;
using namespace std;

class Image {
public:
    // 형변환 연산자 오버로딩: 객체를 string으로 취급할 때 호출
    operator string() { return &quot;사진 데이터&quot;; }
};

class Message {
public:
    Message(int sendTime, string sendName) 
        : sendTime(sendTime), sendName(sendName) {}

    int getSendTime() const { return sendTime; }
    string getSendName() const { return sendName; }

private:
    int sendTime;   // 자식에서 직접 접근 불가
    string sendName;
};

class TextMessage : public Message {
public:
    TextMessage(int sendTime, string sendName, string text)
        : Message(sendTime, sendName) { // 부모 생성자 호출
        this-&gt;text = text;
    }
    string getText() const { return text; }
private:
    string text;
};

class ImageMessage : public Message {
public:
    ImageMessage(int sendTime, string sendName, Image* image)
        : Message(sendTime, sendName) {
        this-&gt;image = image;
    }
    Image* getImage() const { return image; }
private:
    Image* image;
};</code></pre><hr>
<h2 id="3-가상-함수와-다형성-dynamic-binding">3. 가상 함수와 다형성 (Dynamic Binding)</h2>
<p>부모 타입의 포인터로 자식 객체를 가리킬 때(<code>Upcasting</code>), 가상 함수(<code>virtual</code>)를 사용하면 실행 시점에 실제 객체의 타입에 맞는 함수가 호출됩니다.</p>
<h3 id="예제-코드-무기-시스템">예제 코드: 무기 시스템</h3>
<pre><code>class Weapon {
public:
    Weapon(int power) : power(power) {
        cout &lt;&lt; &quot;Weapon 생성자 호출&quot; &lt;&lt; endl;
    }

    // 가상 함수 선언
    virtual void use() {
        cout &lt;&lt; &quot;무기를 사용합니다.&quot; &lt;&lt; endl;
    }

protected:
    // protected: 자식 클래스에게는 접근을 허용
    int power;
};

class Sword : public Weapon {
public:
    Sword(int power) : Weapon(power) {}

    // 부모의 use()를 재정의(Override)
    void use() override {
        cout &lt;&lt; &quot;검을 휘둘러 &quot; &lt;&lt; power &lt;&lt; &quot;의 데미지를 입힙니다!&quot; &lt;&lt; endl;
    }
};

int main() {
    // 다형성 활용: 부모 포인터로 자식 객체 관리
    Weapon* myWeapon = new Sword(100);

    // Sword의 use()가 호출됨 (동적 바인딩)
    myWeapon-&gt;use(); 

    delete myWeapon;
    return 0;
}</code></pre><hr>
<h2 id="요약">요약</h2>
<ol>
<li><strong>상속 순서</strong>: 부모 생성 -&gt; 자식 멤버 객체 생성 -&gt; 자식 생성 순.</li>
<li><strong>접근 제어</strong>: <code>private</code>은 자식도 못 건드린다. <code>protected</code>는 자식에겐 오픈된다.</li>
<li><strong>가상 함수</strong>: <code>virtual</code> 키워드를 써야 부모 포인터로 자식을 가리켰을 때 자식의 함수가 제대로 호출된다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] - 5일차(표준 입출력 & 상속)]]></title>
            <link>https://velog.io/@snow-jun-0/C-5%EC%9D%BC%EC%B0%A8%ED%91%9C%EC%A4%80-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%83%81%EC%86%8D</link>
            <guid>https://velog.io/@snow-jun-0/C-5%EC%9D%BC%EC%B0%A8%ED%91%9C%EC%A4%80-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EC%83%81%EC%86%8D</guid>
            <pubDate>Wed, 18 Feb 2026 14:19:06 GMT</pubDate>
            <description><![CDATA[<h1 id="표준-입출력과-상속">표준 입출력과 상속</h1>
<h2 id="1-표준-입출력-및-문자열-결합">1. 표준 입출력 및 문자열 결합</h2>
<p>C++에서 <code>cin</code>과 <code>cout</code>을 이용해 문자열을 입력받고 결합하는 기초 예제입니다. 
<code>string</code> 클래스를 사용하기 위해서는 <code>&lt;string&gt;</code> 헤더를 포함해야 합니다.</p>
<h3 id="이름과-성을-입력받아-결합하는-코드">이름과 성을 입력받아 결합하는 코드</h3>
<pre><code class="language-c">    #include &lt;iostream&gt;
    #include &lt;string&gt; 
    using namespace std;

    int main() {
        // 변수 선언
        string first;
        string last;
        string space = &quot; &quot;;
        string dot = &quot;.&quot;;
        string fullName;

        // 입력
        cout &lt;&lt; &quot;이름을 입력 :&quot;; // &lt;&lt; endl;을 사용하지 않으면 같은 줄에서 입력
        cin &gt;&gt; last;
        cout &lt;&lt; &quot;성을 입력 :&quot;;
        cin &gt;&gt; first;

        fullName = first + space + dot + last;

        cout &lt;&lt; &quot;전체 이름 : &quot; &lt;&lt; fullName &lt;&lt; endl;
    }</code></pre>
<h3 id="출력-결과-비교">출력 결과 비교</h3>
<ul>
<li><p><strong>endl 미사용 시 (기본)</strong>
  이름을 입력 : 길동
  성을 입력 : 홍</p>
</li>
<li><p><strong>endl 사용 시 (줄바꿈 발생)</strong>
  이름을 입력 : 
  길동
  성을 입력 :
  홍</p>
</li>
</ul>
<hr>
<h2 id="2-상속-inheritance">2. 상속 (Inheritance)</h2>
<p>상속이란 클래스가 다른 클래스에게 자신의 멤버(필드, 메서드)를 <strong>&quot;물려주는 것&quot;</strong>을 의미합니다.</p>
<h3 id="용어-정리">용어 정리</h3>
<ul>
<li><strong>부모 클래스</strong>: 슈퍼 클래스(Super), 기본 클래스(Base)</li>
<li><strong>자식 클래스</strong>: 파생 클래스(Derived), 서브 클래스(Sub)</li>
</ul>
<h3 id="상속의-특징과-장점">상속의 특징과 장점</h3>
<ul>
<li>상속이 이루어지면 부모의 기능을 포함한 새로운 클래스가 만들어집니다.</li>
<li><strong>클래스의 간결성</strong>: 공통된 코드를 부모 클래스에 집중시켜 코드 중복을 줄입니다.</li>
<li>자식 클래스에는 자신만의 멤버가 존재할 수 있으며, 부모에게 물려받은 멤버도 사용 가능합니다.</li>
</ul>
<h3 id="접근-제어-지시자와-상속">접근 제어 지시자와 상속</h3>
<table>
<thead>
<tr>
<th align="left">접근 제어 지시자</th>
<th align="center">클래스 외부 접근</th>
<th align="center">자식 클래스 접근</th>
<th align="center">클래스 내부 접근</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>public</strong></td>
<td align="center">가능</td>
<td align="center">가능</td>
<td align="center">가능</td>
</tr>
<tr>
<td align="left"><strong>protected</strong></td>
<td align="center">불가능</td>
<td align="center">가능</td>
<td align="center">가능</td>
</tr>
<tr>
<td align="left"><strong>private</strong></td>
<td align="center">불가능</td>
<td align="center">불가능</td>
<td align="center">가능</td>
</tr>
</tbody></table>
<p>상속 할 때 부모 클래스이 접근 제어지시자를
protected, private로 선언할 수 있다. (public만 되는게 아님)</p>
<ul>
<li>ex) class Derived : protected Base</li>
<li>ex) class Derived : private Base</li>
</ul>
<blockquote>
<p><strong>주의</strong>: 부모 클래스의 <code>private</code> 멤버는 자식 클래스에게 상속은 되지만, 자식 클래스에서 직접 접근할 수는 없습니다.</p>
</blockquote>
<hr>
<h2 id="3-상속-사용법-및-예제">3. 상속 사용법 및 예제</h2>
<h3 id="기본-문법">기본 문법</h3>
<pre><code class="language-c">    class 자식클래스 : 접근제어지시자 부모클래스 {
        // 추가 멤버
    };</code></pre>
<h3 id="상속-관계도">상속 관계도</h3>
<p><img src="https://velog.velcdn.com/images/snow-jun-0/post/62d7d6e7-02e6-46ce-8783-3d40d14a06ee/image.png" alt=""></p>
<h3 id="예제-base와-derived-클래스">예제: Base와 Derived 클래스</h3>
<pre><code class="language-c">    //부모 클래스
    class Base {
    public:
        void bFunc() {
            cout &lt;&lt; &quot;부모 클래스의 메서드&quot; &lt;&lt; endl;
        }
        int bNum;
    };

    //자식 클래스
    class Derived : public Base {
    public:
        void dFunc() {
            cout &lt;&lt; &quot;자식 클래스의 메서드&quot; &lt;&lt; endl;
        }
        int dNum;
    };

    int main() {
        Base b; //객체 생성
        Derived d; //객체 생성

        b.bFunc();
        b.bNum = 1;

        d.bFunc(); // 부모에게 물려받은 메서드 사용
        d.bNum = 2;
        d.dFunc();
        d.dNum = 1;
    }</code></pre>
<hr>
<h2 id="4-생성자-호출-순서">4. 생성자 호출 순서</h2>
<p>상속 관계에서 자식 클래스의 객체가 생성될 때, <strong>반드시 부모 클래스의 생성자가 먼저 호출</strong>된 후 자식 클래스의 생성자가 호출됩니다.</p>
<pre><code class="language-c">    int main() {
        Derived d; // 1. 부모 생성자 호출 -&gt; 2. 자식 생성자 호출
    }</code></pre>
<h2 id="5-실전-상속-예시-animal-클래스">5. 실전 상속 예시 (Animal 클래스)</h2>
<pre><code class="language-c">
    #include &lt;iostream&gt;
    using namespace std;

    class Animal {
    public:
        void breathe() {
            cout &lt;&lt; &quot;숨을 쉰다.&quot; &lt;&lt; endl;
        }
        int age;
    };

    class Dog : public Animal {
    public:
        void walk() {
            cout &lt;&lt; &quot;걷는다.&quot; &lt;&lt; endl;
        }
    };

    class Sparrow : public Animal {
    public:
        void fly() {
            cout &lt;&lt; &quot;난다.&quot; &lt;&lt; endl;
        }
    };

    int main() {
        Dog d;
        d.age = 7;
        d.breathe(); // 부모 기능
        d.walk();    // 자식 기능

        Sparrow s;
        s.age = 1;
        s.breathe(); // 부모 기능
        s.fly();     // 자식 기능
    }</code></pre>
<hr>
<h2 id="6-업캐스팅-upcasting">6. 업캐스팅 (Upcasting)</h2>
<p>자식 클래스의 객체를 부모 클래스의 포인터(또는 참조)로 가리키는 것을 의미합니다.</p>
<pre><code class="language-c">    int main() {
        Dog d;
        Sparrow s;

        // 업캐스팅: 자식 주소를 부모 포인터에 대입
        Animal* p1 = &amp;d; 
        Animal* p2 = &amp;s;

        p1-&gt;breathe(); // 가능
        p2-&gt;breathe(); // 가능

        // p1-&gt;walk(); // 에러! 부모 포인터로는 자식 전용 멤버가 보이지 않음
    }</code></pre>
<p>업캐스팅을 사용하는 이유 (장점)</p>
<ul>
<li><p>&quot;자식 기능을 못 쓰는데 왜 굳이 부모 포인터로 쓰나요?&quot;라는 의문이 생길 수 있습니다. 
가장 큰 이유는 <strong>관리의 편의성</strong> 때문입니다.</p>
<ul>
<li><p>개별 관리의 불편함: 강아지 10마리, 참새 10마리를 관리하려면 
Dog* dogList[10], Sparrow* sparrowList[10]처럼 <strong>따로따로 리스트</strong>를 만들어야 합니다.</p>
</li>
<li><p>통합 관리의 편리함: Animal* zoo[20] 하나만 만들면, 그 안에 강아지든 참새든 사자든 <strong>&#39;동물&#39;</strong>이라는 이름으로 한꺼번에 담을 수 있습니다.</p>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>Tip: 만약 부모 포인터 상태에서도 자식의 특정한 행동(예: 멍멍, 짹짹)을 하고 싶다면, 나중에 배울 <strong>&#39;가상 함수(virtual function)&#39;</strong>와 <strong>&#39;오버라이딩&#39;</strong>을 사용하면 됩니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] - 4일차(상수 &복사 생성, 대입 연산자)]]></title>
            <link>https://velog.io/@snow-jun-0/C-4%EC%9D%BC%EC%B0%A8%EC%83%81%EC%88%98</link>
            <guid>https://velog.io/@snow-jun-0/C-4%EC%9D%BC%EC%B0%A8%EC%83%81%EC%88%98</guid>
            <pubDate>Wed, 18 Feb 2026 11:04:54 GMT</pubDate>
            <description><![CDATA[<h1 id="상수const와-객체의-깊은-복사-string-클래스-구현">상수(const)와 객체의 깊은 복사 (String 클래스 구현)</h1>
<p>오늘 수업에서는 C++에서 상수를 다루는 방법과, 동적 할당을 포함한 클래스에서 반드시 처리해야 할 &#39;깊은 복사&#39;에 대해 학습했습니다. 특히 직접 String 클래스를 설계해보며 메모리 관리의 중요성을 체감할 수 있었습니다.</p>
<hr>
<h2 id="1-상수-const">1. 상수 (const)</h2>
<p>변하지 않는 값을 정의할 때 사용하며, 선언과 동시에 초기화해야 합니다.</p>
<ul>
<li><p><strong>const 변수</strong>: 값을 변경할 수 없습니다. 
const int a = 10;
(에러: <code>a = 20;</code>)</p>
</li>
<li><p><strong>상수형 메서드</strong>: <code>void func() const { ... }</code> 형태. 메서드 내부에서 객체의 멤버 변수를 수정하는 것을 금지합니다.</p>
</li>
</ul>
<hr>
<h2 id="2-string-클래스-만들기-1차-동적-할당과-소멸자">2. String 클래스 만들기 (1차: 동적 할당과 소멸자)</h2>
<p>문자열을 저장하기 위해 <code>char*</code> 포인터를 사용하여 힙(Heap) 메모리를 관리하는 클래스를 설계합니다.</p>
<h3 id="코드-예시">[코드 예시]</h3>
<pre><code class="language-c">//String class 생성
class String { // &#39;String&#39;이라는 이름의 새로운 설계도(클래스)를 만듭니다.
public:
    String() { // [기본 생성자] 아무런 글자 없이 String 객체를 만들 때 실행됩니다.
        strData = NULL; // 가리킬 곳이 없으므로 주소를 NULL(0)로 비워둡니다.
        len = 0; // 길이는 당연히 0입니다.
    }

    String(const char* str) { // [매개변수 생성자] &quot;Hello&quot; 같은 글자를 넣으며 만들 때 실행됩니다. 포인터 형태의 문자열을 받습니다. 
        len = strlen(str); // strlen 함수로 입력받은 글자 수가 몇 개인지 잽니다.
        strData = new char[len + 1]; // 글자 수 + 1(끝을 알리는 &#39;\0&#39; 자리)만큼 힙(Heap) 메모리를 빌려옵니다. 문자열을 저장할 공간을 동적 할당
        strcpy(strData, str); // 빌린 메모리 칸에 입력받은 글자들을 하나씩 복사해 넣습니다. 깊은 복사

    }

    ~String() { // [소멸자] 객체가 수명을 다해 사라질 때 자동으로 호출됩니다.
        if (strData) { // 만약 빌려 쓰고 있는 메모리(strData)가 있다면?
            delete[]strData; new[]로 빌렸던 메모리를 국가(OS)에 반납합니다. (메모리 누수 방지)
        }
    }


    const char* getStrData() const { // 상수형 메서드: 내부 값을 절대 바꾸지 않겠다고 약속하는 조회 함수입니다.
        if (strData) //저장된 데이터가 있다면
            return strData; // 그 주소값을 돌려줍니다.
        return&quot;&quot;; // 데이터가 없다면 빈 문자열의 주소를 돌려줍니다.
    }

    int getLen() const { // 상수형 메서드입니다.
        return len; // 저장된 길이 값을 돌려줍니다.
    }
private:
    char* strData; // 실제 문자열이 저장된 메모리 주소를 가리키는 화살표(포인터)입니다.
    int len; // 문자열의 길이를 숫자로 저장하는 칸입니다.

};


int main(void) {
    String str1; // 기본 생성자 호출 -&gt; strData=NULL, len=0인 빈 객체 생성
    String str2(&quot;Hello&quot;); // 매개변수 생성자 호출 -&gt; 6칸 빌려서 &quot;Hello\0&quot; 저장

    cout &lt;&lt; str1.getLen() &lt;&lt; endl; // 0 출력
    cout &lt;&lt; str1.getStrData() &lt;&lt; endl; // 빈 줄 출력 (또는 아무것도 안 나옴)
    cout &lt;&lt; str2.getLen() &lt;&lt; endl; // 5 출력
    cout &lt;&lt; str2.getStrData() &lt;&lt; endl; // Hello 출력

    //런타임 에러 case
    //String str3 = str2; 객체를 복사하면 기본적으로 모든 멤버의 값이 복사된다. (포인터라면 메모리 주소도 같이 복사된다. ==얕은 복사가 이루어진다. ) 


    return 0;
}</code></pre>
<p><strong>const char*str</strong></p>
<ul>
<li>const char를 가리키는 포인터
const char* 를 통해서 <strong>문자열을 받는다.</strong> 읽어오는 것은 가능하지만
새로운 값을 쓰는 것은 할 수 없다. <strong>(상수)</strong></li>
</ul>
<hr>
<ul>
<li>만약 생성자를 String(char* str)로 만들었다고 가정해 봅시다.<pre><code class="language-c">나의 의도: String str(&quot;test&quot;);
</code></pre>
</li>
</ul>
<p>컴파일러의 생각:</p>
<ol>
<li><p>&quot;test&quot;는 상수형 문자열(const char*)이네? 절대 바뀌면 안 되는 데이터야.</p>
</li>
<li><p>그런데 받는 쪽(char* str)은 const가 없네? 이건 &quot;나중에 이 내용을 바꿀 수도 있다&quot;는 뜻이잖아.</p>
</li>
<li><p>&quot;안전하지 않아! 상수를 보관하는데 왜 바꿀 수 있는 통에 담으려고 해? 에러!&quot;             </p>
</li>
</ol>
<pre><code>
---

## 3. 얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy)

### 얕은 복사의 문제점
`String str3 = str2;`와 같이 객체를 복사할 때, 별도의 처리가 없으면 포인터 주소값만 그대로 복사됩니다. (얕은 복사가 이루어집니다.)
1. **Double Free Error**: 두 객체가 같은 메모리 주소를 가리키고 있어, 소멸자가 호출될 때 이미 해제된 메모리를 또 해제하려다 에러가 발생합니다.
2. **데이터 공유**: 한쪽에서 값을 바꾸면 의도치 않게 다른 쪽 데이터도 영향을 받습니다.

**예시**
```c
String str3 = str2; //객체를 복사하면 기본적으로 모든 멤버의 값이 복사된다. 
//(포인터라면 메모리 주소도 같이 복사된다. ==얕은 복사가 이루어진다. ) 

str2: len=5, strData=0x1000 (예시 주소)
str3: len=5, strData=0x1000 (똑같은 주소!)


main 함수의 마지막 중괄호 }를 만나는 순간,
Stack에 쌓였던 객체들이 생성된 반대 순서로 사라지기 시작합니다.

1. str3 소멸 시작): 가장 마지막에 들어온 str3의 소멸자가 먼저 호출됩니다.

2. str3가 가진 주소 0x1000을 찾아가서 메모리를 반납(delete[])합니다. (성공)

3. (str2 소멸 시작): 그다음 순서인 str2의 소멸자가 호출됩니다.

4. str2도 자기가 가진 주소 0x1000을 찾아가서 반납하려고 합니다.


문제 발생: 하지만 이미 str3가 반납해버린 땅입니다! 이미 비어있는(혹은 권한이 없는) 메모리를 또 삭제하려 하니 운영체제가 &quot;이건 불법이야!&quot;라며 Double Free Error를 일으킵니다.</code></pre><p>그래서 이 문제를 해결하기 위해서는 
str2의 객체가 생성될 때 <strong>생성자 호출</strong> --&gt; 이 때 호출되는 생성자는 <strong>복사 생성자</strong>이다. </p>
<p>복사 생성자를 새롭게 선언하지 않으면 얕은 복사가 일어난다.
그러므로 <strong>깊은 복사</strong>가 이루어 지도록 <strong>복사 생성자를 선언</strong>해주어야 한다. </p>
<hr>
<h3 id="깊은-복사-복사-생성자">깊은 복사 (복사 생성자)</h3>
<p>새로운 메모리 공간을 할당받고 내용을 복사하여 독립적인 상태를 유지합니다.</p>
<p><strong>예시</strong></p>
<pre><code class="language-c">//복사 생성자 선언 
String(const String &amp;rob){
    len = rob.len;
    strData = new char[len + 1];
    strcpy(strData, rob.strData);

}

...

String str3(str2);
</code></pre>
<hr>
<p><strong>위쪽 예시를 포함한 코드</strong></p>
<pre><code class="language-c">#include &lt;iostream&gt;
#include &lt;cstring&gt; // strlen, strcpy 사용을 위해 필요

using namespace std;

class String {
public:
    // 1. 기본 생성자
    String() {
        strData = NULL;
        len = 0;
    }

    // 2. 매개변수 생성자 (문자열 입력)
    String(const char* str) {
        len = strlen(str);
        strData = new char[len + 1];
        strcpy(strData, str);
    }

    // 3. 복사 생성자 (깊은 복사) - 핵심 수정 부분!
    String(const String &amp;rob) {
        len = rob.len;
        if (rob.strData != NULL) {
            strData = new char[len + 1]; //(깊은 복사)
            strcpy(strData, rob.strData);
        } else {
            strData = NULL;
        }
    }

    // 4. 소멸자
    ~String() {
        if (strData) {
            delete[] strData;
        }
    }

    // 조회용 메서드
    const char* getStrData() const {
        if (strData) return strData;
        return &quot;&quot;;
    }

    int getLen() const {
        return len;
    }

private:
    char* strData;
    int len;
};

int main(void) {
    String str1;                // 기본 생성자
    String str2(&quot;Hello&quot;);       // 매개변수 생성자
    String str3 = str2;         // 복사 생성자 호출 (이제 에러가 나지 않습니다!)

    cout &lt;&lt; &quot;str1: &quot; &lt;&lt; str1.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str1.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    cout &lt;&lt; &quot;str2: &quot; &lt;&lt; str2.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str2.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    cout &lt;&lt; &quot;str3: &quot; &lt;&lt; str3.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str3.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;

    return 0;
}


//출력 결과 
str1:  (길이: 0)
str2: Hello (길이: 5)
str3: Hello (길이: 5)
</code></pre>
<hr>
<h2 id="4-복사-대입-연산자-copy-assignment-operator">4. 복사 대입 연산자 (Copy Assignment Operator)</h2>
<p>복사 생성자와는 다른 내용입니다.
이미 생성된 객체에 다른 객체를 대입할 때(<code>str4 = str2;</code>) 호출됩니다.</p>
<pre><code class="language-c">복사 생성자 : String str3=str2;(태어나면서 바로 복사)

복사 대입 연산자 : str3=str2;(이미 만들어진 str3에 str2를 대입)</code></pre>
<ul>
<li><strong>주의사항</strong>: 기존에 가지고 있던 메모리를 먼저 <code>delete</code> 해야 메모리 누수(Memory Leak)가 발생하지 않습니다.<pre><code>String 클래스처럼 동적 할당을 쓰는 경우, 단순히 `=` 만 쓰면 다시 얕은 복사 문제가 
발생. 
</code></pre></li>
</ul>
<p>이미 str3가 빌려놓은 땅에 str2의 주소를 그냥 덮어씌우면 str3가 쓰던 땅은 미아(메모리 누수)</p>
<pre><code>* **자기 대입 방지**: `if (this != &amp;rob)`를 통해 자기 자신을 대입하는 낭비를 막습니다.

**예시**</code></pre><p>String&amp; operator=(const String &amp;rob) {
    if (this != &amp;rob) { // 자기 대입 체크
        delete[] strData; // 기존 메모리 해제 (중요!)
        len = rob.len;
        strData = new char[len + 1];
        strcpy(strData, rob.strData);
    }
    return *this;
}</p>
<p>...</p>
<p>String str3 = str2;</p>
<pre><code>---

**위의 예시들을 포함한 예시**
```c
#include &lt;iostream&gt;
#include &lt;cstring&gt; // strlen, strcpy 사용을 위해 필요

using namespace std;

class String {
public:
    // 1. 기본 생성자
    String() {
        strData = NULL;
        len = 0;
    }

    // 2. 매개변수 생성자 (문자열 입력)
    String(const char* str) {
        len = strlen(str);
        strData = new char[len + 1];
        strcpy(strData, str);
    }

    // 3. 복사 생성자 (깊은 복사) 
    String(const String &amp;rob) {
        len = rob.len;
        if (rob.strData != NULL) {
            strData = new char[len + 1];
            strcpy(strData, rob.strData);
        } else {
            strData = NULL;
        }
    }

    // 4. 소멸자
    ~String() {
        if (strData) {
            delete[] strData;
        }
    }

    //복사 대입 연산자   -&gt; 메모리 누수 현상 일어남
    String &amp;oper=(const String &amp;rob){
        if (this != &amp;rob){
            len= rob.len;
               delete[]strData;
            strData = new char[len+1];
            strcpy(strData, rob.strData);
        }
        return *this;
    }


    // 조회용 메서드
    const char* getStrData() const {
        if (strData) return strData;
        return &quot;&quot;;
    }

    int getLen() const {
        return len;
    }

private:
    char* strData;
    int len;
};

int main(void) {
    String str1;                // 기본 생성자
    String str2(&quot;Hello&quot;);       // 매개변수 생성자

    String str3 = str2;         // 복사 생성자 호출 (이제 에러가 나지 않습니다!)

    String str4(&quot;C++ Pro&quot;);
    str4 = str2;

    cout &lt;&lt; &quot;str1: &quot; &lt;&lt; str1.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str1.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    cout &lt;&lt; &quot;str2: &quot; &lt;&lt; str2.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str2.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    cout &lt;&lt; &quot;str3: &quot; &lt;&lt; str3.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str3.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    cout &lt;&lt; &quot;str4: &quot; &lt;&lt; str4.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str4.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;
    cout &lt;&lt; &quot;str2: &quot; &lt;&lt; str2.getStrData() &lt;&lt; &quot; (길이: &quot; &lt;&lt; str2.getLen() &lt;&lt; &quot;)&quot; &lt;&lt; endl;

    return 0;
}

//출력 결과

str1:  (길이: 0)
str2: Hello (길이: 5)
str3: Hello (길이: 5)
str4: Hello (길이: 5)
str2: Hello (길이: 5)

    str1: 기본 생성자로 만들어져 내용이 비어 있고 길이는 0입니다.

    str2: &quot;Hello&quot;라는 문자열을 가지고 있으며 길이는 5입니다.

    str3: str2를 복사 생성자로 복사했으므로 똑같이 &quot;Hello&quot;와 5가 출력됩니다.

    str4: 처음에는 &quot;C++ Pro&quot;였지만, str4 = str2;를 거치면서 
    기존 메모리를 delete 하고 str2의 값을 가져왔습니다. 
    그래서 **Hello**와 5가 출력됩니다.

    마지막 str2: str4에 값을 대입해줬다고 해서 원본인 str2가 변하지는 않습니다. 
    그대로 **Hello**와 5가 나옵니다.</code></pre><hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] - 3일차(동적 할당)]]></title>
            <link>https://velog.io/@snow-jun-0/C-3%EC%9D%BC%EC%B0%A8%EB%8F%99%EC%A0%81-%ED%95%A0%EB%8B%B9</link>
            <guid>https://velog.io/@snow-jun-0/C-3%EC%9D%BC%EC%B0%A8%EB%8F%99%EC%A0%81-%ED%95%A0%EB%8B%B9</guid>
            <pubDate>Tue, 17 Feb 2026 12:45:54 GMT</pubDate>
            <description><![CDATA[<h1 id="동적-할당과-메모리의-관리-얕은-복사-vs-깊은-복사">동적 할당과 메모리의 관리 (얕은 복사 vs 깊은 복사)</h1>
<p>객체지향 프로그래밍에서 가장 중요한 것 중 하나는 <strong>메모리를 할당하고 관리하는 능력</strong>입니다. 특히 객체가 복사될 때 내부 데이터(특히 포인터)가 어떻게 처리되는지 이해하는 것이 핵심입니다.</p>
<hr>
<h2 id="1-정적-할당-vs-동적-할당">1. 정적 할당 vs 동적 할당</h2>
<h3 id="정적-할당-static-allocation">정적 할당 (Static Allocation)</h3>
<ul>
<li><strong>특징</strong>: 컴파일 시점에 메모리 크기가 결정됩니다.</li>
<li><strong>장점</strong>: 사용하기 쉽고 관리(해제)를 신경 쓸 필요가 없습니다.</li>
<li><strong>단점</strong>: 실행 도중에 메모리 크기를 변경할 수 없어 효율성이 떨어질 수 있습니다.</li>
</ul>
<pre><code class="language-c">    // 예시
    int a(5);
    int a = int(5);</code></pre>
<h3 id="동적-할당-dynamic-allocation">동적 할당 (Dynamic Allocation)</h3>
<ul>
<li><strong>특징</strong>: 프로그램 실행 도중(<code>Runtime</code>)에 필요한 만큼 메모리를 요청합니다.</li>
<li><strong>장점</strong>: 메모리를 효율적으로 사용할 수 있고, 필요한 시점에 생성/소멸이 가능합니다.</li>
<li><strong>단점</strong>: <code>delete</code>를 통해 직접 메모리를 해제해주지 않으면 <strong>메모리 누수(Memory Leak)</strong>가 발생합니다.</li>
</ul>
<pre><code class="language-c">    // 예시 (new 연산자 활용)
    int *a = new int(5); 
    delete a;            // 반드시 해제!</code></pre>
<p>new int(5)선언을 하면 </p>
<ol>
<li>int를 담는 공간 하나가 동적으로 생성</li>
<li>5라는 값이 들어간다.</li>
<li>접근하기 위해서 새로 만들어진 공간의 주소값을 반환(포인터 변수 선언)</li>
</ol>
<hr>
<h2 id="2-객체의-동적-할당과-소멸-순서">2. 객체의 동적 할당과 소멸 순서</h2>
<p>객체를 동적으로 생성하면 <code>new</code>를 하는 순간 생성자가 호출되고, <code>delete</code>를 하는 순간 소멸자가 즉시 호출됩니다. 반면 일반 객체는 함수가 끝날 때 역순으로 소멸합니다.</p>
<pre><code class="language-c">class Vector {
public:
    Vector() : x(0), y(0) {
        cout &lt;&lt; this &lt;&lt; &quot; : Vector()&quot; &lt;&lt; endl;
    }

    Vector(float x, float y) : x(x), y(y) {
        cout &lt;&lt; this &lt;&lt; &quot; : Vector(float, float)&quot; &lt;&lt; endl;
    }

    // 소멸자
    ~Vector() {
        cout &lt;&lt; this &lt;&lt; &quot; : ~Vector()&quot; &lt;&lt; endl;
    }

    float getX() {return x;}
    float getY() { return y; }

private:
    float x, y;
};


int main(void) {
    cout &lt;&lt; &quot;main() 함수 시작&quot; &lt;&lt; endl;
    // 정적 할당 객체
    Vector v1;
    Vector v2(3, 4);

    //동적 할당
    Vector* v3 = new Vector();
    Vector* v4 = new Vector(5, 6);

    cout &lt;&lt; &quot;(&quot; &lt;&lt; v3-&gt;getX() &lt;&lt; &quot;,&quot; &lt;&lt; v3-&gt;getY() &lt;&lt;&quot;)&quot;&lt;&lt; endl;
    cout &lt;&lt; &quot;(&quot; &lt;&lt; v4-&gt;getX() &lt;&lt; &quot;,&quot; &lt;&lt; v4-&gt;getY() &lt;&lt; &quot;)&quot; &lt;&lt; endl;

    delete v3; // v3 즉시 소멸
    delete v4;

    cout &lt;&lt; &quot;main() 함수 끝&quot; &lt;&lt; endl;

}// 함수 종료 시 v2, v1 소멸


//출력 과정
this는 주소를 출력

main() 함수 시작
0x...10 : Vector()             // v1 생성
0x...20 : Vector(float, float)  // v2 생성

0x...30 : Vector()             // v3 생성 (new)
0x...40 : Vector(float, float)  // v4 생성 (new)

(0,0)                          // v3-&gt;getX(), getY()
(5,6)                          // v4-&gt;getX(), getY()

0x...30 : ~Vector()            // delete v3 실행 (즉시 소멸)
0x...40 : ~Vector()            // delete v4 실행 (즉시 소멸)

main() 함수 끝

0x...20 : ~Vector()            // v2 소멸 (main이 끝나며 역순 소멸)
0x...10 : ~Vector()            // v1 소멸 (main이 끝나며 역순 소멸)

</code></pre>
<hr>
<h2 id="3-얕은-복사shallow-copy-vs-깊은-복사deep-copy">3. 얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy)</h2>
<p>메모리를 복사할 때, 특히 <strong>포인터 변수</strong>가 포함된 경우 복사의 방식이 매우 중요합니다.</p>
<h3 id="얕은-복사-shallow-copy">얕은 복사 (Shallow Copy)</h3>
<ul>
<li><p><strong>정의</strong>: 주소값만 복사하는 방식입니다.</p>
</li>
<li><p><strong>문제점</strong>: 두 포인터가 같은 메모리 공간을 가리키게 되어, 한쪽에서 값을 바꾸면 다른 쪽도 영향을 받습니다. 또한 <code>delete</code> 시 이미 해제된 메모리를 또 해제하려는 에러가 발생할 수 있습니다.</p>
<pre><code class="language-c">  int *a = new int(3)

  //실제 int를 담는 공간과 그 공간에 있는 값이 복사 된 것이 아니라, 주소값만 복사
  int *b = a;

</code></pre>
</li>
</ul>
<pre><code>//결과
a 값 1000(주소)
b 값 1000(주소)

1000의 주소에 있는 값 3

*a=5;

//결과
a 값 1000(주소)
b 값 1000(주소)

1000의 주소에 있는 값 3 -&gt; 5</code></pre><pre><code>### 깊은 복사 (Deep Copy)
* **정의**: 실제 데이터가 담긴 새로운 공간을 따로 만들어서 내용물만 복사하는 방식입니다.
* **장점**: 두 객체는 완전히 독립된 메모리를 가집니다.
```c
    int *a = new int(3)
    int *b = new int(*a)


    //결과
    a 값 1000(주소),   1000의 주소값 3
    b 값 2000(주소),   2000의 주소값 3

    *a=5;

    //결과
    a 값 1000(주소),   1000의 주소값 5
    b 값 2000(주소),   2000의 주소값 3
</code></pre><hr>
<h2 id="4-포인터-멤버를-가진-클래스의-복사-예시">4. 포인터 멤버를 가진 클래스의 복사 예시</h2>
<p>클래스 멤버로 포인터가 있을 때, 기본 복사를 수행하면 어떤 일이 벌어지는지 분석해봅시다.</p>
<pre><code class="language-c">class A{
public:
    A(int x, int y) : x(x), y(y) {    
    int x;
    int *y;
};


int main(void({
    A a(1, new int(2));

    A b = a; 기본 복사 발생 (얕은 복사)

    a.x = 3; // a.x는 일반 변수라 b.x에 영향 없음 (값 복사)
    *a.y = 4; // a.y는 포인터라 주소가 복사됨. b.y도 똑같이 4로 변함 (얕은 복사)

    cout &lt;&lt; b.x &lt;&lt; endl; // 출력: 1
    cout &lt;&lt;*b.y &lt;&lt; endl; // 출력: 4 

    delete a.y; // a.y를 해제하면 b.y는 갈 곳 잃은 포인터(Dangling Pointer)가 됨

}


//출력 결과
1. A a(1, new int(2));
a안에, x, y가 있는데,
x의 값은 1
y의 값은 1000(주소값), *y(1000의 주소에는)의 값은 2

2. A b = a;
b안에, x, y가 있는데,
x의 값은 1
y의 값은 1000(주소값), *y(1000의 주소에는)의 값은 2 (얕은 복사)


3. a.x = 3;
a안에, x, y가 있는데,
x의 값은 1 -&gt; 3
y의 값은 1000(주소값), *y(1000의 주소에는)의 값은 2

b안에, x, y가 있는데,
x의 값은 1 (변화 없음, 값 복사이기 때문에(call by value))
y의 값은 1000(주소값), *y(1000의 주소에는)의 값은 2


4. *a.y = 4;
a안에, x, y가 있는데,
x의 값은 3
y의 값은 1000(주소값), *y(1000의 주소에는)의 값은 2 -&gt; 4

b안에, x, y가 있는데,
x의 값은 1 
y의 값은 1000(주소값), *y(1000의 주소에는)의 값은 2 -&gt; 4 (얕은 복사)

</code></pre>
<hr>
<p><strong>요약</strong>: </p>
<ol>
<li><code>new</code>를 썼다면 반드시 <code>delete</code>를 짝지어주자.</li>
<li>포인터를 멤버로 가진 클래스라면, 주소만 옮기는 <strong>얕은 복사</strong>가 일어날 수 있음을 항상 경계하자!</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] - 2일차(생성자, 소멸자)]]></title>
            <link>https://velog.io/@snow-jun-0/C-2%EC%9D%BC%EC%B0%A8%EC%83%9D%EC%84%B1%EC%9E%90-%EC%86%8C%EB%A9%B8%EC%9E%90</link>
            <guid>https://velog.io/@snow-jun-0/C-2%EC%9D%BC%EC%B0%A8%EC%83%9D%EC%84%B1%EC%9E%90-%EC%86%8C%EB%A9%B8%EC%9E%90</guid>
            <pubDate>Tue, 17 Feb 2026 10:12:39 GMT</pubDate>
            <description><![CDATA[<h1 id="생성자-소멸자-그리고-객체지향의-핵심-this-gettersetter">생성자, 소멸자 그리고 객체지향의 핵심 (this, Getter/Setter)</h1>
<h2 id="1-생성자와-소멸자-constructor--destructor">1. 생성자와 소멸자 (Constructor &amp; Destructor)</h2>
<p>클래스에서 객체가 생성될 때와 사라질 때 자동으로 실행되는 특별한 함수들입니다.</p>
<h3 id="생성자-constructor-재설명">생성자 (Constructor) 재설명</h3>
<ul>
<li><p>정의: 객체가 메모리에 태어나는 순간 자동으로 실행되는 특별한 함수입니다.</p>
</li>
<li><p>목적: 아기가 태어나면 이름을 지어주듯, 객체가 태어날 때 변수들에 <strong>첫 번째 값(초기값)</strong>을 넣어주는 역할을 합니다.</p>
</li>
<li><p>특징: 클래스 이름과 똑같이 생겼고, 우리가 직접 부르지 않아도 MyClass m1;이라고 쓰는 순간 컴퓨터가 알아서 실행합니다.</p>
</li>
</ul>
<h3 id="소멸자-destructor">소멸자 (Destructor)</h3>
<ul>
<li><strong>특징</strong>: 클래스 이름 앞에 <code>~</code>를 붙입니다.</li>
<li><strong>실행 시점</strong>: 객체가 사라지는 순간(함수가 종료되거나 프로그램이 끝날 때) 자동으로 호출됩니다.</li>
</ul>
<h3 id="실행-순서-분석-지역-객체-vs-전역-객체">실행 순서 분석 (지역 객체 vs 전역 객체)</h3>
<p><strong>1) 지역 객체의 경우</strong>
함수 내부에서 생성된 객체는 해당 함수(<code>{ }</code>)가 끝나는 순간 소멸합니다.</p>
<pre><code class="language-c">    class MyClass {
    public:
        MyClass() { cout &lt;&lt; &quot;생성자 호출&quot; &lt;&lt; endl; } // (3)
        ~MyClass() { cout &lt;&lt; &quot;소멸자 호출&quot; &lt;&lt; endl; } // (5)
    };

    void testObj() {
        cout &lt;&lt; &quot;testObj() 함수 호출 중...&quot; &lt;&lt; endl; // (2)
        MyClass obj2; // 생성자 호출
        cout &lt;&lt; &quot;testObj() 함수 끝...&quot; &lt;&lt; endl; // (4)
    } // obj2 소멸자 자동 호출 시점

    int main() {
        cout &lt;&lt; &quot;=== main 시작 ===&quot; &lt;&lt; endl; // (1)
        testObj();
        cout &lt;&lt; &quot;=== main 종료 ===&quot; &lt;&lt; endl; // (6)
    }</code></pre>
<hr>
<p><strong>2) 전역 객체의 경우</strong>
전역 공간에 선언된 객체는 프로그램 시작 시 가장 먼저 생성되고, 프로그램이 완전히 종료될 때 소멸합니다.</p>
<pre><code class="language-c">    class MyClass {
    public:
        MyClass() {
            cout &lt;&lt; &quot;생성자 호출&quot; &lt;&lt; endl;  //(1)
        }

        ~MyClass() { 
            cout &lt;&lt; &quot;소멸자 호출&quot; &lt;&lt; endl;  //(6) 
        }


    };

    MyClass obj; // 0) 전역 객체: main보다 먼저 생성!


    void testObj() {
        cout &lt;&lt; &quot;testObj() 함수 호출 중...&quot; &lt;&lt; endl; //(3)
        cout &lt;&lt; &quot;testObj() 함수 끝...&quot; &lt;&lt; endl;     //(4)
    } // obj2 소멸자 자동 호출




    int main(void) {
        cout &lt;&lt; &quot;=== main() 함수 시작 ===&quot; &lt;&lt; endl;  //(2)

        testObj(); // 객체 생성  -&gt; 생성자는 자 동 호출 (void testObj로)

        cout &lt;&lt; &quot;=== main() 함수 종료 ===&quot; &lt;&lt; endl; //(5)
    }
</code></pre>
<hr>
<h2 id="2-this-포인터의-비밀">2. &#39;this&#39; 포인터의 비밀</h2>
<p>컴퓨터는 내부적으로 멤버 함수를 호출할 때 &quot;어떤 객체가 나를 불렀는지&quot;를 알기 위해 객체의 주소를 몰래 넘겨줍니다.</p>
<ul>
<li><strong>실제 모습</strong>: <code>void printData()</code> → <code>void printData(MyClass* this)</code></li>
<li><strong>역할</strong>: <code>data</code>라고만 써도 컴퓨터는 <code>this-&gt;data</code>로 해석하여 호출한 객체의 데이터를 정확히 찾아갑니다.</li>
</ul>
<pre><code class="language-c">int main() {
    MyClass a, b; // 객체 a와 b가 만들어졌어요.
    a.data = 10;
    b.data = 20;

    a.printData(); // (A) 호출
    b.printData(); // (B) 호출
}

- (A) a.printData();를 실행할 때 
컴퓨터는 a의 메모리 주소(예: 0x100)를 파악합니다.
printData 함수를 실행하면서 몰래 this = &amp;a; 라고 주소를 넘겨줍니다.
함수 안에서 cout &lt;&lt; data;를 만나는 순간, 컴퓨터는 this가 가리키는 a의 주소로 가서 10을 꺼내옵니다.

- (B) b.printData();를 실행할 때 (이미지의 &amp;b 부분)
이번엔 b의 메모리 주소(예: 0x200)를 파악합니다.
똑같은 printData 함수를 쓰지만, 이번엔 몰래 this = &amp;b; 라고 주소를 바꿔서 넘겨줍니다.
함수 안에서 this는 이제 b를 가리키므로, 20을 꺼내오게 됩니다.
</code></pre>
<hr>
<h2 id="3-정보-은닉-getter와-setter">3. 정보 은닉: Getter와 Setter</h2>
<p>클래스 내부의 변수(멤버 변수)를 <code>private</code>에 숨겨 안전하게 보호하고, 외부에서는 정해진 함수(public)를 통해서만 접근하게 만드는 방식입니다.</p>
<ul>
<li><p><strong>Getter (열람용)</strong>: &quot;금고 안의 데이터를 복사해서 보여만 줄게.&quot;</p>
</li>
<li><p><strong>Setter (설정용)</strong>: &quot;외부에서 가져온 값을 검사한 뒤 안전할 때만 넣어줄게.&quot;</p>
<pre><code class="language-c">  class MyClass {
  private:
      int real; // 외부 접근 불가 (금고)

  public:
      int getReal() { return real; } // Getter
      void setReal(int r) { real = r; } // Setter
  };</code></pre>
</li>
</ul>
<p><strong>통합 예제</strong></p>
<pre><code class="language-c">class MyClass {
    // 1. 외부에서 사용해야 하는 생성자와 함수는 반드시 public에 선언합니다.
public:
    // 기본 생성자
    MyClass() {
        real = 0;
        imag = 0;
    }

    // 매개변수가 있는 생성자
    MyClass(int r, int i) {
        real = r;
        imag = i;
    }

    // Getter / Setter
    int getReal() { return real; }
    void setReal(int r) { real = r; }

    int getImag() { return imag; }
    void setImag(int i) { imag = i; }

    // 2. 실제 데이터(멤버 변수)는 안전하게 private에 보관합니다.
private:
    int real;
    int imag;
};

int main(void) {
    // 객체 생성 방법 3가지
    MyClass m1;                // 기본 생성자 호출 (real=0, imag=0)
    MyClass m2 = MyClass(5, 6); // 명시적 생성
    MyClass m3(7, 8);          // 암시적 생성 (가장 많이 쓰임)

    cout &lt;&lt; &quot;m1: &quot; &lt;&lt; m1.getReal() &lt;&lt; &quot; + &quot; &lt;&lt; m1.getImag()  &lt;&lt; endl;
    cout &lt;&lt; &quot;m2: &quot; &lt;&lt; m2.getReal() &lt;&lt; &quot; + &quot; &lt;&lt; m2.getImag()  &lt;&lt; endl;
    cout &lt;&lt; &quot;m3: &quot; &lt;&lt; m3.getReal() &lt;&lt; &quot; + &quot; &lt;&lt; m3.getImag()  &lt;&lt; endl;

    return 0;
}
</code></pre>
<hr>
<h2 id="4-생성자-오버로딩-overloading">4. 생성자 오버로딩 (Overloading)</h2>
<p>이름은 같지만 매개변수(재료)의 개수나 타입을 다르게 하여 여러 개의 생성자를 만드는 기술입니다.</p>
<pre><code class="language-c">class MyClass {
public:
    // 1번 생성자: 매개변수(재료)가 0개
    MyClass() {
        real = 0; imag = 0;
    }

    // 2번 생성자: 매개변수(재료)가 2개 (int, int)
    // 이름은 1번과 똑같지만 매개변수 개수가 틀리죠? -&gt; 오버로딩!
    MyClass(int ral, int img) {
        real = ral; imag = img;
    }
};



MyClass m1; // 이라고 쓰면 컴퓨터가 1번을 호출합니다.

MyClass m2(5, 6); //이라고 쓰면 재료가 2개니까 2번을 호출합니다.</code></pre>
<p>데이터 타입이 틀린 경우
재료의 개수가 같아도 <strong>종류(타입)</strong>가 다르면 오버로딩이 됩니다.</p>
<pre><code class="language-c">MyClass(int a) : 정수를 받는 버전

MyClass(double a) : 실수를 받는 버전</code></pre>
<ul>
<li><p>컴퓨터는 함수를 찾을 때 이름만 보는 게 아니라, </p>
</li>
<li><p><em>(이름 + 매개변수 구성)*</em>을 통째로 하나의 세트로 봅니다.</p>
</li>
<li><p>Student() 와 Student(int score) 는 이름은 같지만, 컴퓨터 입장에서는 </p>
</li>
<li><p>*&quot;재료가 없는 버전&quot;<strong>과 **&quot;숫자 재료가 하나 필요한 버전&quot;</strong>으로 확실히 구분해서 
인식할 수 있습니다.</p>
</li>
</ul>
<blockquote>
<p>즉 &quot;오버로딩은 이름은 하나로 통일하되, 재료(매개변수)의 &#39;개수&#39;나 &#39;타입&#39;을 다양하게 준비해서 
여러 상황에 대처하는 기술이다!&quot;</p>
</blockquote>
<hr>
<ul>
<li><strong>주의사항</strong>: 매개변수가 있는 생성자를 하나라도 직접 만들면, 컴파일러는 <strong>디폴트 생성자(매개변수 없는 것)</strong>를 자동으로 만들어주지 않습니다. 필요하다면 직접 선언해야 합니다.</li>
</ul>
<pre><code class="language-c">class MyClass {
public:
    // 1. 내가 특별한 메뉴(매개변수 생성자)를 하나 만들었습니다.
    MyClass(int a) { 
        cout &lt;&lt; &quot;숫자 전달받음!&quot; &lt;&lt; endl; 
    }
};

int main() {
    MyClass m1; // 2. 에러 발생! &quot;기본 메뉴(디폴트 생성자)가 없는데요?&quot;
}</code></pre>
<ul>
<li><p>아무것도 안 했을 때 : <strong>(디폴트 생성자 자동 생성)</strong>: 분식집에 메뉴판이 비어있으면, 
주인은 손님이 올 때를 대비해 아주 기본적인 &#39;그냥 김밥&#39; 하나를 미리 준비해 둡니다. 
그래서 우리는 아무 말 없이 &quot;김밥 하나요!&quot; 해도 김밥을 먹을 수 있습니다.</p>
</li>
<li><p>특별한 메뉴를 만들었을 때 <strong>(매개변수 생성자 선언)</strong>: 우리가 메뉴판에 <strong>&#39;참치 김밥(5,000원)&#39;</strong>이라는 특별한 메뉴를 딱 적어 넣는 순간! 주인은  &quot;오, 이제 이 집은 고급 참치 김밥 전문점이구나? 
이제 그냥 김밥은 안 만들어야지.&quot; </p>
</li>
<li><p>문제가 생기는 상황: 이때 어떤 손님이 와서 그냥 &quot;김밥 하나요!(MyClass m1;)&quot;라고 하면, 주인님은 <strong>&quot;우리 집엔 이제 참치 김밥밖에 없어요! 그냥 김밥은 안 팔아요!&quot;</strong>라고 화를 냅니다. 이게 바로 에러가 나는 상황입니다.</p>
</li>
</ul>
<hr>
<h2 id="5-생성자-위임-constructor-delegation">5. 생성자 위임 (Constructor Delegation)</h2>
<p>비슷한 초기화 코드가 중복되는 것을 방지하기 위해, 하나의 생성자가 다른 생성자를 호출하는 방식입니다.</p>
<p><strong>[생성자 위임 방식 (효율적)]</strong>
초기화 리스트(<code>:</code>)를 사용하여 다른 생성자에게 일을 맡깁니다.</p>
<pre><code class="language-c">#include &lt;iostream&gt;
using namespace std;

class Time {
private:
    int h, m, s;

public:
    // 1. 기본 생성자: 모든 값을 0으로 초기화
    Time() : h(0), m(0), s(0) {
        cout &lt;&lt; &quot;기본 생성자 호출&quot; &lt;&lt; endl;
    }

    // 2. 생성자 위임: Time()을 먼저 불러서 0으로 세팅한 뒤 s만 변경
    Time(int s) : Time() {
        this-&gt;s = s;
        cout &lt;&lt; &quot;Time(int s) 호출&quot; &lt;&lt; endl;
    }

    // 3. 생성자 위임: Time(s)를 불러서 처리한 뒤 m만 추가로 변경
    Time(int m, int s) : Time(s) {
        this-&gt;m = m;
        cout &lt;&lt; &quot;Time(int m, int s) 호출&quot; &lt;&lt; endl;
    }

    // 4. 모든 값을 직접 받는 생성자
    Time(int h, int m, int s) : Time(m,s){
        this-&gt;h = h;
    }


};
</code></pre>
<p><strong>[노가다 방식 (비효율적)]</strong>
매번 모든 변수를 일일이 대입해줘야 하므로 코드가 길어지고 실수가 생길 수 있습니다.</p>
<pre><code class="language-c">#include &lt;iostream&gt;
using namespace std;

class Time {
private:
    int h, m, s;

public:
    // 1. 기본 생성자: 모든 값을 0으로 초기화
    Time() : h(0), m(0), s(0) {
        cout &lt;&lt; &quot;기본 생성자 호출&quot; &lt;&lt; endl;
    }

    // 2. 생성자 위임: Time()을 먼저 불러서 0으로 세팅한 뒤 s만 변경
    Time(int s)  {
        h = 0;
        m = 0;
        this-&gt;s = s;
    }

    // 3. 생성자 위임: Time(s)를 불러서 처리한 뒤 m만 추가로 변경
    Time(int m, int s) {
        h=0;
        this-&gt;m = m;
        this-&gt;s = s;
    }

    // 4. 모든 값을 직접 받는 생성자
    Time(int h, int m, int s) {
        this-&gt;h = h;
        this-&gt;m = m;
        this-&gt;s = s;
    }


};</code></pre>
<p><strong>요약</strong>: 외부(main 함수 등)에서 클래스 내부의 private 영역은 직접 건드릴 수 없으므로, 생성자나 Getter/Setter라는 &#39;공식적인 통로&#39;를 이용해 소통해야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[C++] - 1일차(클래스)]]></title>
            <link>https://velog.io/@snow-jun-0/C-1%EC%9D%BC%EC%B0%A8%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@snow-jun-0/C-1%EC%9D%BC%EC%B0%A8%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Tue, 17 Feb 2026 07:54:10 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스와-객체지향">클래스와 객체지향</h1>
<p>C++에 처음 입문하며 가장 먼저 마주하게 되는 벽이자 핵심인 
<strong>클래스(Class)</strong>와 <strong>객체(Object)</strong>에 대해 정리해 보겠습니다.</p>
<hr>
<h2 id="1-c에서-c로-변화의-시작">1. C에서 C++로: 변화의 시작</h2>
<p>C언어에 익숙하다면 가장 먼저 달라지는 입출력 방식부터 손에 익혀야 합니다.</p>
<ul>
<li><strong>헤더파일:</strong> #include &lt;stdio.h&gt;  →  <code>#include &lt;iostream&gt;</code>  </li>
<li><strong>출력:</strong> printf(&quot;내용&quot;);  →  <code>cout &lt;&lt; &quot;내용&quot; &lt;&lt; endl;</code></li>
<li><strong>입력:</strong> scanf(&quot;%d&quot;, &amp;var);  →  <code>cin &gt;&gt; var;</code></li>
</ul>
<hr>
<h2 id="2-클래스class와-객체instance">2. 클래스(Class)와 객체(Instance)</h2>
<p>흔히 <strong>붕어빵</strong>에 비유하면 이해가 빠릅니다.</p>
<ul>
<li><strong>클래스(Class):</strong> 붕어빵을 만들기 위한 <strong>설계도</strong> 혹은 <strong>틀</strong>. 객체를 만들어 내는 도구입니다.</li>
<li><strong>객체(Object/Instance):</strong> 틀에 반죽을 부어 만들어진 <strong>실제 붕어빵</strong>. 설계도를 바탕으로 메모리에 실제로 구현된 결과물입니다.</li>
</ul>
<blockquote>
<p><strong>구조체 vs 클래스</strong></p>
<ul>
<li>구조체: 간단한 데이터의 묶음. 멤버 변수만 선언 가능(함수는 불가능)</li>
<li>클래스: 데이터(변수) 보호와 복잡한 기능(함수)을 포함하는 상위 개념.</li>
</ul>
</blockquote>
<hr>
<h2 id="3-객체지향의-4대-핵심-원칙">3. 객체지향의 4대 핵심 원칙</h2>
<ol>
<li><p><strong>캡슐화 (Encapsulation)</strong>
변수(데이터)와 함수(기능)를 하나의 캡슐 안에 넣어 보호합니다. 외부에서 함부로 접근하지 못하게 &#39;자물쇠(접근 제어자)&#39;를 채우는 과정이 포함됩니다.</p>
</li>
<li><p><strong>추상화 (Abstraction)</strong>
내부의 복잡한 로직은 숨기고, 사용자에게 꼭 필요한 인터페이스(버튼/함수)만 노출하는 것입니다.</p>
</li>
<li><p><strong>상속 (Inheritance)</strong>
이미 만들어진 부모 클래스의 기능을 그대로 물려받아 새로운 자식 클래스를 만드는 것입니다. (예: 붕어빵 틀을 기반으로 &#39;슈크림&#39; 기능만 추가해 슈크림 붕어빵 틀 만들기)</p>
</li>
<li><p><strong>다형성 (Polymorphism)</strong>
이름은 같은 함수라도 객체에 따라 다르게 동작하는 성질입니다. (예: &#39;공격&#39; 버튼을 눌렀을 때 전사는 &#39;칼질&#39;, 마법사는 &#39;파이어볼&#39;)</p>
</li>
</ol>
<hr>
<h2 id="4-클래스-구조와-생성자constructor">4. 클래스 구조와 생성자(Constructor)</h2>
<p>클래스 이름은 관례적으로 <strong>첫 글자를 대문자</strong>로 시작합니다 (예: <code>Student</code>).</p>
<h3 id="생성자란">생성자란?</h3>
<p>객체가 생성되는 순간(태어나자마자) 자동으로 호출되는 특수한 함수입니다.</p>
<ul>
<li><p>클래스 이름과 동일하며, <strong>반환 타입(int, void 등)이 없습니다.</strong></p>
</li>
<li><p>멤버 변수를 안전하게 <strong>초기화</strong>하는 역할을 합니다.</p>
<pre><code class="language-python">  class Student {
  public: // 밖에서 쓰려면 public이 필요해요!
      string name;
      int score;

      // 1. 기본 생성자 (매개변수가 없을 때, 객체를 초기화하는 함수) 
      Student() {
          name = &quot;미등록&quot;;
          score = 0;
      }

      // 2. 매개변수가 있는 생성자 (원하는 정보를 넣을 때)
      Student(string n) {
          name = n;
          score = 0;
      }
  };

  // 사용 예시
  Student std1;           // 기본 생성자 호출
  Student std2(&quot;철수&quot;);    // 매개변수 생성자 호출</code></pre>
</li>
</ul>
<hr>
<p><strong>비유를 하면</strong>
우리가 게임 캐릭터를 새로 만들 때, 레벨은 1이어야 하고 아이템은 초보자 칼 하나는 들고 있어야 합니다. 
캐릭터가 태어나자마자(메모리에 올라오자마자) 이런 <strong>기본값</strong>들을 세팅해 주는 기능이 바로 생성자입니다.</p>
<ul>
<li><p>기본 생성자: &quot;도시락 하나 주세요&quot; 하면 <strong>미리 정해진 구성</strong>(제육볶음, 밥, 김치)으로 딱 나오죠? 이게 기본 생성자입니다.</p>
</li>
<li><p>매개변수가 있는 생성자: &quot;제육볶음 말고 불고기 넣은 도시락으로 주세요&quot;라고 주문하는 거예요. <strong>내가 원하는 정보</strong>를 넣어서 객체를 만들 수 있습니다.</p>
</li>
</ul>
<hr>
<h2 id="5-정보-은닉과-접근-제어-지시자">5. 정보 은닉과 접근 제어 지시자</h2>
<p>객체지향의 핵심은 <strong>&quot;데이터(변수)는 숨기고(private), 기능(함수)은 연다(public)&quot;</strong>는 것입니다.</p>
<ul>
<li><strong>private:</strong> 클래스 내부에서만 접근 가능 (데이터 보호)</li>
<li><strong>public:</strong> 클래스 외부 어디서든 접근 가능 (인터페이스)</li>
</ul>
<h3 id="getter와-setter">Getter와 Setter</h3>
<p>private으로 숨겨진 변수에 안전하게 접근하기 위해 사용하는 함수입니다.</p>
<pre><code class="language-python"> #include &lt;iostream&gt;
using namespace std; //std를 쓰지 않으면, 출력에 문제 생김

    class Tv {
    private:
        int channel; // 외부에서 직접 수정 불가!

    public:
        // Setter: 값을 검사하며 안전하게 변경
        void setChannel(int ch) {
            if (ch &gt;= 1 &amp;&amp; ch &lt;= 999) {
                channel = ch;
            }
        }

        // Getter: 값을 안전하게 읽어옴
        int getChannel() {
            return channel;
        }
    };</code></pre>
<hr>
<h2 id="6-전체-코드-예시-tv-제어">6. 전체 코드 예시 (TV 제어)</h2>
<pre><code class="language-python">    #include &lt;iostream&gt;
    using namespace std;

    class Tv {
    // 필드(멤버 변수)를 private으로 설정하여 보호!
    private:
        bool powerOn;
        int channel;
        int volume;

    public:
        // 생성자를 통한 초기화
        Tv() {
            powerOn = false;
            channel = 1;
            volume = 10;
        }

        // 외부에서 사용할 수 있는 public 기능(함수)들
        void on() { powerOn = true; }
        void off() { powerOn = false; }

        // 직접 변수를 건드리지 않고 &#39;함수&#39;를 통해서만 값을 바꿉니다. (Setter)
        void setChannel(int ch) {
            if (ch &gt;= 1 &amp;&amp; ch &lt;= 999) channel = ch;
        }

        // 숨겨진 변수 값을 안전하게 읽어옵니다. (Getter)
        int getChannel() { return channel; }

        void setVolume(int vol) {
            if (vol &gt;= 0 &amp;&amp; vol &lt;= 100) volume = vol;
        }

        int getVolume() { return volume; }

       };

    int main() {
        Tv myTv; // Tv 클래스의 인스턴스(객체) 생성

        myTv.on(); // 전원 켜기
        myTv.setChannel(5);  // 채널 설정
           myTv.setVolume(25);  // 볼륨 설정

        cout &lt;&lt; &quot;현재 채널은 &quot; &lt;&lt; myTv.getChannel() &lt;&lt; endl;
        cout &lt;&lt; &quot;현재 볼륨은 &quot; &lt;&lt; myTv.getVolume() &lt;&lt; endl;

        return 0;
    }</code></pre>
<hr>
<p><strong>요약:</strong> 클래스는 객체를 만들기 위한 대장(설계도)이며, 캡슐화와 생성자를 통해 데이터를 안전하고 편리하게 관리하는 것이 C++ 프로그래밍의 핵심입니다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 14일차(Pandas - DataFrame)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-14%EC%9D%BC%EC%B0%A8Pandas-DataFrame</link>
            <guid>https://velog.io/@snow-jun-0/MCP-14%EC%9D%BC%EC%B0%A8Pandas-DataFrame</guid>
            <pubDate>Mon, 16 Feb 2026 11:17:47 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터-분석의-핵심-dataframe-완벽-가이드">데이터 분석의 핵심, DataFrame 완벽 가이드</h1>
<h2 id="1-dataframe-개요">1. DataFrame 개요</h2>
<p>Pandas의 <strong>DataFrame</strong>은 2차원 테이블 형태의 데이터 구조입니다. 
Excel의 Spreadsheet이나 SQL의 Table과 매우 유사하며, 데이터 분석 및 머신러닝에서 가장 많이 활용됩니다.
2차원이기 때문에 인덱스가 row, column로 구성됩니다. 
row는 각 개별 데이터를, column은 개별 속성을 의미합니다. (&#39;feature&#39; 라고도 함)</p>
<ul>
<li><strong>Series:</strong> 1차원 배열 (Column 하나)</li>
<li><strong>DataFrame:</strong> 2차원 배열 (Series의 집합)</li>
<li><strong>Index:</strong> 행(Row)을 식별하는 고유 값</li>
<li><strong>Column/Feature:</strong> 열(속성), 데이터의 특성을 의미</li>
</ul>
<hr>
<h2 id="2-환경-설정-및-데이터-로드">2. 환경 설정 및 데이터 로드</h2>
<h3 id="라이브러리-임포트">라이브러리 임포트</h3>
<pre><code class="language-python">    import numpy as np
    import pandas as pd
    import os</code></pre>
<h3 id="데이터-불러오기-google-colab--csv">데이터 불러오기 (Google Colab &amp; CSV)</h3>
<pre><code class="language-python">    from google.colab import drive
    drive.mount(&#39;/content/drive&#39;)

    base_path = r&#39;/content/drive/MyDrive/dataset&#39;
    filepath = os.path.join(base_path, &#39;titanic.csv&#39;) #여기서는 타이타닉 데이터 사용

    # CSV 파일을 DataFrame 객체로 읽기
    df = pd.read_csv(filepath)</code></pre>
<p>출력 결과</p>
<table>
<thead>
<tr>
<th align="left">PassengerId</th>
<th align="center">Survived</th>
<th align="center">Pclass</th>
<th align="left">Name</th>
<th align="center">Sex</th>
<th align="center">Age</th>
<th align="center">SibSp</th>
<th align="center">Parch</th>
<th align="left">Ticket</th>
<th align="center">Fare</th>
<th align="center">Cabin</th>
<th align="center">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>0</strong></td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="center">male</td>
<td align="center">22.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">A/5 21171</td>
<td align="center">7.2500</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>1</strong></td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Cumings, Mrs. John Bradley (Florence Briggs Th...</td>
<td align="center">female</td>
<td align="center">38.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">PC 17599</td>
<td align="center">71.2833</td>
<td align="center">C85</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>2</strong></td>
<td align="center">1</td>
<td align="center">3</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="center">female</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">STON/O2. 3101282</td>
<td align="center">7.9250</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>3</strong></td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath (Lily May Peel)</td>
<td align="center">female</td>
<td align="center">35.0</td>
<td align="center">1</td>
<td align="center">0</td>
<td align="left">113803</td>
<td align="center">53.1000</td>
<td align="center">C123</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>4</strong></td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="center">male</td>
<td align="center">35.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">373450</td>
<td align="center">8.0500</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>...</strong></td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="left">...</td>
<td align="center">...</td>
<td align="center">...</td>
<td align="center">...</td>
</tr>
<tr>
<td align="left"><strong>886</strong></td>
<td align="center">0</td>
<td align="center">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="center">male</td>
<td align="center">27.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">211536</td>
<td align="center">13.0000</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>887</strong></td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="center">female</td>
<td align="center">19.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">112053</td>
<td align="center">30.0000</td>
<td align="center">B42</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>888</strong></td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Johnston, Miss. Catherine Helen &quot;Carrie&quot;</td>
<td align="center">female</td>
<td align="center">NaN</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="left">W./C. 6607</td>
<td align="center">23.4500</td>
<td align="center">NaN</td>
<td align="center">S</td>
</tr>
<tr>
<td align="left"><strong>889</strong></td>
<td align="center">1</td>
<td align="center">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="center">male</td>
<td align="center">26.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">111369</td>
<td align="center">30.0000</td>
<td align="center">C148</td>
<td align="center">C</td>
</tr>
<tr>
<td align="left"><strong>890</strong></td>
<td align="center">0</td>
<td align="center">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="center">male</td>
<td align="center">32.0</td>
<td align="center">0</td>
<td align="center">0</td>
<td align="left">370376</td>
<td align="center">7.7500</td>
<td align="center">NaN</td>
<td align="center">Q</td>
</tr>
</tbody></table>
<p><strong>[891 rows x 12 columns]</strong></p>
<hr>
<h3 id="컬럼-의미">컬럼 의미</h3>
<pre><code class="language-python"># 컬럼 의미
# survived - Survival (0 = No; 1 = Yes)
# class - Passenger Class (1 = 1st; 2 = 2nd; 3 = 3rd)
# name - Name
# sex - Sex
# age - Age
# sibsp - Number of Siblings/Spouses Aboard
# parch - Number of Parents/Children Aboard
# ticket - Ticket Number
# fare - Passenger Fare
# cabin - Cabin
# embarked - Port of Embarkation (C = Cherbourg; Q = Queenstown; S = Southampton)
# boat - Lifeboat (if survived)
# body - Body number (if did not survive and body was recovered)


</code></pre>
<h2 id="3-데이터-파악-eda-기초">3. 데이터 파악 (EDA 기초)</h2>
<h3 id="데이터-미리보기">데이터 미리보기</h3>
<pre><code>df.head()    # 상위 5개 행 출력 (기본값 5)
df.tail(7)   # 하위 7개 행 출력</code></pre><h3 id="데이터-정보-및-통계-확인">데이터 정보 및 통계 확인</h3>
<pre><code class="language-pthon">    # 1. shape: (행, 열) 크기 확인
    print(df.shape)  #(891,12)

    # 2. info(): 컬럼 타입, 결측치(Non-null) 개수 확인
    df.info()

    #출력 결과 
    &lt;class &#39;pandas.core.frame.DataFrame&#39;&gt;
    RangeIndex: 891 entries, 0 to 890
    Data columns (total 12 columns):
     #   Column       Non-Null Count  Dtype  
    ---  ------       --------------  -----  
    0   PassengerId  891 non-null    int64  
    1   Survived     891 non-null    int64  
     2   Pclass       891 non-null    int64  
     3   Name         891 non-null    object 
     4   Sex          891 non-null    object 
    5   Age          714 non-null    float64
     6   SibSp        891 non-null    int64  
    7   Parch        891 non-null    int64  
     8   Ticket       891 non-null    object 
     9   Fare         891 non-null    float64
     10  Cabin        204 non-null    object 
     11  Embarked     889 non-null    object 
    dtypes: float64(2), int64(5), object(5)
    memory usage: 83.7+ KB



    # 3. describe(): 숫자형 데이터의 기술통계량 출력
    # 숫자형 데이터에 대해 기술통계량 정보
    # count, mean, std : 개수, 평균, 표준편차
    # max, min : 최대, 최소
    # 25%, 50%, 75%  : 하위 4분위 하위 2분위...

    df.describe()
</code></pre>
<hr>
<h2 id="4-dataframe-생성-및-속성">4. DataFrame 생성 및 속성</h2>
<h3 id="리스트list로-생성">리스트(List)로 생성</h3>
<pre><code class="language-python">    df_list = pd.DataFrame([
        [1, 2, 3],
        [4, 5, 6]
    ], columns=[&#39;A&#39;, &#39;B&#39;, &#39;C&#39;], index=[&#39;Row1&#39;, &#39;Row2&#39;])</code></pre>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="center">A</th>
<th align="center">B</th>
<th align="center">C</th>
</tr>
</thead>
<tbody><tr>
<td align="left">Row1</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
</tr>
<tr>
<td align="left">Row2</td>
<td align="center">4</td>
<td align="center">5</td>
<td align="center">6</td>
</tr>
</tbody></table>
<h3 id="딕셔너리dict로-생성">딕셔너리(Dict)로 생성</h3>
<p>index= 없어도 생성됨!  (기본 0-base index)</p>
<pre><code class="language-python">    data = {
        &#39;Name&#39;: [&#39;Alice&#39;, &#39;Bob&#39;, &#39;Charlie&#39;],
        &#39;Age&#39;: [25, 30, 35],
        &#39;City&#39;: [&#39;Seoul&#39;, &#39;Busan&#39;, &#39;Incheon&#39;]
    }
    df_dict = pd.DataFrame(data)</code></pre>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="left">Name</th>
<th align="center">Age</th>
<th align="left">City</th>
</tr>
</thead>
<tbody><tr>
<td align="left">0</td>
<td align="left">Alice</td>
<td align="center">25</td>
<td align="left">Seoul</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">Bob</td>
<td align="center">30</td>
<td align="left">Busan</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">Charlie</td>
<td align="center">35</td>
<td align="left">Incheon</td>
</tr>
</tbody></table>
<h3 id="주요-속성들">주요 속성들</h3>
<pre><code class="language-python">    df.index    # 인덱스 정보
    df.columns  # 컬럼명 리스트
    df.dtypes   # 컬럼별 데이터 타입 (Series 형태로 반환)
    df.size     # 전체 요소(Element) 개수
    df.ndim     # 차원 (DataFrame은 항상 2)</code></pre>
<hr>
<h2 id="5-인덱스-및-컬럼-조작">5. 인덱스 및 컬럼 조작</h2>
<h3 id="이름-변경-rename">이름 변경 (Rename)</h3>
<pre><code class="language-python">    # 특정 컬럼명만 변경
    df2 = pd.DataFrame([
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
], columns = [&#39;국어&#39;, &#39;영어&#39;, &#39;수학&#39;, &#39;과학&#39;]

df2.index = [&#39;고길동&#39;, &#39;둘리&#39;, &#39;마이콜&#39;]</code></pre>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="center">국어</th>
<th align="center">영어</th>
<th align="center">수학</th>
<th align="center">과학</th>
</tr>
</thead>
<tbody><tr>
<td align="left">고길동</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">둘리</td>
<td align="center">5</td>
<td align="center">6</td>
<td align="center">7</td>
<td align="center">8</td>
</tr>
<tr>
<td align="left">마이콜</td>
<td align="center">9</td>
<td align="center">10</td>
<td align="center">11</td>
<td align="center">12</td>
</tr>
<tr>
<td align="left">```python</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># 원본 변경 없다!  (inplace= 사용하면 변경됨)</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">df2.rename(columns={&#39;국어&#39;:&#39;kor&#39;, &quot;과학&quot;:&#39;Sci&#39;})</td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
<pre><code>### 인덱스 재설정 (Reset &amp; Set)
- (inplace= 사용하면 원본 변경됨)
```python
    # 1. 기존 인덱스를 컬럼으로 보내고 새로운 숫자 인덱스 부여
    df2.reset_index(inplace=True)</code></pre><table>
<thead>
<tr>
<th align="left"></th>
<th align="left">index</th>
<th align="center">국어</th>
<th align="center">영어</th>
<th align="center">수학</th>
<th align="center">과학</th>
</tr>
</thead>
<tbody><tr>
<td align="left">0</td>
<td align="left">고길동</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">둘리</td>
<td align="center">5</td>
<td align="center">6</td>
<td align="center">7</td>
<td align="center">8</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">마이콜</td>
<td align="center">9</td>
<td align="center">10</td>
<td align="center">11</td>
<td align="center">12</td>
</tr>
<tr>
<td align="left">```python</td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"># drop=True. 기존의 index 는 사라진다.</td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">df2.reset_index(drop=True)</td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left">```</td>
<td align="left"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
<td align="center"></td>
</tr>
<tr>
<td align="left"></td>
<td align="left">국어</td>
<td align="center">영어</td>
<td align="center">수학</td>
<td align="center">과학</td>
<td align="center"></td>
</tr>
<tr>
<td align="left">:---</td>
<td align="left">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center">:---:</td>
<td align="center"></td>
</tr>
<tr>
<td align="left">0</td>
<td align="left">1</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
<td align="center"></td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">5</td>
<td align="center">6</td>
<td align="center">7</td>
<td align="center">8</td>
<td align="center"></td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">9</td>
<td align="center">10</td>
<td align="center">11</td>
<td align="center">12</td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<pre><code class="language-python">    # 2. 컬럼을 index 로 내리고,  기존의 인덱스를 대체한다.
    df2.set_index(&#39;국어&#39;)</code></pre>
<table>
    <thead>
        <tr>
            <th rowspan="2">국어</th>
            <th colspan="3"></th>
        </tr>
        <tr>
            <th>영어</th>
            <th>수학</th>
            <th>과학</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th>1</th>
            <td>2</td>
            <td>3</td>
            <td>4</td>
        </tr>
        <tr>
            <th>5</th>
            <td>6</td>
            <td>7</td>
            <td>8</td>
        </tr>
        <tr>
            <th>9</th>
            <td>10</td>
            <td>11</td>
            <td>12</td>
        </tr>
    </tbody>
</table>

<h3 id="퀴즈-인덱스와-컬럼-스와이프">퀴즈: 인덱스와 컬럼 스와이프</h3>
<pre><code class="language-python">   # 퀴즈: df2 의 index 와 &#39;국어&#39; 컬럼을 바꾸려면?</code></pre>
<p>원본(df2)</p>
<table>
<thead>
<tr>
<th align="left"></th>
<th align="left">index</th>
<th align="center">국어</th>
<th align="center">영어</th>
<th align="center">수학</th>
<th align="center">과학</th>
</tr>
</thead>
<tbody><tr>
<td align="left">0</td>
<td align="left">고길동</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">1</td>
<td align="left">둘리</td>
<td align="center">5</td>
<td align="center">6</td>
<td align="center">7</td>
<td align="center">8</td>
</tr>
<tr>
<td align="left">2</td>
<td align="left">마이콜</td>
<td align="center">9</td>
<td align="center">10</td>
<td align="center">11</td>
<td align="center">12</td>
</tr>
</tbody></table>
<pre><code class="language-python">df2.reset_index().set_index(&#39;국어&#39;)</code></pre>
<table>
<thead>
<tr>
<th align="left">국어 (index)</th>
<th align="left">index</th>
<th align="center">영어</th>
<th align="center">수학</th>
<th align="center">과학</th>
</tr>
</thead>
<tbody><tr>
<td align="left">1</td>
<td align="left">고길동</td>
<td align="center">2</td>
<td align="center">3</td>
<td align="center">4</td>
</tr>
<tr>
<td align="left">5</td>
<td align="left">둘리</td>
<td align="center">6</td>
<td align="center">7</td>
<td align="center">8</td>
</tr>
<tr>
<td align="left">9</td>
<td align="left">마이콜</td>
<td align="center">10</td>
<td align="center">11</td>
<td align="center">12</td>
</tr>
</tbody></table>
<hr>
<h2 id="6-멀티-인덱스-multi-level-index">6. 멀티 인덱스 (Multi-level Index)</h2>
<p>복잡한 구조의 데이터를 표현할 때 사용합니다.</p>
<pre><code class="language-python">    pd.DataFrame({(&#39;k0&#39;, &#39;k1&#39;): [10]})</code></pre>
<table border="1" class="dataframe" style="text-align: center; margin-left: auto; margin-right: auto;">
  <thead>
    <tr style="text-align: center;">
      <th></th>
      <th>k0</th>
    </tr>
    <tr style="text-align: center;">
      <th></th>
      <th>k1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th style="text-align: center;">0</th>
      <td style="text-align: center;">10</td>
    </tr>
  </tbody>
</table>

<pre><code class="language-python">    pd.DataFrame({(&#39;k0&#39;, &#39;k1&#39;): {(&#39;a1&#39;, &#39;a2&#39;): 10, (&#39;b1&#39;, &#39;b2&#39;): 40}})</code></pre>
<table border="1" class="dataframe" style="text-align: center; margin-left: auto; margin-right: auto;">
  <thead>
    <tr>
      <th></th>
      <th></th>
      <th>k0</th>
    </tr>
    <tr>
      <th></th>
      <th></th>
      <th>k1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>a1</th>
      <th>a2</th>
      <td>10</td>
    </tr>
    <tr>
      <th>b1</th>
      <th>b2</th>
      <td>40</td>
    </tr>
  </tbody>
</table>

<pre><code class="language-python">df4 = pd.DataFrame(
   {
    (&#39;k&#39;, &#39;k1&#39;) : [10, 20, 30, 31],
    (&#39;k&#39;, &#39;k2&#39;) : [40, 50, 60, 61],
    (&#39;j&#39;, &#39;j1&#39;) : [70, 80, 90, 91],
    (&#39;j&#39;, &#39;j2&#39;) : [100, 110, 120, 121],
   },
   index = [[&#39;서울&#39;, &#39;서울&#39;, &#39;경기&#39;, &#39;경기&#39;], [&#39;평일&#39;, &#39;휴일&#39;, &#39;평일&#39;, &#39;휴일&#39;]]
)</code></pre>
<table border="1" class="dataframe" style="text-align: center; margin-left: auto; margin-right: auto; border-collapse: collapse;">
  <thead>
    <tr>
      <th></th>
      <th></th>
      <th colspan="2" style="text-align: center;">k</th>
      <th colspan="2" style="text-align: center;">j</th>
    </tr>
    <tr>
      <th></th>
      <th></th>
      <th style="text-align: center;">k1</th>
      <th style="text-align: center;">k2</th>
      <th style="text-align: center;">j1</th>
      <th style="text-align: center;">j2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th rowspan="2" style="text-align: center; vertical-align: middle;">서울</th>
      <th style="text-align: center;">평일</th>
      <td style="text-align: center;">10</td>
      <td style="text-align: center;">40</td>
      <td style="text-align: center;">70</td>
      <td style="text-align: center;">100</td>
    </tr>
    <tr>
      <th style="text-align: center;">휴일</th>
      <td style="text-align: center;">20</td>
      <td style="text-align: center;">50</td>
      <td style="text-align: center;">80</td>
      <td style="text-align: center;">110</td>
    </tr>
    <tr>
      <th rowspan="2" style="text-align: center; vertical-align: middle;">경기</th>
      <th style="text-align: center;">평일</th>
      <td style="text-align: center;">30</td>
      <td style="text-align: center;">60</td>
      <td style="text-align: center;">90</td>
      <td style="text-align: center;">120</td>
    </tr>
    <tr>
      <th style="text-align: center;">휴일</th>
      <td style="text-align: center;">31</td>
      <td style="text-align: center;">61</td>
      <td style="text-align: center;">91</td>
      <td style="text-align: center;">121</td>
    </tr>
  </tbody>
</table>

<hr>
<h1 id="데이터프레임-선택-및-필터링">데이터프레임 선택 및 필터링</h1>
<p>Pandas의 DataFrame에서 특정 컬럼, 로우(행), 그리고 조건에 맞는 데이터를 선택하는 방법들을 정리합니다.</p>
<hr>
<h2 id="1-하나의-컬럼-선택">1. 하나의 컬럼 선택</h2>
<p>컬럼명을 직접 지정하거나 속성(Attribute) 방식을 사용할 수 있습니다.</p>
<ul>
<li><p><code>df[&#39;Survived&#39;]</code>: Series 형태로 반환</p>
</li>
<li><p><code>df.Survived</code>: 속성 방식 (컬럼명에 공백이 없을 때 가능)</p>
</li>
<li><p><code>df.Age</code>: 나이 컬럼 선택</p>
</li>
</ul>
<hr>
<h2 id="2-복수의-컬럼-선택하기">2. 복수의 컬럼 선택하기</h2>
<p>리스트 형태로 컬럼명을 전달하면 DataFrame 형태로 반환됩니다.</p>
<ul>
<li><p><code>df[[&#39;Survived&#39;]]</code>: 대괄호를 두 번 쓰면 결과는 DataFrame이다.</p>
</li>
<li><p><code>df[[&#39;Survived&#39;, &#39;Age&#39;, &#39;Name&#39;]]</code>: 여러 컬럼을 한꺼번에 선택 가능하며, 순서 변경이나 중복 선택도 가능하다.</p>
</li>
</ul>
<hr>
<h2 id="3-row행-선택하기-loc-iloc">3. Row(행) 선택하기: loc[], iloc[]</h2>
<p>DataFrame은 기본적으로 <code>[]</code>를 컬럼 선택에 사용하므로, 행 선택을 위해서는 전용 속성이 필요합니다.</p>
<p>예제</p>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left">986</td>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.00</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">987</td>
<td align="left">888</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="left">female</td>
<td align="left">19.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">112053</td>
<td align="left">30.00</td>
<td align="left">B42</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">988</td>
<td align="left">889</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Johnston, Miss. Catherine Helen &quot;Carrie&quot;</td>
<td align="left">female</td>
<td align="left">NaN</td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">W./C. 6607</td>
<td align="left">23.45</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">989</td>
<td align="left">890</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="left">male</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">111369</td>
<td align="left">30.00</td>
<td align="left">C148</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left">990</td>
<td align="left">891</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">370376</td>
<td align="left">7.75</td>
<td align="left">NaN</td>
<td align="left">Q</td>
</tr>
</tbody></table>
<h3 id="31-loc-label-based">3.1 loc (Label-based)</h3>
<p>인덱스 자체(이름)를 사용하여 선택합니다.</p>
<ul>
<li><code>df.loc[986]</code>: 해당 인덱스의 데이터를 Series로 반환</li>
</ul>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>986</strong></td>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.0</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><br></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
</tbody></table>
<ul>
<li><code>df.loc[[986]]</code>: 해당 인덱스의 데이터를 DataFrame으로 반환</li>
</ul>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>986</strong></td>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.0</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
</tbody></table>
<br>
* `df.loc[[986, 100, 110]]`: 여러 인덱스 동시 선택

<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>986</strong></td>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.00</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>100</strong></td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">A/5 21171</td>
<td align="left">7.25</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>110</strong></td>
<td align="left">11</td>
<td align="left">1</td>
<td align="left">3</td>
<td align="left">Sandstrom, Miss. Marguerite</td>
<td align="left">female</td>
<td align="left">4.0</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">PP 9549</td>
<td align="left">16.70</td>
<td align="left">G6</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>990</strong></td>
<td align="left">891</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">370376</td>
<td align="left">7.75</td>
<td align="left">NaN</td>
<td align="left">Q</td>
</tr>
</tbody></table>
<br>

<h3 id="32-iloc-integer-based">3.2 iloc (Integer-based)</h3>
<p>0부터 시작하는 순서(Position)를 기준으로 선택합니다. (0 based index)</p>
<ul>
<li><code>df.iloc[0]</code>: 0번 인덱스가 아니라, &#39;첫 번째&#39; 행을 의미 (Series)</li>
</ul>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>100</strong></td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">A/5 21171</td>
<td align="left">7.25</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><br></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
<td align="left"></td>
</tr>
</tbody></table>
<ul>
<li><code>df.iloc[[0, 100, 200, 2]]</code>: 0, 100, 200, 2번째 행을 DataFrame으로 반환</li>
</ul>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>100</strong></td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">A/5 21171</td>
<td align="left">7.2500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>200</strong></td>
<td align="left">101</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Petranec, Miss. Matilda</td>
<td align="left">female</td>
<td align="left">28.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">349245</td>
<td align="left">7.8958</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>300</strong></td>
<td align="left">201</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Vande Walle, Mr. Nestor Cyriel</td>
<td align="left">male</td>
<td align="left">28.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">345770</td>
<td align="left">9.5000</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>102</strong></td>
<td align="left">3</td>
<td align="left">1</td>
<td align="left">3</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="left">female</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">STON/O2. 3101282</td>
<td align="left">7.9250</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
</tbody></table>
<hr>
<h2 id="4-row와-column-동시에-선택하기">4. Row와 Column 동시에 선택하기</h2>
<p><code>loc</code>와 <code>iloc</code>에 콤마(,)를 사용하여 행과 열을 동시에 지정할 수 있습니다.
예제</p>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left">986</td>
<td align="left">887</td>
<td align="left">0</td>
<td align="left">2</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">211536</td>
<td align="left">13.00</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">987</td>
<td align="left">888</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Graham, Miss. Margaret Edith</td>
<td align="left">female</td>
<td align="left">19.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">112053</td>
<td align="left">30.00</td>
<td align="left">B42</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">988</td>
<td align="left">889</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Johnston, Miss. Catherine Helen &quot;Carrie&quot;</td>
<td align="left">female</td>
<td align="left">NaN</td>
<td align="left">1</td>
<td align="left">2</td>
<td align="left">W./C. 6607</td>
<td align="left">23.45</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left">989</td>
<td align="left">890</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="left">male</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">111369</td>
<td align="left">30.00</td>
<td align="left">C148</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left">990</td>
<td align="left">891</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">370376</td>
<td align="left">7.75</td>
<td align="left">NaN</td>
<td align="left">Q</td>
</tr>
</tbody></table>
<pre><code class="language-python">    #loc[row, column] &lt;- loc[axis0, axis1]
    `df.loc[986, &#39;Survived&#39;]`: 특정 인덱스의 특정 컬럼 값 선택

    #출력 결과
    np.int64(0)


    df.iloc[-5, -3] # 뒤에서 5번째 행(986), 뒤에서 3번째 열(Fare) 선택

    #출력 결과
    np.float64(13.0)</code></pre>
<p>예제2</p>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">SibSp</th>
<th align="left">Parch</th>
<th align="left">Ticket</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>100</strong></td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">A/5 21171</td>
<td align="left">7.2500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>101</strong></td>
<td align="left">2</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Cumings, Mrs. John Bradley</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">PC 17599</td>
<td align="left">71.2833</td>
<td align="left">C85</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left"><strong>102</strong></td>
<td align="left">3</td>
<td align="left">1</td>
<td align="left">3</td>
<td align="left">Heikkinen, Miss. Laina</td>
<td align="left">female</td>
<td align="left">26.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">STON/O2. 3101282</td>
<td align="left">7.9250</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>103</strong></td>
<td align="left">4</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath</td>
<td align="left">female</td>
<td align="left">35.0</td>
<td align="left">1</td>
<td align="left">0</td>
<td align="left">113803</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>104</strong></td>
<td align="left">5</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="left">male</td>
<td align="left">35.0</td>
<td align="left">0</td>
<td align="left">0</td>
<td align="left">373450</td>
<td align="left">8.0500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
</tbody></table>
<pre><code class="language-python">    df.loc[102, &#39;Name&#39;]

    #출력 결과
    Heikkinen, Miss. Laina


    df.iloc[2, 3]

    #출력 결과
    Heikkinen, Miss. Laina  #동일하다!!!


      df.loc[[986, 100, 110, 990], [&#39;Survived&#39;, &#39;Name&#39;, &#39;Sex&#39;, &#39;Age&#39;]]
    #출력 결과</code></pre>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">Survived</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>986</strong></td>
<td align="left">0</td>
<td align="left">Montvila, Rev. Juozas</td>
<td align="left">male</td>
<td align="left">27.0</td>
</tr>
<tr>
<td align="left"><strong>100</strong></td>
<td align="left">0</td>
<td align="left">Braund, Mr. Owen Harris</td>
<td align="left">male</td>
<td align="left">22.0</td>
</tr>
<tr>
<td align="left"><strong>110</strong></td>
<td align="left">1</td>
<td align="left">Sandstrom, Miss. Marguerite Rut</td>
<td align="left">female</td>
<td align="left">4.0</td>
</tr>
<tr>
<td align="left"><strong>990</strong></td>
<td align="left">0</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p><strong>참고: 체이닝(Chaining) 방식</strong>
<code>df[&#39;Name&#39;][102]</code> 또는 <code>df.loc[102][&#39;Name&#39;]</code> 처럼 연속해서 인덱싱하는 것도 가능하지만, 
가급적 <code>loc[row, col]</code> 방식을 권장합니다.</p>
</blockquote>
<hr>
<h2 id="5-boolean-selection으로-row-선택하기">5. Boolean Selection으로 Row 선택하기</h2>
<p><strong>조건문(Mask)</strong>을 이용하여 특정 조건에 맞는 데이터만 추출합니다.</p>
<h3 id="51-데이터-탐색-value-check">5.1 데이터 탐색 (Value Check)</h3>
<p>Pclass는 객실의 등급입니다. </p>
<ul>
<li><code>df.Pclass.unique()</code>: 클래스의 종류 확인 (1, 2, 3)<pre><code class="language-python"># 출력 결과 : array([3, 1, 2])</code></pre>
<br>


</li>
</ul>
<ul>
<li><code>df.Pclass.value_counts()</code>: 클래스별 데이터 개수 확인<pre><code class="language-python"># 출력 결과 : </code></pre>
<table>
<thead>
<tr>
<th align="left">Pclass</th>
<th align="left">Count</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>3등급 (3)</strong></td>
<td align="left">491명</td>
</tr>
<tr>
<td align="left"><strong>1등급 (1)</strong></td>
<td align="left">216명</td>
</tr>
<tr>
<td align="left"><strong>2등급 (2)</strong></td>
<td align="left">184명</td>
</tr>
</tbody></table>
</li>
</ul>
<hr>
<h3 id="52-조건-필터링-masking">5.2 조건 필터링 (Masking)</h3>
<p>조건을 변수에 담아 가독성을 높일 수 있습니다.</p>
<pre><code class="language-python">    # 1등석 승객만 필터링
    pclass_mask = df[&#39;Pclass&#39;] == 1
    df[pclass_mask]

    #출력 결과 :</code></pre>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>101</strong></td>
<td align="left">2</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Cumings, Mrs. John Bradley</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">71.2833</td>
<td align="left">C85</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left"><strong>103</strong></td>
<td align="left">4</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath</td>
<td align="left">female</td>
<td align="left">35.0</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>106</strong></td>
<td align="left">7</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">McCarthy, Mr. Timothy J</td>
<td align="left">male</td>
<td align="left">54.0</td>
<td align="left">51.8625</td>
<td align="left">E46</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>...</strong></td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left"><strong>989</strong></td>
<td align="left">890</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Behr, Mr. Karl Howell</td>
<td align="left">male</td>
<td align="left">26.0</td>
<td align="left">30.0000</td>
<td align="left">C148</td>
<td align="left">C</td>
</tr>
</tbody></table>
<br>

<pre><code class="language-python">    # 30대 승객 필터링
    age_mask = (df.Age &gt;= 30) &amp; (df.Age &lt; 40)
    df[age_mask]

    #출력 결과 :</code></pre>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>101</strong></td>
<td align="left">2</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Cumings, Mrs. John Bradley</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">71.2833</td>
<td align="left">C85</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left"><strong>103</strong></td>
<td align="left">4</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath</td>
<td align="left">female</td>
<td align="left">35.0</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>104</strong></td>
<td align="left">5</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Allen, Mr. William Henry</td>
<td align="left">male</td>
<td align="left">35.0</td>
<td align="left">8.0500</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>113</strong></td>
<td align="left">14</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Andersson, Mr. Anders Johan</td>
<td align="left">male</td>
<td align="left">39.0</td>
<td align="left">31.2750</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>118</strong></td>
<td align="left">19</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Vander Planke, Mrs. Julius</td>
<td align="left">female</td>
<td align="left">31.0</td>
<td align="left">18.0000</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>...</strong></td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left"><strong>967</strong></td>
<td align="left">868</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">Roebling, Mr. Washington Augustus II</td>
<td align="left">male</td>
<td align="left">31.0</td>
<td align="left">50.4958</td>
<td align="left">A24</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>972</strong></td>
<td align="left">873</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">Carlsson, Mr. Frans Olof</td>
<td align="left">male</td>
<td align="left">33.0</td>
<td align="left">5.0000</td>
<td align="left">B51 B53</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>981</strong></td>
<td align="left">882</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Markun, Mr. Johann</td>
<td align="left">male</td>
<td align="left">33.0</td>
<td align="left">7.8958</td>
<td align="left">NaN</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>985</strong></td>
<td align="left">886</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Rice, Mrs. William (Margaret Norton)</td>
<td align="left">female</td>
<td align="left">39.0</td>
<td align="left">29.1250</td>
<td align="left">NaN</td>
<td align="left">Q</td>
</tr>
<tr>
<td align="left"><strong>990</strong></td>
<td align="left">891</td>
<td align="left">0</td>
<td align="left">3</td>
<td align="left">Dooley, Mr. Patrick</td>
<td align="left">male</td>
<td align="left">32.0</td>
<td align="left">7.7500</td>
<td align="left">NaN</td>
<td align="left">Q</td>
</tr>
</tbody></table>
<br>


<pre><code class="language-python">    # 다중 조건 (AND 연산자 &#39;&amp;&#39; 사용)
    # 1등석이면서 30대인 승객
    df[pclass_mask &amp; age_mask]

    #출력 결과 :</code></pre>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">PassengerId</th>
<th align="left">Survived</th>
<th align="left">Pclass</th>
<th align="left">Name</th>
<th align="left">Sex</th>
<th align="left">Age</th>
<th align="left">Fare</th>
<th align="left">Cabin</th>
<th align="left">Embarked</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>101</strong></td>
<td align="left">2</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Cumings, Mrs. John Bradley</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">71.2833</td>
<td align="left">C85</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left"><strong>103</strong></td>
<td align="left">4</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Futrelle, Mrs. Jacques Heath</td>
<td align="left">female</td>
<td align="left">35.0</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>161</strong></td>
<td align="left">62</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Icard, Miss. Amelie</td>
<td align="left">female</td>
<td align="left">38.0</td>
<td align="left">80.0000</td>
<td align="left">B28</td>
<td align="left">NaN</td>
</tr>
<tr>
<td align="left"><strong>237</strong></td>
<td align="left">138</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">Futrelle, Mr. Jacques Heath</td>
<td align="left">male</td>
<td align="left">37.0</td>
<td align="left">53.1000</td>
<td align="left">C123</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>315</strong></td>
<td align="left">216</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Newell, Miss. Madeleine</td>
<td align="left">female</td>
<td align="left">31.0</td>
<td align="left">113.2750</td>
<td align="left">D36</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left"><strong>...</strong></td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left"><strong>779</strong></td>
<td align="left">680</td>
<td align="left">1</td>
<td align="left">1</td>
<td align="left">Cardeza, Mr. Thomas Drake Martinez</td>
<td align="left">male</td>
<td align="left">36.0</td>
<td align="left">512.3292</td>
<td align="left">B51 B53</td>
<td align="left">C</td>
</tr>
<tr>
<td align="left"><strong>906</strong></td>
<td align="left">807</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">Andrews, Mr. Thomas Jr</td>
<td align="left">male</td>
<td align="left">39.0</td>
<td align="left">0.0000</td>
<td align="left">A36</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>967</strong></td>
<td align="left">868</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">Roebling, Mr. Washington Augustus II</td>
<td align="left">male</td>
<td align="left">31.0</td>
<td align="left">50.4958</td>
<td align="left">A24</td>
<td align="left">S</td>
</tr>
<tr>
<td align="left"><strong>972</strong></td>
<td align="left">873</td>
<td align="left">0</td>
<td align="left">1</td>
<td align="left">Carlsson, Mr. Frans Olof</td>
<td align="left">male</td>
<td align="left">33.0</td>
<td align="left">5.0000</td>
<td align="left">B51 B53</td>
<td align="left">S</td>
</tr>
</tbody></table>
<br>


<pre><code class="language-python">    # 다중 조건 (AND 연산자 &#39;&amp;&#39; 사용)
    # 1등석이면서 30대인 승객의 클래스와 나이 컬럼만 확인
    df[pclass_mask &amp; age_mask][[&#39;Pclass&#39;, &#39;Age&#39;]]

    #출력 결과 :</code></pre>
<table>
<thead>
<tr>
<th align="left">Index</th>
<th align="left">Pclass</th>
<th align="left">Age</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>101</strong></td>
<td align="left">1</td>
<td align="left">38.0</td>
</tr>
<tr>
<td align="left"><strong>103</strong></td>
<td align="left">1</td>
<td align="left">35.0</td>
</tr>
<tr>
<td align="left"><strong>161</strong></td>
<td align="left">1</td>
<td align="left">38.0</td>
</tr>
<tr>
<td align="left"><strong>237</strong></td>
<td align="left">1</td>
<td align="left">37.0</td>
</tr>
<tr>
<td align="left"><strong>315</strong></td>
<td align="left">1</td>
<td align="left">31.0</td>
</tr>
<tr>
<td align="left"><strong>...</strong></td>
<td align="left">...</td>
<td align="left">...</td>
</tr>
<tr>
<td align="left"><strong>935</strong></td>
<td align="left">1</td>
<td align="left">39.0</td>
</tr>
<tr>
<td align="left"><strong>942</strong></td>
<td align="left">1</td>
<td align="left">30.0</td>
</tr>
<tr>
<td align="left"><strong>967</strong></td>
<td align="left">1</td>
<td align="left">31.0</td>
</tr>
<tr>
<td align="left"><strong>972</strong></td>
<td align="left">1</td>
<td align="left">33.0</td>
</tr>
</tbody></table>
<hr>
<h3 id="퀴즈">퀴즈</h3>
<pre><code class="language-python">    3등급 객실의 생존자 수는? 


    # 정답 코드
    pclass_mask = df[&#39;Pclass&#39;] == 3
    Survived_mask = df[&#39;Survived&#39;] == 1

    len(df[pclass_mask &amp; Survived_mask])  #119
</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 13일차(Pandas-Series)]]></title>
            <link>https://velog.io/@snow-jun-0/m849dfyo</link>
            <guid>https://velog.io/@snow-jun-0/m849dfyo</guid>
            <pubDate>Sun, 15 Feb 2026 12:20:37 GMT</pubDate>
            <description><![CDATA[<h1 id="데이터-분석의-기초-series-객체">데이터 분석의 기초: Series 객체</h1>
<p>Pandas는 행(row)과 열(column) 형태의 &#39;정형 데이터&#39;를 다루는 대표적인 Python 라이브러리입니다. 엑셀 시트나 RDB의 테이블과 유사한 2차원 구조를 다루며, 그 기본이 되는 객체가 바로 <strong>Series</strong>와 <strong>DataFrame</strong>입니다.</p>
<hr>
<h2 id="1-series란">1. Series란?</h2>
<ul>
<li>Pandas의 가장 기본적인 객체 중 하나입니다.</li>
<li>Numpy의 <code>ndarray</code>를 기반으로 하며, <strong>인덱싱 기능</strong>이 추가된 <strong>1차원 배열</strong>입니다.</li>
<li><strong>index x value</strong>의 형태를 가집니다.</li>
<li><strong>같은 타입</strong>의 데이터를 0개 이상 가질 수 있습니다.</li>
</ul>
<hr>
<h2 id="2-series-생성-및-기초-속성">2. Series 생성 및 기초 속성</h2>
<h3 id="기본-생성-0-based-index">기본 생성 (0-based Index)</h3>
<p>데이터만 전달하면 인덱스는 0부터 자동으로 부여됩니다.</p>
<pre><code class="language-python">import numpy as np
import pandas as pd  #pandas를 위해 필수 #pandas를 위해 필수</code></pre>
<img src="https://velog.velcdn.com/images/snow-jun-0/post/9ab53ad4-1ee6-4e23-9e03-6e40c9adebaf/image.png" width="200" align="left">

<pre><code class="language-python">s1 = pd.Series([10, 20, 30])
print(s1)
</code></pre>
<pre><code class="language-python"># 결과: 왼쪽이(0,1,2) index,
# 오른쪽이(10,20,30) value, 
# dtype은 데이터 타입

# 주요 속성 확인
s1.values  # 값 확인 (ndarray)
# array([10, 20, 30])

s1.index   # 인덱스 범위/구성 확인
# RangeIndex(start=0, stop=3, step=1)

s1.dtype   # 데이터 타입 확인
dtype(&#39;int64&#39;)</code></pre>
<h3 id="명시적-인덱스-설정">명시적 인덱스 설정</h3>
<p>인덱스는 <strong>숫자일 필요가 없으며</strong> 중복도 허용됩니다.</p>
<pre><code class="language-python"># 숫자 인덱스 지정
pd.Series(data=[1, 2, 3], index=[100, 200, 300])

# 출력결과</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center">100</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">200</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">300</td>
<td align="center">3</td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"># index 는 굳이 정수일 필요 없다!</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">s5 = pd.Series(data=[1, 2, 3], index=[&#39;john&#39;, &#39;mark&#39;, &#39;charlie&#39;])</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center">john</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">mark</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">charlie</td>
<td align="center">3</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 인덱싱
s5[&#39;john&#39;] # np.int64(1)

# 인덱스 중복 허용
s6 = pd.Series([1, 2, 3], [&#39;john&#39;, &#39;john&#39;, &#39;charlie&#39;])</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center">john</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">john</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">charlie</td>
<td align="center">3</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 중복 indexing 결과 Series!!
s6[&#39;john&#39;]</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center">john</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">john</td>
<td align="center">2</td>
</tr>
</tbody></table>
<hr>
<h2 id="3-딕셔너리dict를-이용한-생성">3. 딕셔너리(dict)를 이용한 생성</h2>
<p>딕셔너리의 <strong>Key는 Index</strong>가 되고, <strong>Value는 데이터 값</strong>이 됩니다.</p>
<pre><code class="language-python">sdata = {&#39;김철수&#39;: 35000, &#39;이상현&#39;: 67000, &#39;최종수&#39;: 12000, &#39;박진관&#39;: 4000}
pd.Series(sdata)</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center">김철수</td>
<td align="center">35000</td>
</tr>
<tr>
<td align="center">이상현</td>
<td align="center">67000</td>
</tr>
<tr>
<td align="center">최종수</td>
<td align="center">12000</td>
</tr>
<tr>
<td align="center">박진관</td>
<td align="center">4000</td>
</tr>
</tbody></table>
<hr>
<h2 id="4-인덱싱과-값-변경">4. 인덱싱과 값 변경</h2>
<pre><code class="language-python">s7 = pd.Series(data=np.arange(5), index=np.arange(100, 105), dtype=np.int16)</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>100</strong></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center"><strong>101</strong></td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><strong>102</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>103</strong></td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><strong>104</strong></td>
<td align="center">4</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 단일 값 접근 (Scalar 반환)
s7[102] #np.int16(2)

# 여러 값 접근 (Series 반환) 1차원 (차원 변화 없슴.)
s7[[102, 104]] </code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>102</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>104</strong></td>
<td align="center">4</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 값 변경 및 신규 삽입
s7[104] = 70  # 기존 값 변경
s7</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>100</strong></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center"><strong>101</strong></td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><strong>102</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>103</strong></td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><strong>104</strong></td>
<td align="center">70</td>
</tr>
</tbody></table>
<pre><code class="language-python">s7[105] = 90  # 기존에 없던 인덱스에 값을 대입 시 새로 생성 (Numpy와 차별점)</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>100</strong></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center"><strong>101</strong></td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><strong>102</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>103</strong></td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><strong>104</strong></td>
<td align="center">70</td>
</tr>
<tr>
<td align="center"><strong>105</strong></td>
<td align="center">90</td>
</tr>
</tbody></table>
<hr>
<h2 id="5-주요-함수-및-통계-nan-처리">5. 주요 함수 및 통계 (NaN 처리)</h2>
<p>Pandas의 집계 연산은 <code>NaN</code>(결측치)을 제외하고 계산하는 특징이 있습니다.</p>
<ul>
<li>size: 전체 개수 반환</li>
<li>shape: 튜플 형태로 형태 반환</li>
<li>unique(): 유일한 값들을 ndarray로 반환</li>
<li>count(): <strong>NaN을 제외한</strong> 데이터 개수</li>
<li>mean(): <strong>NaN을 제외한</strong> 평균!!</li>
<li>value_counts(): 각 값들의 빈도수 반환 (NaN 제외)</li>
</ul>
<p>[예시: Numpy vs Pandas의 NaN 처리]</p>
<pre><code class="language-python">a1 = np.array([2, 2, 2, 2, np.nan])

print(a1.mean())          # 결과: nan (연산 불가)

print(pd.Series(a1).mean()) # 결과: 2.0 (nan 무시)</code></pre>
<hr>
<h2 id="6-series-연산">6. Series 연산</h2>
<p>Series끼리의 연산은 순서가 아닌 <strong>같은 인덱스</strong>를 기준으로 수행됩니다.</p>
<pre><code class="language-python">s1 = pd.Series([1, 2, 3, 4], [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;])</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>a</strong></td>
<td align="center">1</td>
</tr>
<tr>
<td align="center"><strong>b</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>c</strong></td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><strong>d</strong></td>
<td align="center">6</td>
</tr>
</tbody></table>
<pre><code class="language-python">s2 = pd.Series([6, 3, 2, 1], [&#39;d&#39;, &#39;c&#39;, &#39;b&#39;, &#39;a&#39;])</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>d</strong></td>
<td align="center">6</td>
</tr>
<tr>
<td align="center"><strong>c</strong></td>
<td align="center">3</td>
</tr>
<tr>
<td align="center"><strong>b</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>a</strong></td>
<td align="center">1</td>
</tr>
</tbody></table>
<pre><code class="language-python">print(s1 + s2) # &#39;a&#39;는 &#39;a&#39;끼리, &#39;b&#39;는 &#39;b&#39;끼리 연산
# 인덱스 쌍이 맞지 않으면 결과는 NaN으로 채워집니다.</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>a</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>b</strong></td>
<td align="center">4</td>
</tr>
<tr>
<td align="center"><strong>c</strong></td>
<td align="center">6</td>
</tr>
<tr>
<td align="center"><strong>d</strong></td>
<td align="center">12</td>
</tr>
</tbody></table>
<hr>
<h2 id="7-boolean-selection-필터링">7. Boolean Selection (필터링)</h2>
<p>조건식을 [] 안에 넣어 원하는 데이터만 추출할 수 있습니다.</p>
<pre><code class="language-python">s = pd.Series(np.arange(10), np.arange(10) + 1)

s &gt; 5 # 조건에 맞으면 True, 틀리면 False</code></pre>
<table>
<thead>
<tr>
<th align="center"></th>
<th align="center">0</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>1</strong></td>
<td align="center">False</td>
</tr>
<tr>
<td align="center"><strong>2</strong></td>
<td align="center">False</td>
</tr>
<tr>
<td align="center"><strong>3</strong></td>
<td align="center">False</td>
</tr>
<tr>
<td align="center"><strong>4</strong></td>
<td align="center">False</td>
</tr>
<tr>
<td align="center"><strong>5</strong></td>
<td align="center">False</td>
</tr>
<tr>
<td align="center"><strong>6</strong></td>
<td align="center">False</td>
</tr>
<tr>
<td align="center"><strong>7</strong></td>
<td align="center">True</td>
</tr>
<tr>
<td align="center"><strong>8</strong></td>
<td align="center">True</td>
</tr>
<tr>
<td align="center"><strong>9</strong></td>
<td align="center">True</td>
</tr>
<tr>
<td align="center"><strong>10</strong></td>
<td align="center">True</td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">s[s &gt; 5]        # 5보다 큰 값만 추출</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center"><strong>7</strong></td>
<td align="center">6</td>
</tr>
<tr>
<td align="center"><strong>8</strong></td>
<td align="center">7</td>
</tr>
<tr>
<td align="center"><strong>9</strong></td>
<td align="center">8</td>
</tr>
<tr>
<td align="center"><strong>10</strong></td>
<td align="center">9</td>
</tr>
<tr>
<td align="center">```python</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">s[s % 2 == 0]   # 짝수 값만 추출</td>
<td align="center"></td>
</tr>
<tr>
<td align="center">```</td>
<td align="center"></td>
</tr>
<tr>
<td align="center"></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center">:---:</td>
<td align="center">:---:</td>
</tr>
<tr>
<td align="center"><strong>1</strong></td>
<td align="center">0</td>
</tr>
<tr>
<td align="center"><strong>3</strong></td>
<td align="center">2</td>
</tr>
<tr>
<td align="center"><strong>5</strong></td>
<td align="center">4</td>
</tr>
<tr>
<td align="center"><strong>7</strong></td>
<td align="center">6</td>
</tr>
<tr>
<td align="center"><strong>9</strong></td>
<td align="center">8</td>
</tr>
</tbody></table>
<hr>
<h2 id="8-데이터-삭제-drop-및-inplace">8. 데이터 삭제: drop() 및 inplace</h2>
<hr>
<ul>
<li><p>대부분의 Pandas 함수는 원본을 건드리지 않고 <strong>사본</strong>을 반환합니다.
drop() 함수는 drop 한<strong>결과</strong> 를 새로 만들어서 리턴한거고
원본 데이터 s 는 <strong>변경</strong>하지 않습니다</p>
</li>
<li><p>numpy , pandas, 그밖의 수많은 데이터 관련 모듈들 에서의
대부분의 객체 함수들은 호출한 원본 객체를 <strong>변경</strong>하진 않고
원본의 <strong>사본</strong>을 만든뒤 <strong>사본</strong> 에 연산수행하여 그 <strong>사본</strong> 을 리턴하도록 동작합니다
그러나!</p>
</li>
<li><p><strong>inplace=True</strong> 파라미터를 주면 <strong>사본</strong> 을 만들지 않고 <strong>원본</strong>을 변화시키도록 동작합니다</p>
</li>
</ul>
<pre><code class="language-python">s = pd.Series(np.arange(100, 105), [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;])

# 삭제된 &#39;사본&#39; 리턴 (원본 유지)
s.drop(&#39;a&#39;) 



# 원본을 직접 변경하고 싶을 때(중요)
s.drop(&#39;b&#39;, inplace=True) </code></pre>
<hr>
<h2 id="9-multi-level-index-다중-인덱스">9. Multi-level Index (다중 인덱스)</h2>
<p>계층적인 인덱스 구조를 가질 수 있습니다.</p>
<pre><code class="language-python">s3 = pd.Series([1, 2, 3, 4, 5, 6], [&#39;a&#39;, &#39;a&#39;, &#39;b&#39;, &#39;b&#39;, &#39;c&#39;, &#39;c&#39;])
s3.index  #Index([&#39;a&#39;, &#39;a&#39;, &#39;b&#39;, &#39;b&#39;, &#39;c&#39;, &#39;c&#39;], dtype=&#39;object&#39;)

# ↑ 단일 level index 다!


# multi-level index 를 가진 Series
s4 = pd.Series(
    np.arange(100, 106),
    index = [
        [&#39;a&#39;, &#39;a&#39;, &#39;b&#39;, &#39;b&#39;, &#39;c&#39;, &#39;c&#39;], # Level 0
        [ 1 ,  2 ,  1,   2 ,  1,   2 ], # Level 1
    ]
)</code></pre>
<table>
<thead>
<tr>
<th align="center">Level 0</th>
<th align="center">Level 1</th>
<th align="center">Data (데이터)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>a</strong></td>
<td align="center">1</td>
<td align="center">100</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">2</td>
<td align="center">101</td>
</tr>
<tr>
<td align="center"><strong>b</strong></td>
<td align="center">1</td>
<td align="center">102</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">2</td>
<td align="center">103</td>
</tr>
<tr>
<td align="center"><strong>c</strong></td>
<td align="center">1</td>
<td align="center">104</td>
</tr>
<tr>
<td align="center"></td>
<td align="center">2</td>
<td align="center">105</td>
</tr>
</tbody></table>
<pre><code class="language-python"># 인덱스
s4.index #MultiIndex([(&#39;a&#39;, 1),
                     #(&#39;a&#39;, 2),
                     #(&#39;b&#39;, 1),
                     #(&#39;b&#39;, 2),
                     #(&#39;c&#39;, 1),
                     #(&#39;c&#39;, 2)],
                        #)

#인덱싱 방법
s4[&#39;a&#39;, 1]     # 튜플 형태 접근  #np.int64(100)

s4.xs(&#39;a&#39;)     # 특정 레벨 추출 (Cross-section)

s4.xs((&#39;a&#39;, 1))  # () 괄호 꼭 필요!   # s4[&#39;a&#39;, 1] 과 동일

# s4.xs(2)  # 에러, level 0 에서 2 라는 index? 없다!
s4.xs(2, level=1) # 특정 레벨의 값 기준 추출
</code></pre>
<hr>
<h2 id="10-apply와-rename">10. apply()와 rename()</h2>
<p>Pandas의 <code>apply()</code>는 데이터 전처리 시 가장 빈번하게 사용하는 함수 중 하나입니다.
각 원소에 복잡한 로직을 적용하거나 문자열을 가공할 때 매우 유용합니다.</p>
<pre><code class="language-python">Series.apply(func, convert_dtype=True, args=(), **kwargs)</code></pre>
<h3 id="다양한-apply-활용-사례">다양한 apply() 활용 사례</h3>
<p>단순 연산부터 인자 전달, 문자열 처리까지의 예제입니다.</p>
<pre><code class="language-python">    import pandas as pd
    import numpy as np

    s = pd.Series([1, 2, 3, 4, 5])

    # [사례 1] 람다(lambda)를 이용한 제곱 연산
    result_sq = s.apply(lambda x: x ** 2)

    # [사례 2] 사용자 정의 함수로 문자열 포맷팅
    def custom_func(x):
        return f&quot;Value: {x}&quot;
    result_custom = s.apply(custom_func)

    # [사례 3] args를 통한 추가 인자(factor) 전달
    def multiply(x, factor):
        return x * factor
    result_mult = s.apply(multiply, args=(10,))

    # [사례 4] 문자열 공백 제거 및 소문자 변환
    s2 = pd.Series([&quot;  Apple &quot;, &quot;Banana&quot;, &quot; Cherry &quot;])
    result_str = s2.apply(lambda x: x.strip().lower())


   #[사례 1]출력 결과 
    0     1
    1     4
    2     9
    3    16
    4    25
    dtype: int64

    #[사례 2]출력 결과 
    0    Value: 1
    1    Value: 2
    2    Value: 3
    3    Value: 4
    4    Value: 5
    dtype: object

    #[사례 3]출력 결과 
    0    10
    1    20
    2    30
    3    40
    4    50
    dtype: int64

    #[사례 4]출력 결과 
    0     apple
    1    banana
    2    cherry
    dtype: object
</code></pre>
<h3 id="📊-주요-실행-결과-표">📊 주요 실행 결과 (표)</h3>
<table>
<thead>
<tr>
<th align="center">구분</th>
<th align="center">데이터 예시 (첫 행)</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>제곱 적용</strong></td>
<td align="center">1 → 1, 5 → 25</td>
<td align="left">모든 원소에 지수 연산 수행</td>
</tr>
<tr>
<td align="center"><strong>문자 포맷</strong></td>
<td align="center">1 → &quot;Value: 1&quot;</td>
<td align="left">숫자 데이터를 문자열 템플릿에 결합</td>
</tr>
<tr>
<td align="center"><strong>인자 전달</strong></td>
<td align="center">1 → 10, 5 → 50</td>
<td align="left"><code>args=(10,)</code>을 통해 10배수 연산</td>
</tr>
<tr>
<td align="center"><strong>문자열 처리</strong></td>
<td align="center">&quot; Apple &quot; → &quot;apple&quot;</td>
<td align="left">양끝 공백 제거(<code>strip</code>) 및 소문자화</td>
</tr>
</tbody></table>
<hr>
<h3 id="rename을-이용한-인덱스-변경">rename()을 이용한 인덱스 변경</h3>
<p>Series의 특정 인덱스 이름을 바꾸고 싶을 때는 <code>rename()</code> 메서드를 사용합니다. 
딕셔너리 형태(<code>{기존: 변경}</code>)로 전달하면 원하는 인덱스만 콕 집어 바꿀 수 있습니다.</p>
<pre><code class="language-python">    # 인덱스 1번을 &#39;haha&#39;로 변경
    s2_renamed = s2.rename(index={1: &#39;haha&#39;})

    print(s2_renamed)</code></pre>
<h3 id="📊-인덱스-변경-결과-s2rename">📊 인덱스 변경 결과 (s2.rename)</h3>
<table>
<thead>
<tr>
<th align="center">Index (인덱스)</th>
<th align="center">Data (데이터)</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><strong>0</strong></td>
<td align="center">&quot;  apple &quot;</td>
</tr>
<tr>
<td align="center"><strong>haha</strong></td>
<td align="center">&quot;banana&quot;</td>
</tr>
<tr>
<td align="center"><strong>2</strong></td>
<td align="center">&quot; Cherry &quot;</td>
</tr>
</tbody></table>
<hr>
<h3 id="💡-핵심-정리">💡 핵심 정리</h3>
<ol>
<li><strong>apply(args=...)</strong>: 함수에 고정된 상수값을 전달해야 할 때 <code>args</code> 파이썬 튜플을 사용합니다.</li>
<li><strong>Method Chaining</strong>: <code>s2.apply(lambda x: x.strip()).apply(lambda x: x.lower())</code> 처럼 여러 번 이어서 사용할 수도 있습니다.</li>
<li><strong>Immutability</strong>: <code>rename</code>이나 <code>apply</code> 모두 원본을 바로 바꾸지 않고 새로운 객체를 반환합니다. 원본을 바꾸려면 다시 할당(<code>s2 = s2.rename(...)</code>)해야 합니다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 12일차(Numpy)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-%EC%9D%BC%EC%B0%A8ndarray</link>
            <guid>https://velog.io/@snow-jun-0/MCP-%EC%9D%BC%EC%B0%A8ndarray</guid>
            <pubDate>Sun, 15 Feb 2026 06:32:39 GMT</pubDate>
            <description><![CDATA[<h1 id="numpy-데이터-분석의-기초-다차원-배열-ndarray-완벽-정리">[Numpy] 데이터 분석의 기초, 다차원 배열 ndarray 완벽 정리</h1>
<p>Numpy는 수치적 연산을 위해 최적화된 파이썬 모듈로, 데이터 분석과 머신러닝의 가장 기본이 되는 라이브러리입니다. Pandas, Scikit-learn 등 수많은 라이브러리가 Numpy를 기반으로 구현되어 있습니다.</p>
<hr>
<h2 id="1-numpy를-사용하는-이유">1. Numpy를 사용하는 이유</h2>
<ol>
<li><strong>성능</strong>: 파이썬 리스트보다 훨씬 빠릅니다.</li>
<li><strong>메모리</strong>: 적은 메모리를 효율적으로 사용합니다.</li>
<li><strong>기능</strong>: 선형대수, 통계 등 풍부한 수치 함수를 제공합니다.</li>
<li><strong>표준</strong>: 데이터 과학 생태계의 공용어와 같습니다.</li>
</ol>
<hr>
<h3 id="차원">차원</h3>
<p><img src="https://statkclee.github.io/deep-learning/fig/tensor.jpg" alt="aaa"></p>
<p><strong>Scalar</strong> : 0차원 array (단일값)</p>
<p><strong>Vector</strong> : 1차원 array</p>
<p><strong>Matrix</strong> : 2차원 array</p>
<p><strong>Tensor</strong> : 3차원(이상) array</p>
<h2 id="2-ndarray의-기본-속성">2. ndarray의 기본 속성</h2>
<p>Numpy의 핵심 타입은 <code>ndarray</code> (n-dimensional array)입니다. 모든 원소는 <strong>단일 타입</strong>으로 정의됩니다. (리스트는 원소타입이 각각 다르다)</p>
<pre><code class="language-python">    import numpy as np #핵심

    #생성
    arr1 = np.array([1, 2, 3, 4, 5])

    # 주요 속성 확인
    arr1.shape  # (5,) -&gt; 1차원, 크기 5
    arr1.ndim   # 1 (차원 수)    # len(arr1.shape)로 써도 된다. 
    arr1.size   # 5 (전체 원소 개수)
    arr1.dtype  # dtype(&#39;int64&#39;) (데이터 타입)



    # 2차원 array 생성
    arr2=np.array([[2,3,4],[1,2,4]])

    arr2.shape #(2,3)
    #숫자 2개==2차원, 
    #차원의 크기는 2*3=6, 
    #크기가 3짜리 1차원 배열이 2개가 있다는 뜻


    # 1차원 배열의 원소는 스칼라값 (0차원)
    len(arr1) #5

    # 2차원 배열의 원소는 1차원 배열
    len(arr2)  #2    #1차원 배열의 개수는 2개
</code></pre>
<h3 id="데이터-타입-dtype">데이터 타입 (dtype)</h3>
<p>타입이 섞여 있을 경우, 더 큰 범위를 포함하는 타입(예: 정수와 실수가 섞이면 실수형)으로 통일됩니다.</p>
<ul>
<li><strong>int</strong>: 정수</li>
<li><strong>float</strong>: 실수</li>
<li><strong>bool</strong>: 불리언</li>
<li><strong>object</strong>: 파이썬 객체</li>
</ul>
<h4 id="자료형의-종료">자료형의 종료</h4>
<p>(자료형 뒤에 붙는 숫자는 몇 비트 크기인지를 의미한다.)</p>
<ul>
<li>부호가 있는 정수 int(8, 16, 32, 64)</li>
<li>부호가 없는 정수 uint(8 ,16, 32, 64)</li>
<li>실수 float(16, 32, 64, 128)</li>
<li>복소수 complex(64, 128, 256)</li>
<li>불리언 bool</li>
<li>문자열 string_</li>
<li>파이썬 오프젝트 object</li>
<li>유니코드 unicode_</li>
</ul>
<hr>
<h2 id="3-배열-생성-및-차원-변경">3. 배열 생성 및 차원 변경</h2>
<h3 id="생성-함수">생성 함수</h3>
<ul>
<li><code>np.arange(start, stop, step)</code>: 범위 내 배열 생성 (<strong>range</strong>와 사용법 유사)</li>
<li><code>np.zeros(shape)</code>: 0으로 채워진 배열</li>
<li><code>np.ones(shape)</code>: 1로 채워진 배열</li>
<li><code>np.full(shape, fill_value)</code>: 특정 값으로 채우기</li>
<li><code>np.eye(N)</code>: 주대각선만 1이고 나머지는 0 인 N x N 단위 행렬</li>
</ul>
<pre><code class="language-python">np.arange(10)
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

np.arange(1,10,2)
# array([1, 3, 5, 7, 9])

np.arange(10,0)
# array([], dtype=int64) 빈 배열

np.arange(10,0,-1)
# array([10,  9,  8,  7,  6,  5,  4,  3,  2,  1])

np.arange(1,10,dtype=np.int16)
# array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int16)

# N x N 단위 행렬
np.eye(5,dtype=np.int16)
&quot;&quot;&quot;array([[1, 0, 0, 0, 0],
            [0, 1, 0, 0, 0],
             [0, 0, 1, 0, 0],
             [0, 0, 0, 1, 0],
             [0, 0, 0, 0, 1]], dtype=int16)&quot;&quot;&quot;


</code></pre>
<h3 id="shape차원-변경하기">shape(차원) 변경하기</h3>
<p><strong>차원변환</strong>은 데이터분석 과 인공지능에서 매우 빈번하게 발생되는 작업이니만큼 자유자재로 변환할수 있어야 하고, 머리속으로 내가 변환하는 데이터의 구조가 그려지도록 익숙해져야 합니다</p>
<p>EX) 이미지 데이터 벡터화 - 이미지는 기본적으로 2차원 혹은 3차원(RGB)이나 트레이닝을 위해 1차원으로 변경하여 사용됩니다. </p>
<table>
<thead>
<tr>
<th align="left">특징</th>
<th align="left">ravel()</th>
<th align="left">flatten()</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>반환값</strong></td>
<td align="left">원본의 <strong>View</strong> (가급적 참조)</td>
<td align="left">원본의 <strong>Copy</strong> (데이터 복사)</td>
</tr>
<tr>
<td align="left"><strong>속도/메모리</strong></td>
<td align="left">빠름, 메모리 효율적</td>
<td align="left">상대적으로 느림, 메모리 추가 점유</td>
</tr>
<tr>
<td align="left"><strong>수정 시</strong></td>
<td align="left">반환된 값을 수정하면 <strong>원본도 바뀜</strong></td>
<td align="left">반환된 값을 수정해도 <strong>원본은 유지됨</strong></td>
</tr>
<tr>
<td align="left"><strong>형태</strong></td>
<td align="left"><code>np.ravel(a)</code> 또는 <code>a.ravel()</code></td>
<td align="left"><code>a.flatten()</code> (ndarray의 메서드로만 제공)</td>
</tr>
</tbody></table>
<h4 id="ravel-flatten-예시">ravel(), flatten() 예시</h4>
<pre><code class="language-python">import numpy as np
a = np.array([[1, 2], 
              [3, 4]])

# C-style (Row-major): 가로 방향으로 읽으며 펼침 (기본값)
# 결과: [1, 2, 3, 4]
print(a.ravel(order=&#39;C&#39;)) 

# F-style (Column-major): 세로 방향으로 읽으며 펼침
# 결과: [1, 3, 2, 4]
print(a.ravel(order=&#39;F&#39;))</code></pre>
<h4 id="reshape함수-예시">reshape함수 예시</h4>
<ul>
<li>원소의 <strong>총 개수(size)</strong>가 유지되어야 변환이 가능합니다.</li>
<li><code>-1</code>을 사용하면 나머지 차원을 자동으로 계산합니다.</li>
</ul>
<pre><code class="language-python">np.arange(12).reshape(2,6) #2차원 배열, 원소 6개씩
#array([[ 0,  1,  2,  3,  4,  5],
           #[ 6,  7,  8,  9, 10, 11]])

x.reshape(2, -1)   # (2, 6) 자동 계산

np.arange(12).reshape(3,2,2) 
# 전체 12개를 먼저 3개의 큰 덩어리로 나누고, 그 각 덩어리를 다시 2행 2열짜리 표로 만든 것 

#array([[[ 0,  1],
     #   [ 2,  3]],

     #  [[ 4,  5],
     #   [ 6,  7]],

     #  [[ 8,  9],
     #   [10, 11]]])
</code></pre>
<hr>
<h2 id="차원-확장-expansion">차원 확장 (Expansion)</h2>
<h3 id="1-reshape-사용">(1) reshape() 사용</h3>
<p>가장 기본적인 방법으로, 전체 요소의 개수만 맞으면 자유롭게 확장 가능합니다.</p>
<pre><code class="language-python">    import numpy as np
    x3 = np.arange(6)  # (6,)

    # (6,) =&gt; (6, 1) 로 차원 확장
    x3 = x3.reshape(6, 1)  #덮어쓰기를 해야지 적용된다!!!!

    # (6, 1) =&gt; (6, 1, 1) 로 추가 확장
    x3 = x3.reshape(6, 1, 1)</code></pre>
<h3 id="2-npexpand_dims-사용">(2) np.expand_dims() 사용</h3>
<p>특정 축(axis)을 지정하여 그 자리에 차원을 &#39;삽입&#39;합니다. </p>
<pre><code class="language-python">    x5 = np.arange(3)  # (3,)

    # axis=0: 맨 앞에 차원 추가 (3,) -&gt; (1, 3)
    y5 = np.expand_dims(x5, axis=0)

    x6 = np.arange(4).reshape(2, 2)

    # axis=-1: 마지막에 차원 추가 (2, 2) -&gt; (2, 2, 1)
    y7 = np.expand_dims(x6, axis=-1)

    # 여러 축에 동시 추가 가능: (2, 2) -&gt; (1, 2, 2, 1)
    y8 = np.expand_dims(x6, axis=(0, -1))</code></pre>
<h3 id="3-npnewaxis-활용-indexing">(3) np.newaxis 활용 (Indexing)</h3>
<p>슬라이싱 연산 중에 직관적으로 차원을 늘릴 수 있어 실무에서 매우 선호되는 방식입니다.</p>
<pre><code class="language-python">    x8 = np.array([2, 0, 1, 8])  # (4,)

    # 1차원 벡터를 행 벡터(Row Vector)로 변환: (4,) -&gt; (1, 4)
    row_vec = x8[np.newaxis, :]

    # 1차원 벡터를 열 벡터(Column Vector)로 변환: (4,) -&gt; (4, 1)
    col_vec = x8[:, np.newaxis]</code></pre>
<hr>
<h2 id="차원-제거-reduction">차원 제거 (Reduction)</h2>
<h3 id="1-npsqueeze">(1) np.squeeze()</h3>
<p>차원 중 사이즈가 <strong>1</strong>인 것들을 모두 찾아 제거합니다. 데이터의 본질적인 값은 유지하면서 불필요한 껍데기(차원)를 벗겨냅니다.</p>
<pre><code class="language-python">    # (2, 1, 3, 1) 구조의 배열 생성
    x4 = np.arange(6).reshape((2, 1, 3, 1))

    # 사이즈가 1인 차원을 모두 제거: (2, 1, 3, 1) -&gt; (2, 3)
    squeezed_x4 = x4.squeeze()</code></pre>
<h3 id="2-특정-차원만-제거하기">(2) 특정 차원만 제거하기</h3>
<p><code>squeeze()</code>의 <code>axis</code> 파라미터를 사용하면 사이즈가 1인 차원이 여러 개일 때 원하는 것만 골라 제거할 수 있습니다.</p>
<pre><code class="language-python">    # x4.squeeze(axis=1) -&gt; (2, 3, 1)</code></pre>
<hr>
<h2 id="4-축axis의-이해">4. 축(axis)의 이해</h2>
<p>Numpy 연산에서 <code>axis</code> 파라미터는 매우 중요합니다.
axis (축) 은 각 &#39;차원&#39; 을 의미합니다.
<strong>axis= 값을 명시</strong>하면 그 함수의 연산 은 해당 axis(축) 에 &#39;따라서&#39; 연산을 수행함</p>
<ul>
<li>1차원 array 라면  각 차원에 대한 axis 값은 0  &lt;- 1개 입니다.</li>
<li>2차원 array 라면  각 차원에 대한 axis 값은 0, 1  &lt;- 2개 입니다.</li>
<li>3차원 array 라면  각 차원에 대한 axis 값은 0, 1, 2  &lt;- 3개 입니다.<pre><code class="language-python"></code></pre>
</li>
</ul>
<p><code>axis=0</code>: 행을 따라 연산 (세로로 더하기)
<code>axis=1</code>: 열을 따라 연산 (가로로 더하기)</p>
<p>x1 = np.arange(15)</p>
<p>np.sum(x1)  #np.int64(105)
np.sum(x1,axis=None) #np.int64(105)  </p>
<p>x2 = x1.reshape(3, 5)
#array([[ 0,  1,  2,  3,  4],</p>
<h1 id="-5--6--7--8--9">[ 5,  6,  7,  8,  9],</h1>
<h1 id="10-11-12-13-14">[10, 11, 12, 13, 14]])</h1>
<p>np.sum(x2)  # axis=None,  105</p>
<p>np.sum(x2, axis=0) #행끼리 연산  (3,5) =&gt; (5,) axis=0인 3을 제거한 것
#array([15, 18, 21, 24, 27]) 행이 사라지고 열의 형태만 남음</p>
<p>np.sum(x2, axis=1) #(3,5) =&gt; (3,) 얘는 1인 5를 제거한 것 
#array([10, 35, 60]) 열(세로)이 사라지고 행(가로)의 형태만 남음</p>
<pre><code>---







## 5. 인덱싱과 슬라이싱

### 인덱싱(index)
 - 파이썬 리스트와 동일한 개념으로 사용합니다.
 - tuple 를 사용하여 각 차원별 인덱스에 접근 가능합니다. 
 - 인덱싱 할때마다 차원감소됩니다. 


```python
 y = np.arange(10).reshape(2, 5) # 2차원
#array([[0, 1, 2, 3, 4],
        #[5, 6, 7, 8, 9]])

#출력 결과
y[0]
#array([0, 1, 2, 3, 4]) 1차원으로 차원감소

y[0][2]
# np.int64(2) scarler 값으로 차원 감소 

# 콤마(튜플)로 차원별 인덱싱 가능!  numpy 에선 후자의 방법을 추천!(중요)
y[0,2] #위와 결과가 같음. 
# np.int64(2) scarler 값으로 차원 감소 
</code></pre><h3 id="슬라이싱-slicing">슬라이싱 (Slicing)</h3>
<p>리스트와 달리 다차원에서 콤마(<code>,</code>)를 이용한 동시 슬라이싱이 가능하며,
슬라이싱 결과는 차원을 유지합니다.</p>
<pre><code class="language-python">y = [[0, 1, 2, 3, 4],
     [5, 6, 7, 8, 9],
     [10, 11, 12, 13, 14]]


# 과연 아래와 같이 slicing 가능한가?
# [[1, 2, 3],
#  [6, 7, 8]]    


y[:2][1:4] #안된다
# ↑ list 는 차원별 slicing 이 불가능하다!    
# 출력 결과 : [[5, 6, 7, 8, 9]]

# ↓ Numpy Array 는 차원별 slicing 가능하다!
x = np.arange(15).reshape(3, 5)
x

#이렇게가 아니라
x[:2][1:4]    #출력 결과 : array([[5, 6, 7, 8, 9]])

#이렇게!
x[:2, 1:4]    #출력 결과 : array([[1, 2, 3],
                                #[6, 7, 8]])


x[2, 1:4]     #출력 결과 : array([11, 12, 13])
</code></pre>
<hr>
<h3 id="배열의-축-바꾸기-t-transpose-swapaxes">배열의 축 바꾸기 (T, transpose, swapaxes)</h3>
<p>데이터의 행과 열을 바꾸거나, 고차원 텐서의 차원 순서를 변경하는 방법을 정리합니다.
<img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtmNz3%2FbtqDk6Xy5nh%2FD7U80E2R3fnahK00cijoY1%2Fimg.png" alt=""></p>
<hr>
<h2 id="2차원-배열의-전치-transpose">2차원 배열의 전치 (Transpose)</h2>
<p>가장 기본적으로 행과 열을 서로 맞바꾸는 동작입니다.</p>
<pre><code class="language-python">    import numpy as np
    a = np.arange(15).reshape(3, 5) # (3, 5)

    # 방법 1: np.transpose()
    np.transpose(a) # (5, 3)

    # 방법 2: .T 속성 (가장 많이 사용됨)
    a.T 

    # 방법 3: swapaxes() - 0번 축과 1번 축을 교환
    np.swapaxes(a, 0, 1)</code></pre>
<hr>
<h2 id="2-고차원-배열에서의-축-변경">2. 고차원 배열에서의 축 변경</h2>
<p>3차원 이상의 배열에서는 단순히 뒤집는 것보다 <strong>특정 축의 순서를 지정</strong>하는 것이 중요합니다.</p>
<h3 id="1-nptransposearray-axes">(1) np.transpose(array, axes)</h3>
<p>축의 순서를 리스트나 튜플로 지정합니다. 지정하지 않으면 역순으로 바뀝니다.</p>
<pre><code class="language-python">    # (2, 3, 5) -&gt; 축 번호는 (0, 1, 2)
    b = np.random.randn(2, 3, 5)

    # 0번과 1번의 위치를 바꾸고 싶을 때
    b_trans = b.transpose(1, 0, 2) # 결과 shape: (3, 2, 5)

### (2) np.swapaxes(array, axis1, axis2)
전체 순서를 고민할 필요 없이, **바꾸고 싶은 두 개의 축**만 딱 집어서 교환합니다.

    # 0번 축과 2번 축을 교환
    b_swapped = np.swapaxes(b, 0, 2) # 결과 shape: (5, 3, 2)</code></pre>
<hr>
<h3 id="요약">요약</h3>
<ul>
<li><strong><code>.T</code></strong>: 2차원 행렬 뒤집기용 (간편함)</li>
<li><strong><code>transpose()</code></strong>: 전체 축 순서를 재설정할 때 (강력함)</li>
<li><strong><code>swapaxes()</code></strong>: 두 축의 위치만 가볍게 바꿀 때 (명확함)</li>
</ul>
<hr>
<h2 id="6--array-연산의-기초-list와의-차이-및-브로드캐스팅">6.  Array 연산의 기초: List와의 차이 및 브로드캐스팅</h2>
<p>파이썬 기본 리스트(List)와 넘파이 배열(Array)의 연산 방식 차이를 이해하고, 넘파이만의 강력한 기능인 브로드캐스팅을 정리합니다.</p>
<hr>
<h2 id="파이썬-리스트list의-연산">파이썬 리스트(List)의 연산</h2>
<p>리스트에서의 연산은 산술 계산이 아니라 &#39;데이터의 변형(반복, 연결)&#39;을 의미합니다.</p>
<pre><code class="language-python">    a = [10, 20, 30, 40]
    b = 2
    c = [100, 200, 300, 400]

    # 리스트 * 숫자 : 리스트 내용 반복
    print(a * 2)  # [10, 20, 30, 40, 10, 20, 30, 40]

    # 리스트 + 숫자 : TypeError 발생
    # a + b

    # 리스트 + 리스트 : 두 리스트를 하나로 연결
    print(a + c)  # [10, 20, 30, 40, 100, 200, 300, 400]</code></pre>
<hr>
<h2 id="넘파이-배열array의-연산">넘파이 배열(Array)의 연산</h2>
<p>배열의 연산은 기본적으로 <strong>원소끼리(Element-wise)</strong> 수행됩니다. 수학적 행렬/벡터 연산과 동일하게 동작합니다.</p>
<pre><code class="language-python">    import numpy as np
    x = np.array([1, 2, 3])
    y = np.array([10, 20, 30])

    # 원소별 더하기/빼기
    print(x + y)  # [11, 22, 33]
    print(x - y)  # [-9, -18, -27]
</code></pre>
<hr>
<h2 id="브로드캐스팅-broadcasting">브로드캐스팅 (Broadcasting)</h2>
<ul>
<li><p>(기본적으로는) Shape이 같은 두 ndarray에 대한 연산은 각 원소별로 진행합니다.</p>
</li>
<li><p><strong>다른 Shape을 갖는 array 간 연산</strong> 의 경우 브로드 캐스팅(Shape을 맞춤) 후 진행합니다.
<img src="https://numpy.org/doc/stable/_images/broadcasting_1.png" alt="">   </p>
<h3 id="1-array와-스칼라scalar-연산">(1) Array와 스칼라(Scalar) 연산</h3>
<p>배열의 모든 원소에 동일한 값을 한 번에 적용합니다.</p>
<pre><code class="language-python"># 모든 원소에 10을 더함
print(x + 10)  # [11, 12, 13]</code></pre>
<h3 id="2-단일-값을-가진-객체와의-연산">(2) 단일 값을 가진 객체와의 연산</h3>
<p>대괄호(<code>[]</code>)의 개수에 따라 연산 후 결과물의 차원(Shape)이 결정됩니다.</p>
<pre><code class="language-python"># x + [10] : 1차원 벡터 간의 연산으로 간주
# [1, 2, 3] + [10, 10, 10]
print(x + [10])  # [11, 12, 13] (1차원)

# x + [[10]] : 2차원 행렬과의 연산으로 간주 (브로드캐스팅)
# x는 (3,)에서 (1, 3)으로 확장되고, [[10]]은 (1, 3)으로 확장됨
# 결과는 [[11, 12, 13]] (2차원)
print(x + [[10]]) 

a = np.arange(12).reshape(4, 3)
b = np.arange(100, 103) # (3,)
a + b # b가 모든 행에 더해짐

 #출력 결과
 array([[100, 102, 104],
         [103, 105, 107],
         [106, 108, 110],
      [109, 111, 113]])  

</code></pre>
</li>
</ul>
<pre><code>
---

## 요약 및 결론

* **List**: `+`는 연결, `*`는 반복을 의미하며 숫자와의 직접 더하기는 불가능합니다.
* **Array**: 모든 산술 연산이 **원소 단위**로 이루어집니다.
* **Broadcasting**: `[[10]]`처럼 고차원 단일 값과 연산하면, 결과 배열도 해당 **고차원 형태**를 따라갑니다.





---

## 7. 불리언 인덱싱 (Boolean Indexing) ★중요
조건에 맞는 데이터만 추출하는 강력한 기능입니다.
array 인덱싱 시, bool 리스트(aka. mask)를 전달하여 True인 경우만 필터링 합니다. 
for 사용하지 않고도 array 에서 &#39;조건&#39;에 맞는 데이터만 추출 하는 기능
```python
    # 브로드캐스팅을 활용하여 array로 부터 bool list 얻기
    #  - 예) 짝수인 경우만 찾아보기

    np.random.seed(41)
    x = np.random.randint(1, 100, size=10)

    even_mask = x % 2 ==0
    # 위와 같이 bool 값으로 이루어진 array 를 Mask 라고도 한다

    print(even_mask) # True, False들로 구성. 
    # x[[True,True,True,True,False,False,False,False,False,True]]

    x[even_mask]  #True 값들만 출력


    x = np.random.randint(1, 100, 10)
    # 30보다 큰 짝수만 추출
    mask = (x &gt; 30) &amp; (x % 2 == 0) #이때 and는 사용(x), &amp;만 사용 가능
    x[mask]

</code></pre><hr>
<h2 id="8-실습-예제-서울시-5월-기온-분석">8. 실습 예제: 서울시 5월 기온 분석</h2>
<pre><code>temp = np.array([23.9, 24.4, 24.1, 25.4, 27.6, 29.7, 26.7, 25.1, 25.0, 22.7, 21.9, 23.6, 24.9, 25.9, 23.8, 24.7, 25.6, 26.9, 28.6, 28.0, 25.1, 26.7, 28.1, 26.5, 26.3, 25.9, 28.4, 26.1, 27.5, 28.1, 25.8])

# Q1. 평균기온이 25도를 넘는 날의 수는?
over_25 = temp[temp &gt; 25]
print(len(over_25))

# Q2. 평균기온이 25도를 넘는 날의 평균기온은?
print(f&quot;{over_25.mean():.1f}도&quot;)</code></pre><hr>
<h2 id="9-nprandom-서브-모듈">9. np.random 서브 모듈</h2>
<ul>
<li>rand: 0부터 1사이의 균일 분포 [0, 1)  uniform distribution</li>
<li>randn: 가우시안 표준 정규 분포 (평균0, 표준편차1 인 종모양 분포)  normal distribution</li>
<li>randint: 균일 분포의 정수 난수</li>
<li>seed: 램덤 시드값.  고정 난수값 생성</li>
</ul>
<p><img src="https://thebook.io/img/080263/218.jpg" alt=""></p>
<pre><code class="language-python">
np.random.rand(10) #0부터 1까지 랜덤 숫자 생성


np.random.rand(2,3) #값 3개 가진 이중 배열

np.random.randn(5) #정규분포를 가진 5개 랜덤 숫자 생성


np.random.randint(5) # 0 ~ 4 사이의 정수 난수 [0, 5) 1개 생성

np.random.randint(1,10) #[1,10) # 1 ~ 9 사이의 정수 난수 1개 생성

np.random.randint(1,100,(3,5,2)) #3중 배열로 2중 배열 3개, 각 2중 배열에 1차원 배열 5개씩 생성

# seed() : 난수를 예측가능하도록 만든다.  실행할때마다 동일한 난수가 발생되도록 함.
np.random.seed(0) #이걸 사용하는 다른 컴퓨터도 동일한 결과를 내놓게 함.
np.random.rand(4)


#  비결정적 연산 (Non-Deterministic Operations)
#    같은 코드, 같은 입력을 줬는데도 결과가 매번 조금씩 달라지는 연산

#  결정적 연산 (Deterministic Operations)
#    같은 코드, 같은 입력, 같은 시드를 주면 결과가 동일한 연산
</code></pre>
<hr>
<h2 id="10-통계-함수와-nannot-a-number">10. 통계 함수와 NaN(Not a Number)</h2>
<p>배열에서 최댓값과 그 위치를 찾는 방법, 그리고 데이터 분석의 필수 관문인 결측치(NaN)의 특징을 정리합니다.</p>
<hr>
<h2 id="최댓값-찾기-max와-argmax">최댓값 찾기: max()와 argmax()</h2>
<p>넘파이에서는 단순히 최댓값을 찾는 것뿐만 아니라, 그 값이 어디에 위치해 있는지도 쉽게 알 수 있습니다.</p>
<h3 id="1-전체-대상-연산">(1) 전체 대상 연산</h3>
<p>별도의 축 지정이 없으면 배열을 1차원으로 펼쳤을 때를 기준으로 계산합니다.</p>
<pre><code class="language-python">    import numpy as np
    y = np.array([[0, 1, 2, 3, 4],
                  [5, 6, 7, 8, 9],
                  [10, 11, 12, 13, 14]])

    # 전체 최댓값
    np.max(y) # 14

    # 전체 최댓값의 인덱스 (펼쳤을 때의 번호)
    np.argmax(y) # 14</code></pre>
<h3 id="2-축axis별-연산">(2) 축(axis)별 연산</h3>
<p>특정 방향(행 또는 열)을 기준으로 최댓값을 찾습니다.</p>
<pre><code class="language-python">    # axis=0 (열 방향): 위에서 아래로 훑으며 최댓값 찾기
    # 결과 모양: (3, 5) -&gt; (5,)
    np.max(y, axis=0) # [10, 11, 12, 13, 14]

    # 열 방향 최댓값의 인덱스
    np.argmax(y, axis=0) # [2, 2, 2, 2, 2] (모두 마지막 행에 있음)</code></pre>
<hr>
<h2 id="결측치-처리-nan-not-a-number">결측치 처리: NaN (Not a Number)</h2>
<p><code>NaN</code>은 정의되지 않거나 표현할 수 없는 수치 결과를 의미하며, 실무 데이터(누락값, DBMS의 null 등)에서 매우 자주 마주하게 됩니다.</p>
<h3 id="1-nan의-특징">(1) NaN의 특징</h3>
<p><code>NaN</code>은 수치형 데이터 타입(float)이지만, <strong>어떤 연산을 해도 결과는 NaN</strong>이 된다는 치명적인 특징이 있습니다.</p>
<pre><code class="language-python">    np.nan  # nan

    # NaN과의 연산 결과는 무조건 NaN
    print(np.nan + 10) # nan

    arr = np.array([10, 20, np.nan])
    print(np.sum(arr)) # nan (하나만 섞여 있어도 결과가 파괴됨)</code></pre>
<h3 id="2-nan-판별하기-isnan">(2) NaN 판별하기: isnan()</h3>
<p><code>NaN</code>은 일반적인 비교 연산자(<code>==</code>)로 확인할 수 없으므로, 반드시 전용 함수를 사용해야 합니다.</p>
<pre><code class="language-python">    # 100은 숫자인가? (False)
    np.isnan(100) # False

    # np.nan은 NaN인가? (True)
    np.isnan(np.nan) # True

    # math 라이브러리에서도 동일하게 제공
    import math
    math.isnan(np.nan) # True</code></pre>
<hr>
<h2 id="요약-및-주의사항">요약 및 주의사항</h2>
<ul>
<li><strong>데이터 분석의 필수:</strong> 원본 데이터에 <code>NaN</code>이 포함되어 있다면 통계값(평균, 합계 등)이 왜곡될 수 있으므로, 연산 전에 반드시 제거하거나 다른 값(0이나 평균값 등)으로 <strong>치환</strong>해야 합니다.</li>
<li><strong>차원 축소:</strong> <code>max(axis=0)</code>을 하면 해당 축이 사라지며 차원이 축소됩니다. (3x5 배열이 5개짜리 1차원 배열로 변함)</li>
</ul>
<hr>
<h2 id="팁-nan을-무시하고-계산하고-싶다면">팁: NaN을 무시하고 계산하고 싶다면?</h2>
<p>넘파이에는 <code>NaN</code>을 제외하고 계산해주는 <code>nan-safe</code> 함수들이 별도로 존재합니다.</p>
<ul>
<li><code>np.nansum(arr)</code>: NaN을 0으로 간주하고 합계 계산</li>
<li><code>np.nanmax(arr)</code>: NaN을 제외한 최댓값 계산</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 11일차(Scope)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-11%EC%9D%BC%EC%B0%A8Scope</link>
            <guid>https://velog.io/@snow-jun-0/MCP-11%EC%9D%BC%EC%B0%A8Scope</guid>
            <pubDate>Sun, 15 Feb 2026 04:12:23 GMT</pubDate>
            <description><![CDATA[<h1 id="scope-변수-범위-완벽-정리">Scope (변수 범위) 완벽 정리</h1>
<p>변수명, 함수명, 클래스명 등 이름(name)이 사용될 수 있는 영역을 <strong>Scope</strong>라고 합니다. 즉, 변수가 살아있는 범위와 이를 어디에서 사용할 수 있는지에 대한 규칙입니다.</p>
<hr>
<h2 id="1-global-variable--global-scope-전역-변수">1. Global Variable &amp; Global Scope (전역 변수)</h2>
<p>함수 바깥에서 선언한 변수로, 스크립트 전체에서 접근할 수 있습니다.</p>
<pre><code class="language-python">    x = 10  # 전역 변수

    def foo():
        print(x)  # 함수 안에서도 전역변수 &#39;읽기&#39; 동작 가능

    foo()
    print(x)</code></pre>
<hr>
<h2 id="2-local-variable--local-scope-지역-변수">2. Local Variable &amp; Local Scope (지역 변수)</h2>
<p>함수 안에서 선언된 변수는 해당 함수 내부에서만 접근 가능하며, 함수 종료(리턴)와 함께 소멸합니다.</p>
<pre><code class="language-python">    def foo():
        y = 10  # y는 foo의 지역변수
        print(y)

    foo()
    # print(y)  # 에러 발생: 함수 밖에서는 지역 변수에 접근 불가</code></pre>
<hr>
<h2 id="3-함수-안에서-전역-변수-수정하기-쓰기-동작">3. 함수 안에서 전역 변수 수정하기 (쓰기 동작)</h2>
<p>함수 내에서 전역 변수와 동일한 이름에 값을 대입하면, 파이썬은 이를 새로운 <strong>지역 변수</strong>로 간주합니다.</p>
<pre><code class="language-python">    z = 10

    def foo():
        z = 20  # z는 foo의 지역변수로 새로 생성됨 (쓰기 동작)
        print(z) # 지역변수 z(20) 출력

    foo()    # 20
    print(z) # 10 (전역 변수는 변하지 않음)</code></pre>
<h3 id="-주의-unboundlocalerror">※ 주의: UnboundLocalError</h3>
<p>함수 내에서 변수에 값을 대입하는 코드가 있으면 파이썬은 그 변수를 지역 변수로 인지합니다. 대입 전에 사용하려고 하면 에러가 발생합니다.</p>
<pre><code class="language-python">    a = 1
    def foo():
        # a = a + 1  # 에러 발생: a를 지역 변수로 인식했지만 값이 할당되기 전임
        print(&#39;foo] a=&#39;, a)</code></pre>
<hr>
<h2 id="4-전역-변수-값을-변경하는-방법">4. 전역 변수 값을 변경하는 방법</h2>
<h3 id="방법-1-return-값-활용-추천">방법 1: return 값 활용 (추천)</h3>
<p>가장 깔끔하고 구조적인 방법입니다.</p>
<pre><code class="language-python">    a = 1  # 전역변수

    def foo(a):  # 매개변수 a (지역변수)
        a = a + 1
        return a

    a = foo(a)  # 리턴값으로 전역변수 a를 갱신
    print(&#39;전역 a=&#39;, a)</code></pre>
<h3 id="방법-2-global-키워드-사용-비추천">방법 2: global 키워드 사용 (비추천)</h3>
<p>코드의 의존성을 높여 유지보수를 어렵게 만들 수 있습니다.</p>
<pre><code class="language-python">    a = 1

    def foo():
        global a  # 이 함수 안에서 사용하는 a는 전역변수임을 선언
        a = a + 1
        print(&#39;foo] a=&#39;, a)

    foo()
    print(&#39;전역 a=&#39;, a)</code></pre>
<hr>
<h2 id="5-네임스페이스-namespace와-legb-규칙">5. 네임스페이스 (Namespace)와 LEGB 규칙</h2>
<p>네임스페이스는 &#39;이름&#39;들이 담겨있는 공간입니다. <code>locals()</code>를 통해 확인할 수 있습니다.</p>
<h3 id="legb-규칙-이름-검색-순서">LEGB 규칙 (이름 검색 순서)</h3>
<p>이름을 찾을 때 <strong>L → E → G → B</strong> 순서로 탐색합니다.</p>
<ol>
<li><strong>L (Local)</strong>: 함수 내부</li>
<li><strong>E (Enclosing)</strong>: 중첩 함수에서 바깥 함수 범위</li>
<li><strong>G (Global)</strong>: 전역 변수 범위</li>
<li><strong>B (Built-in)</strong>: 파이썬 내장 함수/변수 (print, len 등)</li>
</ol>
<pre><code class="language-python">    k = 100 //Global
    def aaa():
        k = 200  # Enclosing scope가 됨
        print(k)  # Local

        def bbb():
            # k를 찾을 때: L(없음) -&gt; E(여기 있네!)
            print(k)

        bbb()

    aaa()

 #출력 결과
 200
 200

</code></pre>
<hr>
<h2 id="6-python-scope의-특징-block-scope의-부재">6. Python Scope의 특징: Block Scope의 부재</h2>
<p><strong>Python은 if, for, while, try, with 블록에서 새로운 Scope를 생성하지 않습니다.</strong></p>
<p>Java나 C, JavaScript(let, const)와는 대조적인 특징입니다. 블록 안에서 선언한 변수도 블록 밖(동일 함수 내 또는 전역)에서 사용 가능합니다.</p>
<pre><code class="language-python">    # for문 예시
    for i in range(3):
        xx = i * 10  # xx는 전역 scope에 생성됨

    print(xx)  # for 바깥에서도 사용 가능 (20 출력)

    # if문 예시
    if True:
        yy = 100
    print(yy)  # 사용 가능</code></pre>
<h3 id="scope-생성-기준-정리">Scope 생성 기준 정리</h3>
<ul>
<li><strong>새로운 Scope 생성</strong>: <code>def</code>(함수), <code>lambda</code>, <code>class</code></li>
<li><strong>기존 Scope 유지</strong>: <code>if</code>, <code>for</code>, <code>while</code>, <code>try-except</code>, <code>with</code></li>
</ul>
<hr>
<h2 id="7-nonlocal-키워드">7. nonlocal 키워드</h2>
<p>중첩 함수에서 바깥 함수의 변수를 수정하고 싶을 때 사용합니다.</p>
<pre><code class="language-python">    k = 100
    def aaa():
        k = 200
        print(&quot;aaa 내부 k:&quot;, k)

        def bbb():
            nonlocal k  # bbb의 지역변수가 아니라 aaa의 k를 사용하겠다고 선언
            k = k + 1
            print(&quot;bbb 내부 k:&quot;, k)

        bbb()
        print(&quot;bbb 호출 후 aaa의 k:&quot;, k)

    aaa()
    print(&quot;전역 k:&quot;, k)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 10일차(동기 & 비동기)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-10%EC%9D%BC%EC%B0%A8%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0</link>
            <guid>https://velog.io/@snow-jun-0/MCP-10%EC%9D%BC%EC%B0%A8%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0</guid>
            <pubDate>Sat, 14 Feb 2026 18:00:51 GMT</pubDate>
            <description><![CDATA[<h1 id="asyncio를-이용한-비동기-프로그래밍-이해하기">asyncio를 이용한 비동기 프로그래밍 이해하기</h1>
<p>파이썬의 <code>asyncio</code> 모듈을 사용하여 동기(Synchronous)와 비동기(Asynchronous) 방식의 차이점을 알아보고 실무적인 사용법을 정리합니다.</p>
<hr>
<h2 id="1-동기synchronous-vs-비동기asynchronous">1. 동기(Synchronous) vs 비동기(Asynchronous)</h2>
<h3 id="🌐-동기-프로그래밍-synchronous">🌐 동기 프로그래밍 (Synchronous)</h3>
<ul>
<li><strong>개념:</strong> 작업을 순차적으로 처리합니다. 앞선 작업이 완료되어야 다음으로 넘어갑니다.</li>
<li><strong>장점:</strong> 설계가 간단하고 디버깅이 쉽습니다.</li>
<li><strong>단점:</strong> I/O 작업(네트워크, 파일 읽기 등)처럼 시간이 걸리는 작업 시 전체 프로세스가 멈춥니다(Blocking).</li>
</ul>
<h3 id="⚡-비동기-프로그래밍-asynchronous">⚡ 비동기 프로그래밍 (Asynchronous)</h3>
<ul>
<li><strong>개념:</strong> 작업을 시작한 뒤 완료를 기다리지 않고 다음 작업을 수행합니다. 결과는 나중에 통지받습니다.</li>
<li><strong>장점:</strong> 자원을 효율적으로 사용하며, 여러 작업을 동시에 처리할 때 성능이 극대화됩니다.</li>
<li><strong>단점:</strong> 코드 흐름이 복잡해질 수 있으며 디버깅이 상대적으로 까다롭습니다.</li>
</ul>
<h2 id=""><img src="https://velog.velcdn.com/images%2Fdat0802%2Fpost%2F32583695-bf93-4d6e-856b-fe04e1cd2f1f%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-18%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%203.36.46.png" alt=""></h2>
<h2 id="2-파이썬의-비동기-문법-async--await">2. 파이썬의 비동기 문법 (async / await)</h2>
<p>파이썬 3.5부터 <code>async</code>와 <code>await</code> 키워드가 공식 도입되어 비동기 프로그래밍을 지원합니다.</p>
<h3 id="코루틴coroutine-정의-및-호출">코루틴(Coroutine) 정의 및 호출</h3>
<pre><code class="language-python">    import asyncio
    import time

    # async def로 선언하면 코루틴 객체를 리턴하는 함수가 됩니다.
    async def hello():
        print(&#39;hello python!&#39;)

    # 일반적인 호출 방식으로는 실행되지 않습니다.
    # await hello() 또는 asyncio.run(hello())를 사용해야 합니다.</code></pre>
<hr>
<h2 id="3-동기-방식-예제-timesleep">3. 동기 방식 예제 (time.sleep)</h2>
<p>동기 방식에서는 모든 작업 시간이 합산되어 나타납니다.</p>
<pre><code class="language-python">    def sync_work(icon, seconds=0):
        print(f&#39;{icon} {seconds}초 작업 시작&#39;)
        start = time.time()
        time.sleep(seconds)  # 작업이 끝날 때까지 여기서 멈춤
        end = time.time()
        print(f&quot;{icon} 작업종료: {end-start:.3f}초 소요&quot;)

    def sync_all():
        sync_work(&#39;🍆&#39;, 3)
        sync_work(&#39;🍊&#39;, 1)
        sync_work(&#39;🥦&#39;, 2)

    start = time.time()
    sync_all()
    end = time.time()
    print(f&#39;&gt;&gt;&gt; 총 경과시간: {end - start:.3f}초&#39;)
    # 결과: 약 6초 (3+1+2)

</code></pre>
<hr>
<h2 id="4-비동기-방식-예제-asynciosleep">4. 비동기 방식 예제 (asyncio.sleep)</h2>
<p>비동기 방식에서는 대기 시간 동안 다른 작업을 수행하므로, 가장 오래 걸리는 작업 시간을 기준으로 전체 작업이 완료됩니다.</p>
<pre><code class="language-python">    async def async_work(icon, seconds=0):
        print(f&#39;{icon} {seconds}초 작업 시작&#39;)
        start = time.time()
        await asyncio.sleep(seconds)  # 대기하는 동안 제어권을 넘김
        end = time.time()
        print(f&#39;{icon} 작업종료: {end - start:.3f}초 소요&#39;)
        return f&#39;{icon}-{seconds}작업&#39;

    async def async_all():
        # Task를 생성하여 비동기 실행을 예약합니다.
        task1 = asyncio.create_task(async_work(&#39;🍆&#39;, 3))
        task2 = asyncio.create_task(async_work(&#39;🍊&#39;, 1))
        task3 = asyncio.create_task(async_work(&#39;🥦&#39;, 2))

        # gather를 통해 여러 비동기 작업을 동시에 기다리고 결과값을 모읍니다.
        result = await asyncio.gather(task1, task2, task3)
        return result

    start = time.time()
    # 주피터/코랩 환경이 아닐 경우 asyncio.run(async_all()) 사용
    result = await async_all() 
    end = time.time()
    print(f&#39;&gt;&gt;&gt; 총 경과시간: {end - start:.3f}초&#39;)
    print(f&#39;결과 리스트: {result}&#39;)
    # 결과: 약 3초 (가장 긴 작업인 3초에 수렴)

</code></pre>
<hr>
<h3 id="요약">요약</h3>
<ul>
<li><strong>동기:</strong> 순차적 실행 (3+1+2 = 6초)</li>
<li><strong>비동기:</strong> 병렬적 대기 (max(3, 1, 2) = 3초)</li>
<li><strong>핵심:</strong> I/O Bound 작업이 많은 현대 애플리케이션에서 <code>asyncio</code>는 성능 향상의 필수 요소입니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 10일차(Gemini API사용)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-10%EC%9D%BC%EC%B0%A8Gemini-API%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@snow-jun-0/MCP-10%EC%9D%BC%EC%B0%A8Gemini-API%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Sat, 14 Feb 2026 17:06:52 GMT</pubDate>
            <description><![CDATA[<h1 id="gemini-api-사용법-및-환경-설정-가이드">Gemini API 사용법 및 환경 설정 가이드</h1>
<h2 id="1-api-key-보안-및-환경변수-설정">1. API Key 보안 및 환경변수 설정</h2>
<p>API Key와 같은 민감한 정보는 소스 코드에 직접 노출하지 않고 환경변수로 관리하는 것이 보안상 필수입니다.</p>
<h3 id="환경변수-로드-및-확인">환경변수 로드 및 확인</h3>
<pre><code class="language-python">    import os
    os.environ[&#39;LANGUAGE&#39;]
    os.environ[&#39;GEMINI_API_KEY&#39;] #여기에 제미나이 키 입력

    # 별도의 환경변수 파일을 만들고
    # 실행시 환경변수 로딩을 하고 사용하기

    # .env 파일 작성


    from dotenv import load_dotenv
    load_dotenv()  # 환경변수 파일(기본 &#39;.env&#39;)을 읽어들여 환경변수 등록.
               # 성공하면 True 리턴

     api_key = os.environ[&#39;GEMINI_API_KEY&#39;]  #여기에 제미나이 키 입력         
</code></pre>
<hr>
<h2 id="2-gemini-api-기본-호출">2. Gemini API 기본 호출</h2>
<p>라이브러리 설치: <code>pip install google-genai</code></p>
<h3 id="기본-텍스트-생성">기본 텍스트 생성</h3>
<pre><code class="language-python">    from google import genai

    client = genai.Client()

    # 모델 호출
    response = client.models.generate_content(
        model=&quot;gemini-3-flash-preview&quot;,
        contents=&quot;Google Gemini에 대해 설명해줘&quot;,
    )
    print(response.text) # 설명이 다 나옵니다.  </code></pre>
<hr>
<h2 id="3-주요-기능-활용하기">3. 주요 기능 활용하기</h2>
<h3 id="스트리밍-streaming">스트리밍 (Streaming)</h3>
<p>답변이 생성되는 대로 즉시 출력하여 사용자 경험을 개선합니다.</p>
<pre><code class="language-python">from google import genai

client = genai.Client()

# 모델 호출
response = client.models.generate_content_stream(  # generate_content_stream 는 iterable 리턴
    model=&quot;gemini-3-flash-preview&quot;,
    contents=&quot;Google Gemini 에 대해 설명해줘&quot;,
)

for chunk in response:
  print(chunk.text, end=&quot;&quot;)</code></pre>
<h3 id="시스템-인스트럭션-system-instruction">시스템 인스트럭션 (System Instruction)</h3>
<p>모델의 페르소나나 답변 스타일을 고정할 수 있습니다.</p>
<pre><code class="language-python">from google import genai
from google.genai import types

client = genai.Client()

# 모델 호출
response = client.models.generate_content(
    model=&quot;gemini-3-flash-preview&quot;,

    config= types.GenerateContentConfig(
        system_instruction=&quot;너는 고양이다.  너의 이름은 &#39;냐코&#39; 다&quot;
    ),

    contents=&quot;안녕?&quot;,
)

print(response.text) #고양이처럼 말해줍니다. </code></pre>
<h3 id="온도-조절-temperature">온도 조절 (Temperature)</h3>
<p>0.0에 가까울수록 결정론적(일관적)이고, 1.0에 가까울수록 창의적인 답변을 생성합니다.
    config = types.GenerateContentConfig(temperature=0.1)
    # ... 호출 시 config 적용</p>
<pre><code class="language-python">from google import genai
from google.genai import types

client = genai.Client()

# 모델 호출
response = client.models.generate_content(
    model=&quot;gemini-3-flash-preview&quot;,

    config= types.GenerateContentConfig(
        temperature=0.1
    ),

    contents=&quot;AI 가 어떻게 동작하는지 알려줘&quot;,
)

print(response.text)
</code></pre>
<hr>
<h2 id="4-멀티모달-multi-modal-추론">4. 멀티모달 (Multi-modal) 추론</h2>
<p>텍스트뿐만 아니라 이미지를 함께 입력으로 전달하여 분석할 수 있습니다.</p>
<h3 id="이미지-분석-예시">이미지 분석 예시</h3>
<pre><code class="language-python">    import requests
    from PIL import Image
    from io import BytesIO
    from google import genai

    # 이미지 로드
    url = &quot;https://cdn.britannica.com/18/129118-050-BF48319E/organ.jpg&quot;
    img_data = requests.get(url).content
    image = Image.open(BytesIO(img_data))

    # 이미지와 텍스트를 함께 전달
    client = genai.Client()
    response = client.models.generate_content(
        model=&quot;gemini-3-flash-preview&quot;,
        contents=[image, &quot;이 악기에 대해 설명해 줘&quot;],
    )
    print(response.text)</code></pre>
<hr>
<h2 id="5-gemini-모델-사이즈-요약">5. Gemini 모델 사이즈 요약</h2>
<ul>
<li><strong>Ultra</strong>: 복잡한 추론 및 코딩 작업용 최상위 모델</li>
<li><strong>Pro</strong>: 성능과 속도의 균형이 잡힌 범용 모델</li>
<li><strong>Flash</strong>: 실시간 응답이 필요한 고효율 경량 모델</li>
<li><strong>Nano</strong>: 모바일 기기 내부에서 작동하는 온디바이스 모델</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 9일차(Try ~ except)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-9%EC%9D%BC%EC%B0%A8Try-except</link>
            <guid>https://velog.io/@snow-jun-0/MCP-9%EC%9D%BC%EC%B0%A8Try-except</guid>
            <pubDate>Sat, 14 Feb 2026 14:25:44 GMT</pubDate>
            <description><![CDATA[<h1 id="예외-처리-exception--error-handling">예외 처리 (Exception / Error Handling)</h1>
<h2 id="1-예외-처리란">1. 예외 처리란?</h2>
<p>프로그램 실행 중 발생하는 오류(Error)를 <code>if</code> 조건문으로 일일이 막으려 하면 코드가 매우 난잡해집니다. 파이썬에서는 <strong>&#39;코드 수행 블록&#39;</strong>과 <strong>&#39;예외 처리 블록&#39;</strong>을 분리하여 유지보수를 쉽게 할 수 있도록 
<code>try ~ except</code> 구문을 제공합니다.</p>
<hr>
<h2 id="2-기본-구문-try--except">2. 기본 구문 (try ~ except)</h2>
<p><code>try</code> 블록 수행 중 오류가 발생하면 즉시 <code>except</code> 블록으로 넘어갑니다. 오류가 없으면 <code>except</code> 블록은 무시됩니다.</p>
<pre><code class="language-python">    num = 0

    try:
        print(&#39;1-1 try 시작&#39;)
        result = 10 / num  # ZeroDivisionError 발생 -&gt; except로 점프
        print(&#39;1-2 try 종료&#39;)
    except:
        print(&#39;2. 오류 발생&#39;)

    print(&#39;4. 프로그램 종료&#39;)</code></pre>
<hr>
<h2 id="3-예외의-세분화-및-정보-확인">3. 예외의 세분화 및 정보 확인</h2>
<h3 id="a-특정-오류만-처리하기">A. 특정 오류만 처리하기</h3>
<p>발생할 것으로 예상되는 오류명을 명시하여 각각 다르게 처리할 수 있습니다.</p>
<pre><code class="language-python">    try:
        # result = 10 / 0      # ZeroDivisionError
        result = 10 / &quot;0&quot;      # TypeError
    except ZeroDivisionError:
        print(&#39;2-1. 0으로 나눌 수 없습니다.&#39;)
    except TypeError:
        print(&#39;2-2. 타입이 맞지 않습니다.&#39;)</code></pre>
<h3 id="b-예외-메시지-변수-사용-as-e">B. 예외 메시지 변수 사용 (as e)</h3>
<p>오류의 상세 내용(에러 메시지 등)을 확인하고 싶을 때 <code>as</code> 키워드를 사용합니다.</p>
<pre><code class="language-python">    try:
        result = 10 / &quot;0&quot;
    except TypeError as e:
        print(&#39;오류 발생:&#39;, e)
        print(&#39;추가 정보(args):&#39;, e.args)</code></pre>
<hr>
<h2 id="4-반드시-실행되어야-하는-코드-finally">4. 반드시 실행되어야 하는 코드 (finally)</h2>
<p>오류 발생 여부와 관계없이, 파일을 닫거나 리소스를 해제하는 등 <strong>무조건 실행</strong>되어야 하는 코드는 <code>finally</code>에 작성합니다.</p>
<pre><code class="language-python">    try:
        f = open(&#39;foo.txt&#39;, &#39;w&#39;, encoding=&#39;utf-8&#39;)
        a = 10 + bb  # 정의되지 않은 변수 bb로 인해 NameError 발생
    except Exception as e:
        print(&#39;오류:&#39;, e)
    finally:
        print(&#39;파일을 안전하게 닫습니다.&#39;)
        f.close()</code></pre>
<hr>
<h2 id="5-다중-예외-처리-tuple-사용">5. 다중 예외 처리 (Tuple 사용)</h2>
<p>여러 개의 오류를 하나의 <code>except</code> 블록에서 동시에 처리할 수 있습니다.</p>
<pre><code class="language-python">    try:
        a = [&#39;alpha&#39;, &#39;beta&#39;]
        print(a[2])  # IndexError 발생 가능
        b = 4 / 0    # ZeroDivisionError 발생 가능
    except (IndexError, ZeroDivisionError) as e:
        print(f&quot;에러 발생: {e.args}, 클래스명: {e.__class__.__name__}&quot;)</code></pre>
<hr>
<h2 id="6-예외-강제-발생-raise">6. 예외 강제 발생 (raise)</h2>
<p>개발자가 의도적으로 오류를 일으킬 때 <code>raise</code>를 사용합니다. 주로 부모 클래스를 상속받는 자식 클래스가 특정 메서드를 <strong>반드시 구현(오버라이딩)</strong>하도록 강제할 때 유용합니다.</p>
<pre><code class="language-python">    class Bird:
        def fly(self):
            # 자식 클래스에서 이 메서드를 재정의하지 않으면 에러 발생
            raise NotImplementedError

    class Eagle(Bird):
        # fly()를 오버라이딩 하지 않고 호출하면 에러 발생
        def fly(self):
            print(&quot;독수리는 빠르게 납니다.&quot;)

    # 정상 작동
    eagle = Eagle()
    eagle.fly()</code></pre>
<hr>
<blockquote>
<p><strong>요약</strong>: </p>
<ol>
<li><strong>try</strong>: 실제 코드를 수행하는 곳</li>
<li><strong>except</strong>: 발생한 에러를 잡아서 처리하는 곳</li>
<li><strong>finally</strong>: 에러 유무와 상관없이 마무리 작업을 하는 곳</li>
<li><strong>raise</strong>: 일부러 에러를 던지는 곳</li>
</ol>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 8일차(모듈 & 패키지)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-8%EC%9D%BC%EC%B0%A8%EB%AA%A8%EB%93%88-%ED%8C%A8%ED%82%A4%EC%A7%80</link>
            <guid>https://velog.io/@snow-jun-0/MCP-8%EC%9D%BC%EC%B0%A8%EB%AA%A8%EB%93%88-%ED%8C%A8%ED%82%A4%EC%A7%80</guid>
            <pubDate>Sat, 14 Feb 2026 13:19:36 GMT</pubDate>
            <description><![CDATA[<h1 id="python-모듈module과-패키지package-개념-정리">[Python] 모듈(Module)과 패키지(Package) 개념 정리</h1>
<h2 id="1-모듈-module-이란">1. 모듈 (Module) 이란?</h2>
<ul>
<li><strong>정의</strong>: 함수, 변수, 클래스를 모아놓은 <strong>파이썬 파일(*.py)</strong>입니다.</li>
<li><strong>장점</strong>: <ul>
<li>한 번 만들어 놓으면 다른 프로그램에서 언제든 <code>import</code>하여 재사용 가능합니다.</li>
<li>다른 사람이 만든 유용한 프로그램을 내 코드에 쉽게 가져다 쓸 수 있습니다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="2-모듈-만들기-및-불러오기-import">2. 모듈 만들기 및 불러오기 (import)</h2>
<h3 id="a-모듈-파일-생성-예-mod0py">A. 모듈 파일 생성 (예: mod0.py)</h3>
<p>현재 작업 폴더에 다음과 같은 내용으로 <code>mod0.py</code>를 저장합니다.</p>
<pre><code class="language-python">    my_name = &quot;hong&quot;

    def my_func(*argc):
        print(argc)

    class My_class:
        def __init__(self):
            print(&#39;My_class() 생성&#39;)</code></pre>
<h3 id="b-모듈-사용하기">B. 모듈 사용하기</h3>
<p><code>import 모듈이름</code> 형식으로 불러와서 사용합니다. 이때 모듈 안에 정의된 요소들은 <code>모듈명.이름</code> 형태로 접근합니다.</p>
<pre><code class="language-python">    import mod0

    # 모듈의 변수 사용
    print(mod0.my_name)

    # 모듈의 함수 호출
    mod0.my_func(10, 20, 30)

    # 모듈의 클래스 인스턴스 생성
    mod0.My_class()</code></pre>
<hr>
<h2 id="3-패키지-package-와-모듈-경로">3. 패키지 (Package) 와 모듈 경로</h2>
<ul>
<li><strong>패키지</strong>: 여러 모듈을 디렉토리 구조로 묶어 관리하는 것 (일종의 모듈 주머니).</li>
<li><strong>경로 접근</strong>: 점(<code>.</code>)을 사용하여 하위 디렉토리로 들어갑니다.</li>
</ul>
<h3 id="예시-하위-폴더의-모듈-가져오기">예시: 하위 폴더의 모듈 가져오기</h3>
<p>만약 <code>./Mymodules/mod1.py</code> 경로에 파일이 있다면:</p>
<pre><code class="language-python">    import Mymodules.mod1  # Mymodules는 패키지, mod1은 모듈

    # 사용 시 경로를 다 적어야 해서 이름이 길어짐
    Mymodules.mod1.add_num(10, 20)</code></pre>
<hr>
<h2 id="4-효율적인-import-기법-as-from">4. 효율적인 import 기법 (as, from)</h2>
<h3 id="a-별칭-사용하기-as">A. 별칭 사용하기 (as)</h3>
<p>모듈 명칭이 너무 길거나 복잡할 때 별명을 붙여 사용합니다.</p>
<pre><code class="language-python">    import Mymodules.mod1 as my
    my.add_num(20, 30)</code></pre>
<h3 id="b-특정-요소만-직접-가져오기-from--import">B. 특정 요소만 직접 가져오기 (from ... import)</h3>
<p>모듈명을 생략하고 함수나 변수 이름만 바로 쓰고 싶을 때 사용합니다.</p>
<pre><code class="language-python">    from Mymodules.mod1 import add_num
    add_num(10, 15)  # 모듈명 없이 사용 가능

    # 여러 개를 동시에 가져올 수도 있음
    from mod0 import my_name, my_func
    print(my_name)
    my_func(1, 2, 3)</code></pre>
<hr>
<h2 id="5-파이썬-생태계의-관례적인-별칭-alias">5. 파이썬 생태계의 관례적인 별칭 (Alias)</h2>
<p>데이터 분석이나 인공지능 분야에서 관례적으로 사용하는 줄임말들입니다.</p>
<pre><code class="language-python">    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import tensorflow as tf
    from tensorflow import keras
    from sklearn.model_selection import train_test_split, cross_validate</code></pre>
<hr>
<blockquote>
<p><strong>Tip</strong>: 모듈을 찾지 못할 경우(ModuleNotFoundError), 해당 파일이 현재 실행 중인 스크립트와 같은 경로에 있는지 혹은 파이썬 경로(sys.path)에 등록되어 있는지 확인해야 합니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 7일차(JSON)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-7%EC%9D%BC%EC%B0%A8JSON</link>
            <guid>https://velog.io/@snow-jun-0/MCP-7%EC%9D%BC%EC%B0%A8JSON</guid>
            <pubDate>Sat, 14 Feb 2026 12:29:13 GMT</pubDate>
            <description><![CDATA[<h1 id="json-데이터-처리-완벽-정리">JSON 데이터 처리 완벽 정리</h1>
<h2 id="1-json-javascript-object-notation-이란">1. JSON (JavaScript Object Notation) 이란?</h2>
<ul>
<li><strong>정의</strong>: 데이터 교환 용도의 JavaScript 객체 구문입니다.</li>
<li><strong>특징</strong>: 오늘날 웹, 앱 등 애플리케이션 개발에서 데이터 교환에 사용되는 가장 중요한 <strong>텍스트 포맷</strong>입니다.</li>
</ul>
<hr>
<h2 id="2-데이터-타입-비교-python-vs-js">2. 데이터 타입 비교 (Python vs JS)</h2>
<p>파이썬과 자바스크립트의 데이터 구문은 모양은 거의 동일하나, 명칭과 세부 규칙이 조금 다릅니다.</p>
<table>
<thead>
<tr>
<th align="left">데이터 종류</th>
<th align="left">JSON</th>
<th align="left">파이썬 (Python)</th>
<th align="left">자바스크립트 (JS)</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>숫자</strong></td>
<td align="left">숫자</td>
<td align="left">int, float</td>
<td align="left">number</td>
</tr>
<tr>
<td align="left"><strong>문자열</strong></td>
<td align="left">&quot;&quot; (쌍따옴표)</td>
<td align="left">str</td>
<td align="left">string</td>
</tr>
<tr>
<td align="left"><strong>리스트/배열</strong></td>
<td align="left">[]</td>
<td align="left">list</td>
<td align="left">array</td>
</tr>
<tr>
<td align="left"><strong>객체/딕셔너리</strong></td>
<td align="left">{name:value}</td>
<td align="left">dict</td>
<td align="left">object</td>
</tr>
<tr>
<td align="left"><strong>논리값</strong></td>
<td align="left">true / false</td>
<td align="left">bool (True/False)</td>
<td align="left">boolean</td>
</tr>
<tr>
<td align="left"><strong>빈 값</strong></td>
<td align="left">null</td>
<td align="left">None</td>
<td align="left">null</td>
</tr>
</tbody></table>
<hr>
<h2 id="3-json-구문의-핵심-규칙">3. JSON 구문의 핵심 규칙</h2>
<ol>
<li><strong>반드시 쌍따옴표(<code>&quot;</code>) 사용</strong>: name(key)과 문자열 데이터는 반드시 쌍따옴표로 감싸야 합니다.<ul>
<li>예: {&quot;name&quot;: &quot;John&quot;} (O) / {&#39;name&#39;: &#39;John&#39;} (X)</li>
</ul>
</li>
<li><strong>Trailing Comma 불가</strong>: 배열이나 객체의 마지막 원소 뒤에 콤마(<code>,</code>)를 허용하지 않습니다.</li>
<li><strong>담을 수 있는 것</strong>: str, int, float, list, tuple, dict, None</li>
<li><strong>담을 수 없는 것</strong>: set, function, datetime (별도의 직렬화 과정 필요)</li>
</ol>
<hr>
<h2 id="4-python-json-모듈-사용법">4. Python <code>json</code> 모듈 사용법</h2>
<p>파이썬에서는 <code>import json</code>을 통해 기본적으로 JSON 기능을 제공합니다.</p>
<h3 id="a-jsondumps--python-데이터-→-json-문자열-직렬화">A. json.dumps() : Python 데이터 → JSON 문자열 (직렬화)</h3>
<pre><code class="language-python">    import json

    # 문자열 변환
    print(json.dumps(&#39;hello&#39;)) 
    # 결과: &quot;hello&quot;

    # 딕셔너리 변환
    print(json.dumps({&#39;name&#39;: &#39;John&#39;})) 
    # 결과: {&quot;name&quot;: &quot;John&quot;}

    # 리스트 변환
    print(json.dumps([10, 20, 30])) 
    # 결과: [10, 20, 30]

    # 논리값 및 None 변환
    print(json.dumps([True, False, None])) 
    # 결과: [true, false, null]

### B. json.loads() : JSON 문자열 → Python 데이터 (역직렬화)

    import json

    # JSON 문자열 준비
    json_texts = [
        &quot;[4, 5, 6]&quot;,
        &#39;{&quot;name&quot;:&quot;hong&quot;, &quot;age&quot;:13}&#39;
    ]

    for text in json_texts:
        obj = json.loads(text)
        print(obj, type(obj))

    # 주의사항: 
    # &#39;{&#39;name&#39;:&#39;hong&#39;}&#39; -&gt; key에 홀따옴표 사용 시 에러 발생
    # &#39;[4, 5, 6,]&#39; -&gt; 마지막 콤마 포함 시 에러 발생

### C. 파일 입출력 (json.load / json.dump)

    # 1. 파일 생성 및 쓰기 (준비 과정)
    with open(&#39;data.json&#39;, &#39;w&#39;, encoding=&#39;utf-8&#39;) as f:
        f.write(&#39;&#39;&#39;
        {
          &quot;name&quot;: &quot;홍길동&quot;,
          &quot;birth&quot;: &quot;0525&quot;,
          &quot;age&quot;: 30
        }
        &#39;&#39;&#39;)

    # 2. json.load(file) : JSON 파일 -&gt; 파이썬 데이터
    with open(&#39;data.json&#39;, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f:
        obj = json.load(f)
        print(obj)
        print(f&quot;타입: {type(obj)}&quot;)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[MCP - 7일차(Class)]]></title>
            <link>https://velog.io/@snow-jun-0/MCP-7%EC%9D%BC%EC%B0%A8Class</link>
            <guid>https://velog.io/@snow-jun-0/MCP-7%EC%9D%BC%EC%B0%A8Class</guid>
            <pubDate>Sat, 14 Feb 2026 09:55:38 GMT</pubDate>
            <description><![CDATA[<h1 id="python-파이썬-객체지향-프로그래밍oop-기초-정리">[Python] 파이썬 객체지향 프로그래밍(OOP) 기초 정리</h1>
<h2 id="1-클래스-정의와-인스턴스-생성">1. 클래스 정의와 인스턴스 생성</h2>
<p>클래스는 새로운 타입을 정의하는 &#39;붕어빵 틀&#39;과 같습니다. 이 틀을 통해 만들어진 실체를 &#39;객체&#39; 또는 &#39;인스턴스&#39;라고 부릅니다.</p>
<h3 id="클래스-정의-및-객체-생성">클래스 정의 및 객체 생성</h3>
<pre><code class="language-python">class Cookie:
        pass

    # 인스턴스 생성
    a = Cookie()
    print(type(a))  # &lt;class &#39;__main__.Cookie&#39;&gt;</code></pre>
<hr>
<h2 id="2-객체의-속성과-동작">2. 객체의 속성과 동작</h2>
<ul>
<li><strong>속성(Attribute)</strong>: 객체가 가지는 변수 (가로, 세로, 이름 등)</li>
<li><strong>동작(Method)</strong>: 객체가 수행하는 함수 (넓이 구하기, 걷기 등)</li>
</ul>
<h3 id="객체변수instance-variable">객체변수(instance variable)</h3>
<p><strong>객체변수</strong>앞에서 말한 <strong>속성값</strong>과 같은 뜻입니다. 속성값이라고 불리고, <strong>멤버 변수</strong> 혹은 <strong>필드</strong>라고 불립닏다. </p>
<h3 id="생성자-constructor-__init__">생성자 (Constructor): <code>__init__</code></h3>
<p>객체가 생성될 때 자동으로 호출되며, 주로 속성을 초기화하는 역할을 합니다.</p>
<h3 id="self의-이해">self의 이해</h3>
<p>메소드의 첫 번째 매개변수는 항상 <code>self</code>여야 합니다. 이는 호출된 &#39;객체 자신&#39;을 가리킵니다.</p>
<pre><code class="language-python">    class Rectangle: #클래스 정의
        def __init__(self, width=1, height=1): #객체가 생성되면 자동 호출
            print(f&quot;Rectangle({width}, {height}) 생성&quot;)
            self.width = width #객체 변수 생성
            self.height = height #객체 변수 생성

        #메소드(함수) 정의 
        def get_area(self):
            return self.width * self.height 

        def set_size(self, w, h):
            self.width = w
            self.height = h

    #인스턴스 생성 및 자동 호출
    r1 = Rectangle(30, 20)

    #매개변수 없이 호출(기본값)
    r2 = Rectangle()


    #메소드 호출 및 결과 출력
    print(r1.get_area())  # 600
    print(r2.get_area())  # 1

    #생성 후 객체 값 수정
    r2.set_size(10, 50)

    #수정 결과 출력
    print(r2.get_area())  # 500
</code></pre>
<hr>
<h2 id="3-클래스-변수-vs-인스턴스-변수">3. 클래스 변수 vs 인스턴스 변수</h2>
<ul>
<li><p><strong>인스턴스 변수</strong>: <code>self.변수명</code>. 각 객체마다 독립적인 값을 가집니다.</p>
</li>
<li><p><strong>클래스 변수</strong>: 클래스 내부에서 선언. 모든 객체가 공유하며 <code>클래스명.변수명</code>으로 접근합니다.</p>
<pre><code class="language-python">  class Account:
      num_accounts = 0  # 클래스 변수 (전체 계좌 수)

      def __init__(self, name):
          self.name = name  # 인스턴스 변수
          Account.num_accounts += 1

</code></pre>
</li>
</ul>
<pre><code>a1 = Account(&quot;철수&quot;) 
# 1. &#39;철수&#39;라는 이름표를 가진 객체 생성
# 2. 공용 게시판(Account.num_accounts)의 숫자가 0에서 1이 됨

a2 = Account(&quot;영희&quot;)
# 1. &#39;영희&#39;라는 이름표를 가진 객체 생성
# 2. 공용 게시판(Account.num_accounts)의 숫자가 1에서 2가 됨</code></pre><pre><code>| 구분 | 인스턴스 변수 (self.name) | 클래스 변수 (Account.num_accounts) |
| :--- | :--- | :--- |
| **소유주** | 개별 객체 (인스턴스) | 클래스 전체 (모든 객체 공용) |
| **생성 시점** | 객체가 생성될 때마다 매번 | 클래스가 정의될 때 딱 한 번 |
| **접근 방법** | 객체명.변수명 | 클래스명.변수명 (권장) |
| **용도** | 객체의 고유한 특징 (이름, 잔액 등) | 모든 객체가 공유하는 정보 (전체 개수, 고정 이율 등) |


---

### 예제
```python
# &#39;매 직원(PartTimer)&#39;에 공통적으로 적용되는 자료
# - 시급
# - 전체 직원수

# 각 직원별 객체 생성시 직원별로 &#39;별칭&#39;과 &#39;근무지&#39; &#39;급여총액&#39; 초기화 (속성)
#   &#39;근무지&#39; 생략시 &#39;113동&#39; 으로 지정
#   직원별로 &#39;급여총액&#39;  0으로 초기화

# 직원의 급여 계산하기(동작)
#    &#39;몇시간 근무&#39;,  &#39;+상여금&#39;  에 따른 직원급여 계산
#   &#39;상여금&#39; 은 지정안하면 0 으로 처리


# 예]
# park = PartTimer(&#39;라이언&#39;)   // park 은 ‘라이언’ 이라는 닉네임의 직원으로 등록

# park 이 4시간 일한 급여 총액은?  → 34400
# park 이 2시간 일한 급여 총액은? → 17200
# park 이 2시간 일한 급여 + 상여급 2000 총액은? → 19200


class PartTimer:
  # 클래스변수
  hour_rate = 10320 # 시급
  total_part_timers = 0 # 전체 직원수

  # 생성자 (nickname, workplace)
  #   인스턴스 변수들 선언 (nickname, workplace, total_wage)
  def __init__(self, nickname, workplace = &quot;113동&quot;):
    PartTimer.total_part_timers += 1
    self.nickname = nickname
    self.workplace = workplace
    self.total_wage = 0

  # 급여계산
  def calculate_wage(self, hours, bonus=0):
    self.total_wage = PartTimer.hour_rate * hours + bonus
    return self.total_wage

#실행하기
park = PartTimer(&#39;라이언&#39;)
lee = PartTimer(&#39;네오&#39;, &#39;127-1동&#39;)


park.total_wage  # 급여총액 0
lee.total_wage # 0


park.calculate_wage(4) # 시급 x 4

lee.calculate_wage(3, 15000) # 시급 x 3 + 보너스 15000


PartTimer.total_part_timers # 2 명
</code></pre><h2 id="4-상속-inheritance">4. 상속 (Inheritance)</h2>
<ul>
<li><p>기존 클래스(부모)의 기능을 그대로 물려받아 새로운 클래스(자식)를 만드는 것입니다.
코드 재사용성이 높아집니다.</p>
</li>
<li><p>기존의 만들어진 클래스를 상속받아 새로운 클래스 정의 가능합니다. </p>
</li>
<li><p>상속받아 만들어진 클래스는 <strong>기존의 클래스의 메소드, 객체변수</strong> 를 그대로 가지고 있다.</p>
</li>
<li><p>상속받은뒤, <strong>새로운</strong> 객체변수, 메소드 <strong>추가</strong> 할수 있다.</p>
</li>
<li><p>상속받은뒤, <strong>상속받은 메소드 재정의</strong> 가능 <strong>(오버라이딩)</strong></p>
</li>
</ul>
<hr>
<p>기존의 클래스 상속하여 새로운 클래스 정의하는 구문</p>
<pre><code class="language-python">class 새클래스명(기존의 클래스명)
class 새클래스명(기존클래스1, 기존클래스2, ...)  &lt;-- 다중상속 허용</code></pre>
<ul>
<li><p>기존의 클래스를 &#39;부모클래스(parent class)&#39; 라고 하고<br>(혹은 super class,  base class ...)</p>
</li>
<li><p>상속받은 클래스를 &#39;자식클래스(child class) 라고 한다 
(혹은 sub class, derived class ...)</p>
</li>
</ul>
<hr>
<h3 id="상속과-오버라이딩overriding">상속과 오버라이딩(Overriding)</h3>
<p>부모의 메소드를 자식 클래스에서 목적에 맞게 다시 정의하는 것을 말합니다.</p>
<pre><code class="language-python">    class BasicTV:
        def __init__(self):
            self.power = False
            self.channel = 0

        def display_info(self):
            print(f&quot;전원: {self.power}, 채널: {self.channel}&quot;)

    class SmartTV(BasicTV): #자식
        def __init__(self):
            super().__init__()  # 1. 부모의 생성자를 호출하여 power, channel 초기화
            self.ip = &quot;192.168.0.1&quot; # 2. SmartTV만의 고유 속성 추가


        def display_info(self):  # 메소드 오버라이딩(재정의)
            super().display_info() # 4. 부모의 출력 기능을 먼저 실행 (부모 클래스로 이동)
            print(f&quot;IP: {self.ip}&quot;) # 5. 추가된 IP 정보 출력</code></pre>
<hr>
<h2 id="5-클래스-설계-원칙-is-a-vs-has-a">5. 클래스 설계 원칙 (IS-A vs HAS-A)</h2>
<ul>
<li><strong>IS-A (상속)</strong>: &quot;~은 ~이다&quot; 성립 시 (예: 자동차는 탈것이다 -&gt; Car IS-A Vehicle)</li>
<li><strong>HAS-A (포함)</strong>: &quot;~은 ~을 가지고 있다&quot; 성립 시 (예: 자동차는 타이어를 가진다 -&gt; 속성으로 정의)</li>
</ul>
<hr>
<h3 id="예제">예제</h3>
<pre><code class="language-python"># 2차원 원 Circle
#  └─ 3차원 구 (球,Sphere)

#  1. &#39;원&#39; 객체 정의
#  클래스 이름 : Circle
#  생성자 : &#39;반지름(radius)&#39;를 받아서 초기화
#  get_area() : 면적을 계산하여 리턴하는 메소드
#  get_perimeter() : 둘레을 계산하여 리턴하는 메소드

# 2. &#39;구&#39; 객체 정의 &lt;-- Circle 상속받아 정의
#  클래스 이름 : Cube
#  get_area() : 정육면체의 총 면적.   4/3 x pi x r³
#  get_volume() : 정육면체의 부피 계산.  4 x pi x r²



import math

# 2차원 Circle 정의
class Circle:
  def __init__(self, radius = 0):
    self.radius = radius

  def get_area(self):
    return math.pi * self.radius ** 2

  def get_perimeter(self):
    return 2 * math.pi * self.radius


#실행해보기
c1 = Circle(10)

print(c1.get_area())
print(c1.get_perimeter())



# Circle 을 상속받아 구(Sphere) 객체 생성
class Sphere(Circle):
  def get_volume(self):  # 자식 클래스에서 추가되는 메소드
    return (4 / 3) * math.pi * self.radius ** 3

  def get_area(self):  # 자식클래스에서 부모클래스의 메소드를 재정의 &#39;오버라이딩&#39;
    return 4 * math.pi * self.radius ** 2

#실행해보기
s1 = Sphere(10)

print(s1.get_area())
print(s1.get_perimeter())
print(s1.get_volume())
</code></pre>
<hr>
<h1 id="상속에서의-생성자-호출과-super-완벽-가이드">상속에서의 생성자 호출과 super() 완벽 가이드</h1>
<p>상속 관계에서 자식 클래스가 생성자를 정의할 때, 부모의 생성자를 어떻게 처리해야 하는지 단계별로 알아봅니다.</p>
<hr>
<h2 id="1-생성자-상속의-기본-원리">1. 생성자 상속의 기본 원리</h2>
<p>자식 클래스에 <code>__init__</code>이 없으면 파이썬은 자동으로 부모의 <code>__init__</code>을 찾아 실행합니다. 하지만 자식에게 <code>__init__</code>을 만드는 순간, 부모의 것은 덮어씌워져(Overriding) 호출되지 않습니다. 따라서 <strong>명시적 호출</strong>이 필요합니다.</p>
<hr>
<h2 id="2-코드-분석-및-완성">2. 코드 분석 및 완성</h2>
<h3 id="①-부모-생성자-명시적-호출">① 부모 생성자 명시적 호출</h3>
<p>자식 생성자에서 <code>super().__init__()</code>을 호출하여 부모가 가진 <code>speed</code> 속성을 안전하게 물려받습니다.</p>
<pre><code class="language-python">    class Vehicle:
        def __init__(self, speed=0):
            print(f&#39;Vehicle 생성 speed={speed}&#39;)
            self.speed = speed

    class Car(Vehicle):
        def __init__(self, speed=0, oil=0):
            # 부모에게 필요한 speed 값을 전달하며 생성자 호출
            super().__init__(speed) 
            print(f&#39;Car 생성 oil={oil}&#39;)
            self.oil = oil</code></pre>
<h3 id="②-3단계-상속-구조-완성-hybridcar">② 3단계 상속 구조 완성 (HybridCar)</h3>
<p><code>Vehicle</code> → <code>Car</code> → <code>HybridCar</code>로 이어지는 상속 체인을 완성해 봅니다.</p>
<pre><code class="language-python">    class HybridCar(Car):
        def __init__(self, speed=0, oil=0, battery=0):
            # 바로 위 부모인 Car의 생성자를 호출
            # Car는 다시 Vehicle의 생성자를 호출하게 됩니다 (상속 체인)
            super().__init__(speed, oil)
            print(f&#39;HybridCar 생성 battery={battery}&#39;)
            self.battery = battery</code></pre>
<hr>
<h2 id="3-핵심-포인트-정리">3. 핵심 포인트 정리</h2>
<table>
<thead>
<tr>
<th align="left">상황</th>
<th align="left">동작 방식</th>
<th align="left">비유</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><strong>자식에 생성자가 없을 때</strong></td>
<td align="left">부모의 생성자가 자동으로 실행됨</td>
<td align="left">가업을 그대로 이어받음</td>
</tr>
<tr>
<td align="left"><strong>자식에 생성자를 만들 때</strong></td>
<td align="left">부모의 생성자는 무시됨 (직접 불러야 함)</td>
<td align="left">내가 새로운 가업을 시작함 (부모 도움 필요 시 요청)</td>
</tr>
<tr>
<td align="left"><strong>super()의 역할</strong></td>
<td align="left">부모 클래스의 메서드/생성자에 접근</td>
<td align="left">&quot;부모님, 물려주신 기본 세팅은 제가 알아서 할게요&quot;</td>
</tr>
</tbody></table>
<hr>
<h2 id="4-실행-결과-hybridcar-생성-시">4. 실행 결과 (HybridCar 생성 시)</h2>
<pre><code class="language-python">

    h = HybridCar(100, 50, 80)

    # 출력 순서:
    # Vehicle 생성 speed=100 (최상위 부모부터)
    # Car 생성 oil=50
    # HybridCar 생성 battery=80 (마지막에 자기 자신)</code></pre>
<hr>
<p><strong>💡 주의사항</strong>
<code>super().__init__()</code>을 호출하지 않으면, 자식 객체는 부모가 정의한 <code>self.speed</code> 같은 변수를 가지지 못하게 됩니다. 나중에 <code>h.speed</code>를 조회할 때 <code>AttributeError</code>가 발생할 수 있으니 꼭 써주는 것이 원칙입니다!</p>
<p>예시</p>
<pre><code class="language-python">자식이 생성자를 만들지 않은 경우
class Vehicle:
    def __init__(self, speed):
        print(&quot;Vehicle 생성자 실행!&quot;)
        self.speed = speed

class Car(Vehicle):
    pass  # 생성자를 만들지 않음

# Car에는 생성자가 없지만, 부모의 것을 빌려와서 사용함
c1 = Car(100) 
print(c1.speed) # 결과: 100



자식이 생성자를 만든 경우(오버라이딩)
class Vehicle:
    def __init__(self, speed):
        self.speed = speed  # 부모의 소중한 변수 설정

class Car(Vehicle):
    def __init__(self, oil):
        self.oil = oil  # 자식인 나는 내 변수(oil)만 챙김

c1 = Car(50)
print(c1.oil)   # 출력: 50 (잘 됨)
print(c1.speed) # 에러 발생! (AttributeError: &#39;Car&#39; object has no attribute &#39;speed&#39;)</code></pre>
<hr>
<h2 id="6-매직-메소드-magic-method">6. 매직 메소드 (Magic Method)</h2>
<p><code>__</code>로 시작하고 끝나는 특별한 메소드들로, 파이썬 내장 연산자들의 동작을 클래스에 정의할 수 있게 합니다.</p>
<table>
<thead>
<tr>
<th>연산자</th>
<th>메소드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>+</td>
<td><code>__add__</code></td>
<td>덧셈 연산</td>
</tr>
<tr>
<td>==</td>
<td><code>__eq__</code></td>
<td>값 비교</td>
</tr>
<tr>
<td>len()</td>
<td><code>__len__</code></td>
<td>길이 반환</td>
</tr>
<tr>
<td>print()</td>
<td><code>__str__</code></td>
<td>문자열 출력용</td>
</tr>
</tbody></table>
<h3 id="repr-vs-str"><strong>repr</strong> vs <strong>str</strong></h3>
<ul>
<li><p><code>__repr__</code>: 객체 자체의 표현값 (개발/디버깅용)</p>
</li>
<li><p><code>__str__</code>: 사용자가 보기 편한 문자열 (출력용)</p>
<pre><code class="language-python">  class Number:
      def __init__(self, number):
          self.number = number

      def __add__(self, other):
          return Number(self.number + other.number)

      def __repr__(self):
          return str(self.number)

  n1, n2 = Number(10), Number(20)
  print(n1 + n2)  # 30 (__add__에 의해 객체 연산 가능)</code></pre>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>