<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>goodjob79 님의 블로그</title>
    <link>https://goodjop79.tistory.com/</link>
    <description>Step By Step!  왕초보 인공지능 응용시스템 개발자 교육수강 스토리.  오류를 고치며 배운다. (개인학습로그, 응용S/W, AI, Python, C#)</description>
    <language>ko</language>
    <pubDate>Sat, 30 May 2026 15:46:48 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>goodjop79 님의 블로그</managingEditor>
    <image>
      <title>goodjob79 님의 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/8630992/attach/60f793f31f44436289e3ae19481fe67c</url>
      <link>https://goodjop79.tistory.com</link>
    </image>
    <item>
      <title>D+36 [Python] OOP(객체지향프로그래밍), Class 개념과 활용</title>
      <link>https://goodjop79.tistory.com/50</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ㅇ 일&amp;nbsp; 자 :&amp;nbsp; 2026년 5월 29일(목)&lt;/b&gt;&lt;/h4&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;제&amp;nbsp; 목 : OOP(객체지향프로그래밍),&amp;nbsp;Class&amp;nbsp;개념과&amp;nbsp;활용&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 서&amp;nbsp; 론&lt;/b&gt;&lt;/h2&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp; 현대 소프트웨어 개발 환경은 과거에 비해 비교할 수 없을 만큼 복잡해지고, 요구사항은 끊임없이 변화하고 있다. &lt;br&gt;초기 프로그래밍 방식이었던 절차지향 프로그래밍은 프로그램을 단순히 명령어의 순차적인 실행으로 보았기에, 규모가 커질수록 코드를 이해하고, 수정하고, 유지보수하는 것이 기하급수적으로 어려워지는 한계에 봉착했다.&lt;br&gt;&amp;nbsp; 이러한 한계를 극복하고 더 유연하고 재사용 가능한 소프트웨어를 만들기 위해 등장한 것이 바로 객체지향 프로그래밍(OOP)이다.&lt;b&gt; 객체지향프로그래밍(OOP)는 &quot;현실 세계의 사물과 개념&quot;을 프로그램의 독립된 단위인 '객체'로 모델링하여 프로그램을 구성&lt;/b&gt;한다.&lt;br&gt;&amp;nbsp; 신입 개발자가 &lt;b&gt;OOP의 핵심 개념과 구현하는 도구인 Class를 반드시 이해하고 적용&lt;/b&gt;해야 하는 이유는 다음과 같다.&lt;br&gt;&amp;nbsp; 첫째, &lt;b&gt;유지보수성 향상&lt;/b&gt;이다. 프로그램이 거대해질수록 스파게티 코드처럼 엉킨 코드는 수정할 때마다 새로운 버그를 유발한다. OOP는 코드 간의 '의존성'을 줄이고 독립된 '객체' 단위로 관리하여, 변화에 유연하게 대처할 수 있게 한다. &lt;br&gt;&amp;nbsp; 둘째, &lt;b&gt;코드 재사용성&lt;/b&gt;이다. 잘 설계된 Class는 다른 프로젝트나 프로그램의 다른 부분에서 그대로 재사용할 수 있어 개발 속도를 높이고 중복 코드를 줄여준다. &lt;br&gt;&amp;nbsp; 셋째, &lt;b&gt;협업의 용이성&lt;/b&gt;이다. OOP를 기반으로 한 설계는 코드의 의미를 명확하게 전달하며, 각 개발자가 독립된 객체나 모듈을 담당하여 개발할 수 있는 구조를 제공한다.&lt;br&gt;따라서 신입 개발자에게 OOP와 Class는 단순히 지나쳐가는 기술이 아니라, 복잡한 현대 소프트웨어 개발 환경에서 살아남고 성장하기 위해 반드시 갖춰야 할 필수적인 기술적 체력이자 기본기라고 할 수 있다.&amp;nbsp;&lt;/p&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가. 신입개발자가 갖춰야 할 기술적 목표는 무엇인가?&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(1) 신입 개발자의 현실적인 기술 목표&lt;/b&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; 신입개발자는 프로그래밍 이라는 소프트웨어 개발의 각 단계를 이해하고 이를 바탕으로 자신이 만든 Project 라는 소프트웨어 결과를 Portfolio 에 정리해야 한다. 신입 개발자의 참신함은 ‘전체 흐름’을 꿰뚫는 Portfolio 구축에 있다. &quot;class까지는 순차적인 학습이 가능하지만 이후는 내용이 순차적이 아니라 복합적인 교육이 진행된다&quot;. &lt;br&gt;프로그래밍이라는 소프트웨어 개발의 각 단계를 올바르게 이해하고, 그 결과를 Project 기반의 Portfolio로 증명해 내야 한다.&amp;nbsp;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;포함할 영역:&lt;/b&gt; 암호화, 권한 관리, 배포 환경 구축&lt;/li&gt;&lt;li&gt;&lt;b&gt;제외할 영역:&lt;/b&gt; 장애 대응, 대용량 로그 및 모니터링 (현실적으로 신입 단계에서는 어렵다)&lt;/li&gt;&lt;/ul&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 본 론&lt;/b&gt;&lt;/h2&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;가. OOP (객체지향 프로그래밍) 이란 무엇인가?&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(1) 의 미&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;OOP&lt;b&gt;(Object-Oriented Programming,&lt;/b&gt;&lt;b&gt; 객체 지향 프로그래밍)&lt;/b&gt;는 프로그램을 단순히 명령어의 순차적인 나열로 보는 것이 아니라, 데이터와 기능을 가진 독립된 단위인 '객체(Object)'들의 집합과 상호작용으로 파악하는 프로그래밍 패러다임이다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(2) 등장 배경&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;초기 컴퓨터 프로그래밍은 하드웨어를 직접 제어하는 기계어와 어셈블리어를 거쳐, 인간의 언어와 유사한 고급 언어(C 등)를 사용하는 절차지향 프로그래밍으로 발전 했다. 절차지향은 문제를 잘게 쪼개어 순서대로 해결하는 방식에 탁월하여 초기 소프트웨어 개발을 주도했다. 하지만 하드웨어 성능의 발전과 함께 소프트웨어의 규모와 복잡도가 상상 이상으로 커지면서 문제가 발생했다.&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;스파게티 코드:&lt;/b&gt; 프로그램의 각 부분이 서로 밀접하게 연결되어(높은 결합도) 코드 한 줄을 수정하면 프로그램의 전혀 다른 부분에서 예측할 수 없는 오류가 발생했다.&lt;/li&gt;&lt;li&gt;&lt;b&gt;유지보수의 어려움:&lt;/b&gt; 코드를 이해하고 수정하는 데 드는 비용이 새로운 프로그램을 만드는 비용을 넘어서는 '소프트웨어 위기'가 발생했다.&lt;/li&gt;&lt;li&gt;&lt;b&gt;코드 재사용의 한계:&lt;/b&gt; 비슷한 기능을 하는 코드를 다른 프로그램에서 다시 사용하기가 매우 어려워, 매번 새로운 코드를 작성해야 했다.&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제를 해결하기 위해, 현실 세계의 '객체(Object)'라는 개념에 주목하게 되었다. &lt;br&gt;현실 세계의 사물(예: 자동차)은 고유한 데이터(색상, 속도)와 기능(달리기, 멈추기)을 가지고 있으며, 다른 사물과 상호작용 한다.&lt;br&gt;프로그램 또한 이처럼 독립된 데이터와 기능을 가진 '객체'들의 집합으로 구성하고, 이 객체들이 서로 메시지를 주고받으며(함수 호출) 작동하게 함으로써, 코드 간의 연결 고리를 끊고(낮은 결합도) 각 객체의 독립성을 높여(높은 응집도) 복잡도를 관리하고 재사용성을 높이고자 탄생한 것이 바로 객체지향 프로그래밍 이다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(3) 객체지향 이후의 학습은 '순환선'&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;신입 개발자의 현실적인 기술 목표에서 언급했듯, 기초 문법부터 Class 기초까지는 순차적으로 학습할 수 있다.&amp;nbsp; &amp;nbsp; 하지만 OOP의 실제 활용과 심화 학습은 단선적인 도로가 아니라 복합적인 개념들이 서로 얽혀있는 '순환선'과도 같다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kMxxG/dJMcaciVtT9/g8M75RJp4QvXzlRQdLGE70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kMxxG/dJMcaciVtT9/g8M75RJp4QvXzlRQdLGE70/img.png&quot; data-alt=&quot;단계별 순차적 학습 구간 : 디자인패턴 - 추상화 - 인터페이스 - 솔리드(객체지향)원칙 - 이벤트대리인) - 디자인패턴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kMxxG/dJMcaciVtT9/g8M75RJp4QvXzlRQdLGE70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkMxxG%2FdJMcaciVtT9%2Fg8M75RJp4QvXzlRQdLGE70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1408&quot; height=&quot;768&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;단계별 순차적 학습 구간 : 디자인패턴 - 추상화 - 인터페이스 - 솔리드(객체지향)원칙 - 이벤트대리인) - 디자인패턴&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(4) 핵심 개념 3가지&lt;/b&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;&lt;b&gt;클래스(Class):&lt;/b&gt; 객체를 만들기 위한 설계도 또는 틀&lt;/li&gt;&lt;li&gt;&lt;b&gt;객체(Object):&lt;/b&gt; 설계도를 바탕으로 메모리에 구현된 실체&lt;/li&gt;&lt;li&gt;&lt;b&gt;메서드(Method):&lt;/b&gt; 객체가 수행할 수 있는 행동이나 기능(함수)&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k98qx/dJMcagMubAp/adU8Ti1yI5zrJT2HbtYznK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k98qx/dJMcagMubAp/adU8Ti1yI5zrJT2HbtYznK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k98qx/dJMcagMubAp/adU8Ti1yI5zrJT2HbtYznK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk98qx%2FdJMcagMubAp%2FadU8Ti1yI5zrJT2HbtYznK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1408&quot; height=&quot;768&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;(5) OOP의 4대 특징&lt;/b&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;30&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;30,0,0&quot;&gt;캡슐화 (Encapsulation)&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;30,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;데이터와 데이터를 처리하는 함수를 하나로 묶는다&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;span&gt;외부에서 객체 내부 정보에 직접 접근하지 못하도록 숨겨 데이터를 보호(정보 은닉)&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;30,1,0&quot;&gt;상속 (Inheritance)&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;30,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;자식 클래스가 부모 클래스의 속성과 기능을 그대로 물려받는다&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;span&gt;이미 만든 코드를 재사용하여 중복 코드를 줄이고 확장성을 높인다.&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;30,2,0&quot;&gt;다형성 (Polymorphism)&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;30,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;하나의 역할이나 메서드가 상황에 따라 다양한 방식으로 동작하는 성질&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;span&gt;하위 클래스에서 메서드를 재정의하는 오버라이딩(Overriding)이 대표적인 예시&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;30,3,0&quot;&gt;추상화 (Abstraction)&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;30,3,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;복잡한 현실 세계의 사물에서 필요한 공통 속성과 핵심 기능만 추출하여 모델링하는 과정&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;span&gt;불필요한 세부 사항은 숨기고 중요한 개념에 집중할 수 있게 한다.&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
&lt;/ul&gt;&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;나. Class 예시를 통한 개념 이해&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;유아교육을 위한 동물 사운드 및 분류 앱의 시각화 설계도입니다. 객체 지향 프로그래밍(OOP)의 &lt;b&gt;상속(Inheritance)&lt;/b&gt; 개념을 깊이 있게 적용하여, &lt;b&gt;동물&lt;/b&gt;이라는 공통 설계도를 바탕으로 &lt;b&gt;조류, 포유류, 어류&lt;/b&gt;라는 중간 분류를 만들고, 최종적으로 &lt;b&gt;독수리, 호랑이, 상어&lt;/b&gt;라는 구체적인 객체를 효율적으로 구현한다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(1) 동물 사운드 앱 : 깊은 상속 다이어그램&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;이 다이어그램은 부모 클래스인 '동물'에서 시작하여, 각 동물의 생물학적 분류를 '자식 클래스'로 정의하고, 최종적으로 구체적인 동물 종류를 '손자 클래스'로 정의하는 3단계 계층 구조를 보여준다. 이를 통해 공통 속성과 기능을 최상위 클래스에서 정의하고 하위 클래스에서 이를 확장 및 재사용하는 구조를 시각화 한다.&lt;br&gt;&lt;i&gt;※ '동물 - 조류 - 포유류 - 어류'는 계층 구조상 모호한 표현이 있어, 표준적인 '조류, 포유류, 어류' 계층 구조로 정리하였음.&lt;/i&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3BOy1/dJMcadvkVu5/8J8bkzVW2ExSk5edYHvN81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3BOy1/dJMcadvkVu5/8J8bkzVW2ExSk5edYHvN81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3BOy1/dJMcadvkVu5/8J8bkzVW2ExSk5edYHvN81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3BOy1%2FdJMcadvkVu5%2F8J8bkzVW2ExSk5edYHvN81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1408&quot; height=&quot;768&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;(2) 구조 설계 상세 설명&lt;/b&gt;&lt;/p&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,0&quot;&gt;최상위 부모 클래스: 동물 (Animal)&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,0,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;모든 동물들이 공통으로 가지는 기본 틀&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,1,1,0&quot;&gt;속성(Attributes) :&lt;/b&gt;&lt;span&gt; 이름(name)&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,0,1,2,0&quot;&gt;기능(Methods) :&lt;/b&gt;&lt;span&gt; 소리를 재생하는 버튼 동작(playSound)&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,1,0&quot;&gt;중간 자식 클래스 (분류) : 조류, 포유류, 어류&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,1,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;부모 클래스(Animal)를 상속받아 생성되며,&lt;/span&gt;&lt;span&gt; 각 분류의 공통 속성이나 기능을 추가할 수 있다.&lt;/span&gt;&lt;span&gt; 여기선 예시를 위해 직접 상속을 보여 준다.&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,0&quot;&gt;최하위 자식 클래스 (손자): 구체적인 동물 종류&lt;/b&gt; 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;&lt;span&gt;해당하는 중간 분류 클래스를 상속받아,&lt;/span&gt;&lt;span&gt; 각 동물에 맞는 고유한 소리(sound)만 따로 설정&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,1,1,0&quot;&gt;독수리 (Eagle):&lt;/b&gt;&lt;span&gt; sound = &quot;끼에엑&quot;&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,1,2,0&quot;&gt;호랑이 (Tiger):&lt;/b&gt;&lt;span&gt; sound = &quot;어흥&quot;&lt;/span&gt;&lt;/li&gt; 
   &lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;9,2,1,3,0&quot;&gt;상어 (Shark):&lt;/b&gt;&lt;span&gt; sound = &quot;(무소음)&quot;&lt;/span&gt;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
&lt;/ul&gt;&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;(3) 파이썬 코드 구현 예시&lt;/b&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;이 구조를 활용해 실제 웹이나 앱에서 버튼을 누를 때 소리가 나도록 파이썬으로 프로그래밍 한다.&amp;nbsp;&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 1. 최상위 부모 클래스 정의
class Animal:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self, name):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.name = name

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def play_sound(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# 자식 클래스에서 sound 속성을 정의해야 함을 명시 (강제성 부여)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise NotImplementedError(&quot;Subclass must implement abstract attribute 'sound'&quot;)


# 2. 중간 자식 클래스 정의 (분류)
class Aves(Animal): # 조류
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self, name):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(name)

class Mammalia(Animal): # 포유류
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self, name):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(name)

class Pisces(Animal): # 어류
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self, name):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(name)


# 3. 최하위 자식 클래스 정의 (손자, 구체적인 동물)
class Eagle(Aves): # 독수리는 조류
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(&quot;독수리&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.sound = &quot;끼에엑&quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def play_sound(self): # 오버라이딩: 각자 고유한 소리 출력
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;{self.name}이(가) 하늘에서 '{self.sound}'! 소리를 냅니다.&quot;)

class Tiger(Mammalia): # 호랑이는 포유류
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(&quot;호랑이&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.sound = &quot;어흥&quot;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def play_sound(self): # 오버라이딩
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;{self.name}이(가) 숲속에서 '{self.sound}'! 소리를 냅니다.&quot;)

class Shark(Pisces): # 상어는 어류
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(&quot;상어&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.sound = &quot;(무소음)&quot; # 상어는 소리를 내지 않음

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def play_sound(self): # 오버라이딩: 소리가 없는 경우에 대한 구현
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;{self.name}이(가) 바다 속에서 {self.sound}으로 헤엄칩니다.&quot;)


# 4. 객체 생성 및 실행 (버튼 클릭 시 동작 시뮬레이션)

# 예시: 각 분류별로 손자 객체 생성
eagle_button = Eagle()
tiger_button = Tiger()
shark_button = Shark()

# 예시: 독수리 버튼 클릭
eagle_button.play_sound() 
# 출력: 독수리이(가) 하늘에서 '끼에엑'! 소리를 냅니다.

# 예시: 호랑이 버튼 클릭
tiger_button.play_sound()
# 출력: 호랑이이(가) 숲속에서 '어흥'! 소리를 냅니다.

# 예시: 상어 버튼 클릭 (소리 대신 메시지)
shark_button.play_sound()
# 출력: 상어이(가) 바다 속에서 (무소음)으로 헤엄칩니다.&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;이처럼 계층적인 설계를 하면, 새로운 동물(예: 참새)이 추가되더라도 기존의 조류(Aves) 클래스를 상속받아 이름과 소리만 정의해주면 매우 쉽게 기능을 확장할 수 있다. 상위 클래스(Animal, Aves 등)의 코드를 건드릴 필요가 없어 안정적이다.&lt;/b&gt;&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;color: #1B711D;&quot;&gt;다. 프로그램 작성시 우리는 왜&amp;nbsp; 파일(&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #1B711D;&quot;&gt;.py)을&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #1B711D;&quot;&gt;분리 해야 하는가?&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; 위젯의 통합 코드를 여러 파일(main.py,&amp;nbsp; Widget.py,&amp;nbsp; from_tab.py,&amp;nbsp; buttons_tab.py 등)로 분리하여 사용하는 가장 큰 이유는&amp;nbsp;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;u&gt;유지보수의 편의성과 코드의 재사용성 때문&lt;/u&gt;&lt;/b&gt;이다. 코드&lt;/span&gt;가 한 파일에 모두 모여 있으면 초기 개발은 빠를 수 있지만, 프로그램이 커질수록 &quot;수정&quot;과 &quot;관리&quot;가 불가능해 진다. 그러므로 분야별 분담과 유지보수 편의성을 위해 class부분을 분리하여 관리한다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;(1) 파일별 역할 분담 구조 (예시)&lt;/b&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- main.py : 프로그램의 시작점. 전체 애플리케이션을 실행하고 메인 윈도우를 띄우는 진입로 역할&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- Widget.py : 메인 화면의 큰 틀이나 공통 레이아웃을 정의하고 조각 파일들을 하나로 조립하는 본체 역할&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- form_tab.py : 입력창, 콤보박스 등 데이터 입력과 관련된 UI와 로직만 집중적으로 관리&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- buttons_tab.py: 버튼의 배치와 버튼을 눌렀을 때 실행될 기능(이벤트)만 따로 모아 관리&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;(2) 소스코드를 분리하는 핵심 이유&lt;/b&gt;&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;- 가독성 향상 : 한 파일이 수천 줄이 되는 것을 방지하여 코드를 쉽게 읽을 수 있다.&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - 유지보수 용이 :&lt;span style=&quot;color: #8A3DB6;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;color: #1B711D;&quot;&gt;버튼 기능을 수정할 때 buttons_tab.py만 열어서 고치면 되므로&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&amp;nbsp;다른 코드를 건드릴 위험이 줄어든다.&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - 코드 재사용 &lt;span style=&quot;color: #1B711D;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;u&gt;&lt;span style=&quot;color: #1B711D;&quot;&gt;form_tab.py에서 만든 입력 양식을 다른 화면이나 다른 프로젝트에서 그대로 가져다 쓸 수&lt;/span&gt;&lt;/u&gt;&lt;span style=&quot;color: #8A3DB6;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;있다.&lt;br&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; - 협업 수월 : 여러 개발자가 동시에 작업할 때, 파일이 분리되어 있으면&amp;nbsp;&lt;u&gt;깃(Git) 충돌&lt;/u&gt;&amp;nbsp;없이 각자 맡은 화면을 개발할 수 있다.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;※ 예시 : main.py 설명&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;&amp;nbsp;from PyQt6.QtWidgets import QWidget&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp;# 또는 PySide6.QtWidgets&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;&amp;nbsp; &amp;nbsp;class Widget(QWidget)&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&amp;nbsp; &amp;nbsp;# QWidget(기본 위젯 클래스)을 상속받아 새로운 위젯 클래스를 정의함&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;&amp;nbsp;&amp;nbsp;def __init__(self, parent=None)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;:&amp;nbsp;&amp;nbsp;# 클래스가 생성될 때 자동으로 실행되는 초기화 메서드(생성자)&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #006DD7;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(parent) :&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;# 부모 클래스(QWidget)의 생성자를 호출해 위젯을 초기화, 부모-자식 관계 설정&lt;/span&gt;&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 결&amp;nbsp; 론&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;결국 객체지향 프로그래밍(OOP)은 현대 소프트웨어 개발에서 복잡성을 관리하고 변화에 유연하게 대응하기 위한 가장 강력한 무기이다. 그리고 이러한 OOP의 철학을 실제 코드로 구현해 내는 핵심 도구가 바로 클래스(Class) 이다.&lt;br&gt;클래스는 &lt;b&gt;복잡한 현실 세계의 개념을 추상화하여 안전하게 묶어두는 설계&lt;/b&gt;도 역할을 한다.&amp;nbsp; 개발자는 잘 설계된 클래스를 바탕으로 코드의 중복을 획기적으로&lt;span style=&quot;color: #006DD7;&quot;&gt; 줄이고(상속)&lt;/span&gt;, 내부 데이터를 안전하게 &lt;span style=&quot;color: #006DD7;&quot;&gt;보호하며(캡슐화&lt;/span&gt;), 상황에 따라 &lt;span style=&quot;color: #006DD7;&quot;&gt;유연하게 대처하는 코드(다형성&lt;/span&gt;)를 작성할 수 있다.&lt;br&gt;신입 개발자에게 클래스를 올바르게 이해하고 적용하는 것은 단순한 문법 습득을 넘어, 거대하고 복잡한 소프트웨어 생태계로 진입하기 위한 첫 단추다. 클래스라는 기본 설계도를 탄탄히 다질 때, 비로소 고도화된 디자인 패턴이나 아키텍처라는 넓은 구조를 이해하고 다룰 수 있는 진정한 기술적 성장을 이룰 수 있을 것이다. &quot;도전은 계속된다&quot;.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;※ 기타 참고&lt;/span&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;스파게티 코드&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ㅇ 1970년대 후반~1980년대 컴퓨터 학계의 공식 등장&lt;/b&gt; : &lt;b&gt;&amp;nbsp;'스파게티'라는 비유가 문헌에 등장하기 시작한 것은 1970년대 후반&lt;/b&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 1978년 Guy Steele이 저술한 맥카시(McCarthy)의 LISP 역사 관련 논문 등에서 프로그램 구조가 엉킨 모습을 '스파게티'에 비유하기 시작했다.&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 이후&amp;nbsp;1980년대 후반, ISO(국제표준화기구)의 워킹 그룹 문서&amp;nbsp;등에서&lt;b&gt; &quot;구조화되지 않고 제어 흐름이 복잡하게 뒤틀린 소스 코드&quot;&lt;/b&gt;를 공식적으로 'Spaghetti Code'라고 명명하면서 업계 표준 용어로 자리 잡았다.&lt;/span&gt;&lt;br&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ㅇ 1990년대 '안티패턴(Anti-Pattern)'으로 정의&lt;/span&gt;&lt;/b&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1998년 출간된 소프트웨어 공학의 명저 《안티패턴(AntiPatterns)》 책에서 소프트웨어 개발 시 절대 하지 말아야 할 대표적인 실패 사례(디자인 안티패턴) 중 하나로 '스파게티 코드'를 공식 등록하면서 오늘날까지 널리 쓰이게 되었다.&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 요약하자면&amp;nbsp;스파게티 코드는 &quot;코드가 얽히고설켜 유지보수가 불가능한 상태&quot;를 뜻하며, 그 근거와 어원은 1960~70년대 무분별한 GOTO문 사용으로 코드가 뒤엉키는 현상을&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소프트웨어 공학자들이 스파게티 면발에 비유하여 비판한 데서 유래했다.&amp;nbsp; &amp;nbsp; 이를 방지하기 위해 탄생한 대표적인 패러다임이 바로 '객체지향 프로그래밍(OOP)'과 '클래스(Class) 기반 설계' 이다.&amp;nbsp; 끝.&lt;/span&gt;&lt;/p&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>인공지능 AI</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/50</guid>
      <comments>https://goodjop79.tistory.com/50#entry50comment</comments>
      <pubDate>Fri, 29 May 2026 00:28:26 +0900</pubDate>
    </item>
    <item>
      <title>D+36 [Layout] .py 파일분리 왜 할까 ? 레이아웃 종합 예제 학습(2)</title>
      <link>https://goodjop79.tistory.com/49</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ㅇ 일 자 : 2026년 5월 28일(목)&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ㅇ&amp;nbsp;내용&amp;nbsp;:&amp;nbsp;Layout&amp;nbsp;가상환경에서&amp;nbsp;종합&amp;nbsp;예제&amp;nbsp;학습&amp;nbsp;하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;1. QtabWidget을 통해 파일분리를 실습하였다. 왜 .py 파일분리를 해야 하는가?&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위젯의 통합 코드를 여러 파일(main.py,&amp;nbsp; Widget.py,&amp;nbsp; from_tab.py,&amp;nbsp; buttons_tab.py 등)로 분리하여 사용하는 가장 큰 이유는&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;&lt;b&gt;유지보수의 편의성과 코드의 재사용성 때문&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이다. 코드가 한 파일에 모두 모여 있으면 초기 개발은 빠를 수 있지만, 프로그램이 커질수록 &quot;수정&quot;과 &quot;관리&quot;가 불가능해 진다. 그러므로 분야별 분담과 유지보수 편의성을 위해 class부분을 분리하여 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.1. 파일별 역할 분담 구조&lt;/b&gt;&lt;br /&gt;- main.py : 프로그램의 시작점. 전체 애플리케이션을 실행하고 메인 윈도우를 띄우는 진입로 역할&lt;br /&gt;- Widget.py : 메인 화면의 큰 틀이나 공통 레이아웃을 정의하고 조각 파일들을 하나로 조립하는 본체 역할&lt;br /&gt;- form_tab.py : 입력창, 콤보박스 등 데이터 입력과 관련된 UI와 로직만 집중적으로 관리&lt;br /&gt;- buttons_tab.py: 버튼의 배치와 버튼을 눌렀을 때 실행될 기능(이벤트)만 따로 모아 관리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.2. 소스코드를 분리하는 핵심 이유&lt;/b&gt;&lt;br /&gt;- 가독성 향상 : 한 파일이 수천 줄이 되는 것을 방지하여 코드를 쉽게 읽을 수 있다.&lt;br /&gt;- 유지보수 용이 :&lt;span style=&quot;color: #8a3db6;&quot;&gt; &lt;b&gt;&lt;u&gt;버튼 기능을 수정할 때 buttons_tab.py만 열어서 고치면 되므로&lt;/u&gt;&lt;/b&gt;&lt;/span&gt; 다른 코드를 건드릴 위험이 줄어든다.&lt;br /&gt;- 코드 재사용 : &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;u&gt;form_tab.py에서 만든 입력 양식을 다른 화면이나 다른 프로젝트에서 그대로 가져다 쓸 수&lt;/u&gt; &lt;/b&gt;&lt;/span&gt;있다.&lt;br /&gt;- 협업 수월 : 여러 개발자가 동시에 작업할 때, 파일이 분리되어 있으면 &lt;u&gt;깃(Git) 충돌&lt;/u&gt; 없이 각자 맡은 화면을 개발할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;※ 예시 : main.py 설명&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;from PyQt6.QtWidgets import QWidget&lt;/span&gt;&amp;nbsp; &amp;nbsp;# 또는 PySide6.QtWidgets&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp; &amp;nbsp;class Widget(QWidget) &lt;/span&gt;:&amp;nbsp; &amp;nbsp;# QWidget(기본 위젯 클래스)을 상속받아 새로운 위젯 클래스를 정의함&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt; &amp;nbsp;def __init__(self, parent=None)&lt;/span&gt; :&amp;nbsp;&amp;nbsp;# 클래스가 생성될 때 자동으로 실행되는 초기화 메서드(생성자)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(parent) :&lt;/span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt; # 부모 클래스(QWidget)의 생성자를 호출해 위젯을 초기화, 부모-자식 관계 설정&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Layout (QTabWidget) 예시 문제 실습&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1)&amp;nbsp; 간단한 계산기 만들기 (계산기 화면 결과값 오른쪽 정렬)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;계산기 수정전.png&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCLacb/dJMcageBOI3/vmY5vIfmCxDrbkpjC4tkeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCLacb/dJMcageBOI3/vmY5vIfmCxDrbkpjC4tkeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCLacb/dJMcageBOI3/vmY5vIfmCxDrbkpjC4tkeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCLacb%2FdJMcageBOI3%2FvmY5vIfmCxDrbkpjC4tkeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;809&quot; height=&quot;868&quot; data-filename=&quot;계산기 수정전.png&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779966681205&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys
from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QGridLayout
from PySide6.QtCore import Qt


class CalculatorWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle(&quot;계산기&quot;)
        self.setMinimumSize(336, 541)

        # [1] 그리드 레이아웃 생성
        layout = QGridLayout(self)  # 위젯을 행과 열을 기준으로 배치하는 레이아웃이다.
        layout.setSpacing(4)
        layout.setContentsMargins(4, 4, 4, 4)

        # [2] 결과 라벨
    ## 계산 결과를 표시하는 리절트 라벨
        self.result_label = QLabel(&quot;0&quot;)
    ## 계산기 화면 결과값 오른쪽 정렬 한다.(AlignRight, AlignVCenter)
        self.result_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.result_label.setStyleSheet(&quot;font-size: 36px; padding: 8px;&quot;)
        layout.addWidget(self.result_label, 0, 0, 1, 4)

        # [3] 1줄: %, CE, C, ⌫
    ## 열은 0열 부터 3열까지 총 4개를 사용한다.
        btn_percent = QPushButton(&quot;%&quot;)
        btn_ce = QPushButton(&quot;CE&quot;)
        btn_c = QPushButton(&quot;C&quot;)
        btn_del = QPushButton(&quot;⌫&quot;)

        for b in (btn_percent, btn_ce, btn_c, btn_del):
            b.setMinimumHeight(50)
    ## 반복 코드 (버튼을 하나씩 변수로 만들고 하나씩 배치함, 계속 반복해서 코드가 길어진 단점)
        layout.addWidget(btn_percent, 1, 0)
        layout.addWidget(btn_ce, 1, 1)
        layout.addWidget(btn_c, 1, 2)
        layout.addWidget(btn_del, 1, 3)

    ## 결과 라벨이 0행을 차지하므로 버튼 배치는 1행부터 배치한다.
        # [4] 2줄: 1/x, x&amp;sup2;, &amp;radic;x, &amp;divide;
        btn_inv = QPushButton(&quot;1/x&quot;)
        btn_sq = QPushButton(&quot;x&amp;sup2;&quot;)
        btn_sqrt = QPushButton(&quot;&amp;radic;x&quot;)
        btn_div = QPushButton(&quot;&amp;divide;&quot;)

        for b in (btn_inv, btn_sq, btn_sqrt, btn_div):
            b.setMinimumHeight(50)

        layout.addWidget(btn_inv, 2, 0)
        layout.addWidget(btn_sq, 2, 1)
        layout.addWidget(btn_sqrt, 2, 2)
        layout.addWidget(btn_div, 2, 3)

        # [5] 3줄: 7 8 9 &amp;times;
        btn_7 = QPushButton(&quot;7&quot;)
        btn_8 = QPushButton(&quot;8&quot;)
        btn_9 = QPushButton(&quot;9&quot;)
        btn_mul = QPushButton(&quot;&amp;times;&quot;)

        for b in (btn_7, btn_8, btn_9, btn_mul):
            b.setMinimumHeight(50)

        layout.addWidget(btn_7, 3, 0)
        layout.addWidget(btn_8, 3, 1)
        layout.addWidget(btn_9, 3, 2)
        layout.addWidget(btn_mul, 3, 3)

        # [6] 4줄: 4 5 6 &amp;minus;
        btn_4 = QPushButton(&quot;4&quot;)
        btn_5 = QPushButton(&quot;5&quot;)
        btn_6 = QPushButton(&quot;6&quot;)
        btn_sub = QPushButton(&quot;&amp;minus;&quot;)

        for b in (btn_4, btn_5, btn_6, btn_sub):
            b.setMinimumHeight(50)

        layout.addWidget(btn_4, 4, 0)
        layout.addWidget(btn_5, 4, 1)
        layout.addWidget(btn_6, 4, 2)
        layout.addWidget(btn_sub, 4, 3)

        # [7] 5줄: 1 2 3 +
        btn_1 = QPushButton(&quot;1&quot;)
        btn_2 = QPushButton(&quot;2&quot;)
        btn_3 = QPushButton(&quot;3&quot;)
        btn_add = QPushButton(&quot;+&quot;)

        for b in (btn_1, btn_2, btn_3, btn_add):
            b.setMinimumHeight(50)

        layout.addWidget(btn_1, 5, 0)
        layout.addWidget(btn_2, 5, 1)
        layout.addWidget(btn_3, 5, 2)
        layout.addWidget(btn_add, 5, 3)

        # [8] 6줄: +/- 0 . =
        btn_neg = QPushButton(&quot;+/-&quot;)
        btn_0 = QPushButton(&quot;0&quot;)
        btn_point = QPushButton(&quot;.&quot;)
        btn_eq = QPushButton(&quot;=&quot;)

        for b in (btn_neg, btn_0, btn_point, btn_eq):
            b.setMinimumHeight(50)

        layout.addWidget(btn_neg, 6, 0)
        layout.addWidget(btn_0, 6, 1)
        layout.addWidget(btn_point, 6, 2)
        layout.addWidget(btn_eq, 6, 3)

        # [9] 행 비율 설정
        layout.setRowStretch(0, 1)
        layout.setRowStretch(1, 2)
        layout.setRowStretch(2, 2)
        layout.setRowStretch(3, 2)
        layout.setRowStretch(4, 2)
        layout.setRowStretch(5, 2)
        layout.setRowStretch(6, 2)


if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = CalculatorWindow()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1-1) &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 계산기 수정된 사항 : 앞에서 길게 반복해서 사용하던 코드를 간결하게 사용하였음을 확인함&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;-&amp;nbsp; 계산기 만들기 코드 : 개선된 코드는 클린해진다. 클레스 상속을 여러번 받아서 사용하던 것을 2차원 리스트로 하여 코드가 간결하게 작성된다.&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;수정된주석 계산기.png&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;993&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVRRnh/dJMcabdfqtI/2E7H4E1DzAoolvEKkdfMN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVRRnh/dJMcabdfqtI/2E7H4E1DzAoolvEKkdfMN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVRRnh/dJMcabdfqtI/2E7H4E1DzAoolvEKkdfMN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVRRnh%2FdJMcabdfqtI%2F2E7H4E1DzAoolvEKkdfMN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1082&quot; height=&quot;993&quot; data-filename=&quot;수정된주석 계산기.png&quot; data-origin-width=&quot;1082&quot; data-origin-height=&quot;993&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1-2)&amp;nbsp; 계산기 레이아웃 버튼 설명 (주석)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;계산기 버튼 설명.png&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;955&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A2HGD/dJMcaayIs65/NjztuUIMD6eNXYdgrNYN70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A2HGD/dJMcaayIs65/NjztuUIMD6eNXYdgrNYN70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A2HGD/dJMcaayIs65/NjztuUIMD6eNXYdgrNYN70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA2HGD%2FdJMcaayIs65%2FNjztuUIMD6eNXYdgrNYN70%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1089&quot; height=&quot;955&quot; data-filename=&quot;계산기 버튼 설명.png&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;955&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1779967113373&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class CalculatorLayoutDemo(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle(&quot;계산기 레이아웃 데모&quot;)
        self.setMinimumSize(336, 541)

        # [1] QGridLayout 생성
        layout = QGridLayout(self)
        layout.setSpacing(4)
        layout.setContentsMargins(4, 4, 4, 4)

        # [2] 결과 표시 라벨
        self.result_label = QLabel(&quot;0&quot;)
        self.result_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        # self.result_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.result_label.setStyleSheet(&quot;font-size: 36px; padding: 8px;&quot;)
        layout.addWidget(self.result_label, 0, 0, 1, 4)

### 개선된 코드는 클린하다. 클래스 상속을 여러번 받아서 사용하던 것을 버튼 2차원 리스트로 하여 코드가 간결해진다.
        # [3] 계산기 버튼 텍스트를 2차원 리스트로 정의
        buttons = [
            [&quot;%&quot;, &quot;CE&quot;, &quot;C&quot;, &quot;⌫&quot;],
            [&quot;1/x&quot;, &quot;x&amp;sup2;&quot;, &quot;&amp;radic;x&quot;, &quot;&amp;divide;&quot;],
            [&quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;&amp;times;&quot;],
            [&quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;&amp;minus;&quot;],
            [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;+&quot;],
            [&quot;+/-&quot;, &quot;0&quot;, &quot;.&quot;, &quot;=&quot;],
        ]

        # [4] 버튼 생성 및 그리드에 배치
        row_offset = 1
### 버튼 반복문 안에서 만들때 개별 변수명을 안만들고 대신 딕셔너리에 저장해서 나중에 특정 버튼을 찾는다
        self.button_map = {}

        for row_index, row in enumerate(buttons):
            for col_index, text in enumerate(row):
                btn = QPushButton(text)
                btn.setMinimumHeight(50)
#### 인덱스 번호도 함께 얻는다 (row_index는 버튼 줄번호), (col_index는 열 번호)
                grid_row = row_offset + row_index
                grid_col = col_index
                layout.addWidget(btn, grid_row, grid_col)

                self.button_map[text] = btn

        # [5] 특정 버튼에 스타일 지정
        if &quot;=&quot; in self.button_map:
            self.button_map[&quot;=&quot;].setStyleSheet(&quot;font-weight: bold; font-size: 18px;&quot;)

        # [6] 행 스트레치 설정
        layout.setRowStretch(0, 1)
        for r in range(1, 7):
            layout.setRowStretch(r, 2)


if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = CalculatorLayoutDemo()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1-3) 계산기 덧셈만 가능한 레이아웃&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;덧셈만계산기.png&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;955&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnxkas/dJMcajbengz/T2lo99Q6k0tk8NU3gLQKO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnxkas/dJMcajbengz/T2lo99Q6k0tk8NU3gLQKO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnxkas/dJMcajbengz/T2lo99Q6k0tk8NU3gLQKO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcnxkas%2FdJMcajbengz%2FT2lo99Q6k0tk8NU3gLQKO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1089&quot; height=&quot;955&quot; data-filename=&quot;덧셈만계산기.png&quot; data-origin-width=&quot;1089&quot; data-origin-height=&quot;955&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779967295592&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 덧셈 기능 전체 코드
### 그런데 덧셈기능만 구현되는 계산기는 c버튼 클릭시 초기화가 되지 않는 문제가 있다.
import sys
from PySide6.QtWidgets import (
    QApplication, QWidget, QLabel, QPushButton, QGridLayout
)
from PySide6.QtCore import Qt


class CalculatorLayoutDemo(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle(&quot;계산기 (덧셈 기능만)&quot;)
        self.setMinimumSize(336, 541)

        # ======== 계산 상태 변수 ========
        self.current_input = &quot;0&quot;  # 화면에 표시되는 현재 입력
        self.saved_value = None  # 이전 값
        self.is_add_mode = False  # + 버튼이 눌러진 상태 여부

        # ======== [1] 레이아웃 ========
        layout = QGridLayout(self)
        layout.setSpacing(4)
        layout.setContentsMargins(4, 4, 4, 4)

        # ======== [2] 결과 표시 ========
        self.result_label = QLabel(&quot;0&quot;)
        self.result_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self.result_label.setStyleSheet(&quot;font-size: 36px; padding: 8px;&quot;)
        layout.addWidget(self.result_label, 0, 0, 1, 4)

        # ======== [3] 버튼 행렬 ========
        buttons = [
            [&quot;%&quot;, &quot;CE&quot;, &quot;C&quot;, &quot;⌫&quot;],
            [&quot;1/x&quot;, &quot;x&amp;sup2;&quot;, &quot;&amp;radic;x&quot;, &quot;&amp;divide;&quot;],
            [&quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;&amp;times;&quot;],
            [&quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;&amp;minus;&quot;],
            [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;+&quot;],
            [&quot;+/-&quot;, &quot;0&quot;, &quot;.&quot;, &quot;=&quot;],
        ]

        self.button_map = {}
        row_offset = 1

        for r, row in enumerate(buttons):
            for c, text in enumerate(row):
                btn = QPushButton(text)
                btn.setMinimumHeight(50)
                layout.addWidget(btn, row_offset + r, c)
                self.button_map[text] = btn

        # ======== 버튼 기능 연결 ========
        # 숫자 버튼
        for num in [&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;9&quot;]:
            self.button_map[num].clicked.connect(self.on_number_clicked)

        # 덧셈
        self.button_map[&quot;+&quot;].clicked.connect(self.on_plus_clicked)

        # =
        self.button_map[&quot;=&quot;].clicked.connect(self.on_equal_clicked)

        # 초기값 표시
        self.update_display()

    # 숫자 입력 처리
    def on_number_clicked(self):
        text = self.sender().text()

        if self.current_input == &quot;0&quot;:
            self.current_input = text
        else:
            self.current_input += text

        self.update_display()

    # + 동작
    def on_plus_clicked(self):
        self.saved_value = float(self.current_input)
        self.current_input = &quot;0&quot;
        self.is_add_mode = True
        self.update_display()

    # = 동작
    def on_equal_clicked(self):
        if self.is_add_mode and self.saved_value is not None:
            result = self.saved_value + float(self.current_input)
            self.current_input = str(result)

        self.is_add_mode = False
        self.saved_value = None
        self.update_display()

    # 화면 업데이트
    def update_display(self):
        self.result_label.setText(self.current_input)


if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = CalculatorLayoutDemo()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1-4) 계산기 사칙연산이 가능하게 레이아웃 수정하기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;수정된 사칙연산 계산기.png&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjgpQB/dJMcaak8agV/hk7Ybrnp8FdTNbA0LJG3pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjgpQB/dJMcaak8agV/hk7Ybrnp8FdTNbA0LJG3pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjgpQB/dJMcaak8agV/hk7Ybrnp8FdTNbA0LJG3pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjgpQB%2FdJMcaak8agV%2Fhk7Ybrnp8FdTNbA0LJG3pk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1246&quot; height=&quot;913&quot; data-filename=&quot;수정된 사칙연산 계산기.png&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;913&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779967393904&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#### [사칙연산]이 가능한 구조개선 과제 (덧셈과 여러연산자 상태변수 일반화 하기)
#### 덧셈기능만 구현되는 계산기는 초기화 기능 및 사칙연산 계산 기능을 추가하여 문제를 해결함
import sys
from PySide6.QtWidgets import QApplication, QWidget, QGridLayout, QLabel, QPushButton
from PySide6.QtCore import Qt

class CalculatorLayoutDemo(QWidget):
    def __init__(self):
        super().__init__()
### 타이틀 제목을 수정했다. 사칙연산 구조 개선
        self.setWindowTitle(&quot;계산기(사칙연산 구조개선)&quot;)
        self.setMinimumSize(336, 541)

        # ======== 데이터 초기화 ========
        self.current_input = &quot;0&quot;      # 현재 입력 중인 숫자
        self.saved_value = None       # 저장된 이전 값
        self.current_operator = None  # 현재 선택된 연산자 (+, -, *, /)

        # ======== [1] 레이아웃 ========
        layout = QGridLayout(self)
        layout.setSpacing(4)
        layout.setContentsMargins(4, 4, 4, 4)

        # ======== [2] 결과 창 ========
        self.result_label = QLabel(&quot;0&quot;)
        # PySide6에서는 Qt.AlignmentFlag 형식을 권장합니다.
        self.result_label.setAlignment(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
        self.result_label.setStyleSheet(&quot;font-size: 36px; padding: 8px;&quot;)
        layout.addWidget(self.result_label, 0, 0, 1, 4)

        # ======== [3] 버튼 생성 ========
        buttons = [
            [&quot;%&quot;, &quot;CE&quot;, &quot;C&quot;, &quot;back&quot;],
            [&quot;1/x&quot;, &quot;x&amp;sup2;&quot;, &quot;&amp;radic;x&quot;, &quot;/&quot;],
            [&quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;*&quot;],
            [&quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;-&quot;],
            [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;+&quot;],
            [&quot;+/-&quot;, &quot;0&quot;, &quot;.&quot;, &quot;=&quot;],
        ]

        self.button_map = {}
        row_offset = 1

        for r, row in enumerate(buttons):
            for c, text in enumerate(row):
                btn = QPushButton(text)
                btn.setMinimumHeight(50)
                layout.addWidget(btn, row_offset + r, c)
                self.button_map[text] = btn

        # ======== 이벤트 연결 ========
        # 숫자 및 소수점 버튼
        for num in [&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;9&quot;, &quot;.&quot;]:
            self.button_map[num].clicked.connect(self.on_number_clicked)

        # 사칙연산 버튼 (+, -, *, /)
### 사칙연산이 가능하도록 버튼을 눌렀을 때 값이 계산되도록 한다
        for op in [&quot;+&quot;, &quot;-&quot;, &quot;*&quot;, &quot;/&quot;]:
            self.button_map[op].clicked.connect(self.on_operator_clicked)
### 기능버튼을 사용하여 값을 계산하도록 한다.
        # 기능 버튼
        self.button_map[&quot;=&quot;].clicked.connect(self.on_equal_clicked)
        self.button_map[&quot;C&quot;].clicked.connect(self.on_clear_clicked)

### 화면 업데이트
        self.update_display()

    # 숫자 버튼 클릭 이벤트
    def on_number_clicked(self):
        text = self.sender().text()

        if text == &quot;.&quot;:
            if &quot;.&quot; in self.current_input:
                return  # 이미 소수점이 있으면 무시
            self.current_input += text
        elif self.current_input == &quot;0&quot;:
            self.current_input = text
        else:
            self.current_input += text

        self.update_display()

    # 연산자 버튼 클릭 이벤트 (+, -, *, /)
    def on_operator_clicked(self):
        op = self.sender().text()
        self.saved_value = float(self.current_input)
        self.current_operator = op
        self.current_input = &quot;0&quot;
        self.update_display()

    # = 버튼 클릭 이벤트 (결과 계산)
    def on_equal_clicked(self):
        if self.current_operator is None or self.saved_value is None:
            return

        current_val = float(self.current_input)
        result = 0

        # 연산자별 계산
        if self.current_operator == &quot;+&quot;:
            result = self.saved_value + current_val
        elif self.current_operator == &quot;-&quot;:
            result = self.saved_value - current_val
        elif self.current_operator == &quot;*&quot;:
            result = self.saved_value * current_val
        elif self.current_operator == &quot;/&quot;:
            if current_val == 0:
                self.current_input = &quot;Error (0으로 나눌 수 없음)&quot;
                self.update_display()
                self.saved_value = None
                self.current_operator = None
                return
            result = self.saved_value / current_val

        # 소수점 아래가 0이면 정수로 변환, 아니면 실수 그대로 표시
        if result.is_integer():
            self.current_input = str(int(result))
        else:
            self.current_input = str(result)

        self.current_operator = None
        self.saved_value = None
        self.update_display()

    # C 버튼 클릭 이벤트 (초기화)
    def on_clear_clicked(self):
        self.current_input = &quot;0&quot;
        self.saved_value = None
        self.current_operator = None
        self.update_display()

    # 디스플레이 갱신
    def update_display(self):
        self.result_label.setText(self.current_input)


if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = CalculatorLayoutDemo()
    w.show()
    sys.exit(app.exec())  # PySide6에서는 exec_() 대신 exec()을 사용합니다.&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1-5)&lt;span&gt; QTab Widget&amp;nbsp; 버튼틀, 정보입력창 만들기&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;위젯탭1.png&quot; data-origin-width=&quot;1047&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kn2pZ/dJMcac4jXu5/pIsDtNB5YUydhKaPrTaKGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kn2pZ/dJMcac4jXu5/pIsDtNB5YUydhKaPrTaKGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kn2pZ/dJMcac4jXu5/pIsDtNB5YUydhKaPrTaKGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKn2pZ%2FdJMcac4jXu5%2FpIsDtNB5YUydhKaPrTaKGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1047&quot; height=&quot;784&quot; data-filename=&quot;위젯탭1.png&quot; data-origin-width=&quot;1047&quot; data-origin-height=&quot;784&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.py&lt;/p&gt;
&lt;pre id=&quot;code_1779968559888&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import QApplication
from widget import Widget
import sys

if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;widget.py&lt;/p&gt;
&lt;pre id=&quot;code_1779967587906&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout,
    QTabWidget, QPushButton, QLabel, QLineEdit
)

class Widget(QWidget):
    def __init__(self):
        super().__init__()

        # 윈도우 제목
        self.setWindowTitle(&quot;QTabWidget 데모&quot;)

        # [1] 탭 위젯 생성
        tab_widget = QTabWidget(self)

        # [2] 첫 번째 탭 : 정보 입력 탭
        widget_form = QWidget()
        label_full_name = QLabel(&quot;이름 :&quot;)
        line_edit_full_name = QLineEdit()
        line_edit_full_name.setPlaceholderText(&quot;이름을 입력하세요&quot;)

        form_layout = QHBoxLayout()
        form_layout.addWidget(label_full_name)
        form_layout.addWidget(line_edit_full_name)
        widget_form.setLayout(form_layout)

        # [3] 두 번째 탭 : 버튼 탭
        widget_buttons = QWidget()
        button_1 = QPushButton(&quot;버튼 1&quot;)
        button_2 = QPushButton(&quot;버튼 2&quot;)
        button_3 = QPushButton(&quot;버튼 3&quot;)

        # 버튼 1 클릭 시 슬롯 함수 호출
        button_1.clicked.connect(self.button_1_clicked)

        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(button_1)  # 버튼 크기 결정 값
        buttons_layout.addWidget(button_2)  # 버튼 크기 결정 값
        buttons_layout.addWidget(button_3)  # 버튼 크기 결정 값
        widget_buttons.setLayout(buttons_layout)

        # [4] 탭 위젯에 탭 추가
    ### 처음의 위젯 버튼에 &quot;정보입력&quot; 버튼이 있고, 추가로 두번째 클릭 되는 '버튼틀'을 추가한다.
        tab_widget.addTab(widget_form, &quot;정보 입력&quot;)
        tab_widget.addTab(widget_buttons, &quot;버튼들&quot;)

        # [5] 위젯 전체 레이아웃 설정
        layout = QVBoxLayout()
        layout.addWidget(tab_widget)
        self.setLayout(layout)

    # [6] 슬롯 함수 : 버튼 1 클릭 시 동작
    def button_1_clicked(self):
        print(&quot;버튼 1이 클릭되었습니다.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예시 1-6) &lt;b&gt;&lt;span&gt;QTab Widget&amp;nbsp; 버튼틀 누르기&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 버튼 1동작, 버튼틀 추가&amp;nbsp; 수정하기&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;텝레이아웃2.png&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;842&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjAwaR/dJMcadvkQIV/qyx4GtwyysQkS2sjKS8EM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjAwaR/dJMcadvkQIV/qyx4GtwyysQkS2sjKS8EM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjAwaR/dJMcadvkQIV/qyx4GtwyysQkS2sjKS8EM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjAwaR%2FdJMcadvkQIV%2Fqyx4GtwyysQkS2sjKS8EM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1045&quot; height=&quot;842&quot; data-filename=&quot;텝레이아웃2.png&quot; data-origin-width=&quot;1045&quot; data-origin-height=&quot;842&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.py&lt;/p&gt;
&lt;pre id=&quot;code_1779968711881&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import QApplication
from widget import Widget
import sys

if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;widget.py&lt;/p&gt;
&lt;figure style=&quot;color: #333333; text-align: center;&quot; data-ke-style=&quot;alignCenter&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; data-ke-type=&quot;image&quot;&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;pre id=&quot;code_1779968657010&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout,
    QTabWidget, QPushButton, QLabel, QLineEdit
)

class Widget(QWidget):
    def __init__(self):
        super().__init__()

        # 윈도우 제목
        self.setWindowTitle(&quot;QTabWidget 데모&quot;)

        # [1] 탭 위젯 생성
        tab_widget = QTabWidget(self)

        # [2] 첫 번째 탭 : 정보 입력 탭
        widget_form = QWidget()
        label_full_name = QLabel(&quot;이름 :&quot;)
        line_edit_full_name = QLineEdit()
        line_edit_full_name.setPlaceholderText(&quot;이름을 입력하세요&quot;)

        form_layout = QHBoxLayout()
        form_layout.addWidget(label_full_name)
        form_layout.addWidget(line_edit_full_name)
        widget_form.setLayout(form_layout)

        # [3] 두 번째 탭 : 버튼 탭
        widget_buttons = QWidget()
        button_1 = QPushButton(&quot;버튼 1&quot;)
        button_2 = QPushButton(&quot;버튼 2&quot;)
        button_3 = QPushButton(&quot;버튼 3&quot;)

        # 버튼 1 클릭 시 슬롯 함수 호출
        button_1.clicked.connect(self.button_1_clicked)

        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(button_1)  # 버튼 크기 결정 값
        buttons_layout.addWidget(button_2)  # 버튼 크기 결정 값
        buttons_layout.addWidget(button_3)  # 버튼 크기 결정 값
        widget_buttons.setLayout(buttons_layout)

        # [4] 탭 위젯에 탭 추가
    ### 처음의 위젯 버튼에 &quot;정보입력&quot; 버튼이 있고, 추가로 두번째 클릭 되는 '버튼틀'을 추가한다.
        tab_widget.addTab(widget_form, &quot;정보 입력&quot;)
        tab_widget.addTab(widget_buttons, &quot;버튼들&quot;)

        # [5] 위젯 전체 레이아웃 설정
        layout = QVBoxLayout()
        layout.addWidget(tab_widget)
        self.setLayout(layout)

    # [6] 슬롯 함수 : 버튼 1 클릭 시 동작
    def button_1_clicked(self):
        print(&quot;버튼 1이 클릭되었습니다.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(예시 ) &lt;b&gt;&lt;b&gt;&lt;span&gt;QTab Widget 정보 입력하고 이름 확인 클릭시 출력이 된다.&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정보입력탭 버튼클릭 출력.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC0S5Z/dJMcagFIC29/kMN01PX5o7CJkK2M9LUsN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC0S5Z/dJMcagFIC29/kMN01PX5o7CJkK2M9LUsN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC0S5Z/dJMcagFIC29/kMN01PX5o7CJkK2M9LUsN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC0S5Z%2FdJMcagFIC29%2FkMN01PX5o7CJkK2M9LUsN1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1039&quot; height=&quot;880&quot; data-filename=&quot;정보입력탭 버튼클릭 출력.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt;main.py&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1779968823898&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import QApplication
from widget import Widget
import sys

if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt;widget.py&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1779968855923&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout,
    QTabWidget, QPushButton, QLabel, QLineEdit
)

class Widget(QWidget):
    def __init__(self):
        super().__init__()

        # 윈도우 제목
        self.setWindowTitle(&quot;QTabWidget 데모&quot;)

        # [1] 탭 위젯 생성
        tab_widget = QTabWidget(self)

        # [2] 첫 번째 탭 : 정보 입력 탭
        widget_form = QWidget()
        label_full_name = QLabel(&quot;이름 :&quot;)

        # &amp;lt;추가 실습 과제&amp;gt; 인스턴스 변수로 변경
        self.line_edit_full_name = QLineEdit()
        self.line_edit_full_name.setPlaceholderText(&quot;이름을 입력하세요&quot;)

        # &amp;lt;추가 실습 과제&amp;gt; 이름 확인 버튼 추가
        info_button = QPushButton(&quot;이름 확인&quot;)
        info_button.clicked.connect(self.info_button_clicked)

        # 기존: HBoxLayout &amp;rarr; 수정: 이름 입력 + 버튼 수직 배치
        row_layout = QHBoxLayout()
        row_layout.addWidget(label_full_name)
        row_layout.addWidget(self.line_edit_full_name)

        form_layout = QVBoxLayout()   # &amp;lt;추가 실습 과제&amp;gt; 탭 구성 변경
        form_layout.addLayout(row_layout)
        form_layout.addWidget(info_button)  # &amp;lt;추가 실습 과제&amp;gt;
        widget_form.setLayout(form_layout)

        # [3] 두 번째 탭 : 버튼 탭
        widget_buttons = QWidget()
        button_1 = QPushButton(&quot;버튼 1&quot;)
        button_2 = QPushButton(&quot;버튼 2&quot;)
        button_3 = QPushButton(&quot;버튼 3&quot;)

        # 버튼 클릭 시 슬롯 함수 호출
        button_1.clicked.connect(self.button_1_clicked)
        button_2.clicked.connect(self.button_2_clicked)
        button_3.clicked.connect(self.button_3_clicked)

        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(button_1)
        buttons_layout.addWidget(button_2)
        buttons_layout.addWidget(button_3)
        widget_buttons.setLayout(buttons_layout)

        # [4] 탭 위젯에 탭 추가
        tab_widget.addTab(widget_form, &quot;정보 입력&quot;)
        tab_widget.addTab(widget_buttons, &quot;버튼들&quot;)

        # [5] 위젯 전체 레이아웃 설정
        layout = QVBoxLayout()
        layout.addWidget(tab_widget)
        self.setLayout(layout)

    # [6] 슬롯 함수 : 버튼 1 클릭 시 동작
    def info_button_clicked(self):
        # &amp;lt;추가 실습 과제&amp;gt; 이름 입력 여부 확인 후 출력
        name = self.line_edit_full_name.text().strip()
#### 탭에서 이름을 입력한 후 &quot;이름확인&quot;을 클릭하면 클릭했다는 메세지가 출력된다.
        if not name:
            print(&quot;이름을 먼저 입력해 주세요.&quot;)
        else:
            print(f&quot;{name}님, info 출력 클릭하셨습니다.&quot;)

    def button_1_clicked(self):
        print(&quot;버튼 2가 클릭되었습니다.&quot;)

    def button_2_clicked(self):
        print(&quot;버튼 2가 클릭되었습니다.&quot;)

    def button_3_clicked(self):
        print(&quot;버튼 3이 클릭되었습니다.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widget 레이아웃 버튼을 눌러서 출력결과 확인 하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;탭레이아웃 버튼 클릭 출력.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YtM2j/dJMb997B9Jx/hWdnGkdu32kEryIR0ja1A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YtM2j/dJMb997B9Jx/hWdnGkdu32kEryIR0ja1A1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YtM2j/dJMb997B9Jx/hWdnGkdu32kEryIR0ja1A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYtM2j%2FdJMb997B9Jx%2FhWdnGkdu32kEryIR0ja1A1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1039&quot; height=&quot;880&quot; data-filename=&quot;탭레이아웃 버튼 클릭 출력.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widget 버튼 클릭시 클릭되었다는 메세지 출력 확인&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;버튼레이아웃 클릭메지 출력.png&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;902&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/92PEM/dJMcadvkQRH/HXkw5sndqiv7OGer3KNOF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/92PEM/dJMcadvkQRH/HXkw5sndqiv7OGer3KNOF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/92PEM/dJMcadvkQRH/HXkw5sndqiv7OGer3KNOF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F92PEM%2FdJMcadvkQRH%2FHXkw5sndqiv7OGer3KNOF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;958&quot; height=&quot;902&quot; data-filename=&quot;버튼레이아웃 클릭메지 출력.png&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;902&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.py&lt;/p&gt;
&lt;pre id=&quot;code_1779968928676&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;widget.py&lt;/p&gt;
&lt;pre id=&quot;code_1779968957523&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import (
    QWidget, QHBoxLayout, QVBoxLayout,
    QTabWidget, QPushButton, QLabel, QLineEdit
)

class Widget(QWidget):
    def __init__(self):
        super().__init__()

        # 윈도우 제목
        self.setWindowTitle(&quot;QTabWidget 데모&quot;)

        # [1] 탭 위젯 생성
        tab_widget = QTabWidget(self)

        # &amp;lt;추가 실습 과제3&amp;gt; 탭 클릭 시 시그널 연결
        tab_widget.currentChanged.connect(self.tab_changed)

        # [2] 첫 번째 탭 : 정보 입력 탭
        widget_form = QWidget()
        label_full_name = QLabel(&quot;이름 :&quot;)

        # &amp;lt;추가 실습 과제&amp;gt; 인스턴스 변수로 변경
        self.line_edit_full_name = QLineEdit()
        self.line_edit_full_name.setPlaceholderText(&quot;이름을 입력하세요&quot;)

        # &amp;lt;추가 실습 과제&amp;gt; 이름 확인 버튼 추가
        info_button = QPushButton(&quot;이름 확인&quot;)
        info_button.clicked.connect(self.info_button_clicked)

        # 기존: HBoxLayout &amp;rarr; 수정: 이름 입력 + 버튼 수직 배치
        row_layout = QHBoxLayout()
        row_layout.addWidget(label_full_name)
        row_layout.addWidget(self.line_edit_full_name)

        form_layout = QVBoxLayout()   # &amp;lt;추가 실습 과제&amp;gt; 탭 구성 변경
        form_layout.addLayout(row_layout)
        form_layout.addWidget(info_button)  # &amp;lt;추가 실습 과제&amp;gt;
        widget_form.setLayout(form_layout)

        # [3] 두 번째 탭 : 버튼 탭
        widget_buttons = QWidget()
        button_1 = QPushButton(&quot;버튼 1&quot;)
        button_2 = QPushButton(&quot;버튼 2&quot;)
        button_3 = QPushButton(&quot;버튼 3&quot;)

        # 버튼 클릭 시 슬롯 함수 호출
        button_1.clicked.connect(self.button_1_clicked)
        button_2.clicked.connect(self.button_2_clicked)
        button_3.clicked.connect(self.button_3_clicked)

        buttons_layout = QVBoxLayout()
        buttons_layout.addWidget(button_1)
        buttons_layout.addWidget(button_2)
        buttons_layout.addWidget(button_3)
        widget_buttons.setLayout(buttons_layout)

        # [4] 탭 위젯에 탭 추가
        tab_widget.addTab(widget_form, &quot;정보 입력&quot;)
        tab_widget.addTab(widget_buttons, &quot;버튼들&quot;)

        # [5] 위젯 전체 레이아웃 설정
        layout = QVBoxLayout()
        layout.addWidget(tab_widget)
        self.setLayout(layout)

    # [6] 슬롯 함수 : 버튼 1 클릭 시 동작
    def info_button_clicked(self):
        # &amp;lt;추가 실습 과제&amp;gt; 이름 입력 여부 확인 후 출력
        name = self.line_edit_full_name.text().strip()

        if not name:
            print(&quot;이름을 먼저 입력해 주세요.&quot;)
        else:
            print(f&quot;{name}님, info 출력 클릭하셨습니다.&quot;)

    def button_1_clicked(self):
        print(&quot;버튼 2가 클릭되었습니다.&quot;)

    def button_2_clicked(self):
        print(&quot;버튼 2가 클릭되었습니다.&quot;)

    def button_3_clicked(self):
        print(&quot;버튼 3이 클릭되었습니다.&quot;)

### 웹 하나의 창에서 Layout의 버튼 중복 배치를 통해 탭을 클릭하면 동작이 출력하는 코드이다.

    # &amp;lt;추가 실습 과제3&amp;gt; 탭을 클릭하면 탭 이름 출력
    def tab_changed(self, index):
        tab_widget = self.findChild(QTabWidget)  # 현재 탭 위젯 찾기
        tab_text = tab_widget.tabText(index)     # 클릭한 탭의 이름 가져오기
        print(f&quot;'{tab_text}' 탭을 클릭했습니다.&quot;)

        # &amp;lt;추가 실습 과제4&amp;gt; 첫 번째 탭에서 두 번째 탭으로 이동하는 슬롯
        def go_to_second_tab(self):
            # 현재 위젯(self) 안에서 QTabWidget 타입의 자식 위젯을 찾아온다.
            tab_widget = self.findChild(QTabWidget)

            # 탭 위젯을 정상적으로 찾았는지 확인한다.
            if tab_widget is not None:
                # 인덱스 1번 탭으로 이동한다.
                # 0 &amp;rarr; 첫 번째 탭: &quot;정보 입력&quot;
                # 1 &amp;rarr; 두 번째 탭: &quot;버튼들&quot;
                tab_widget.setCurrentIndex(1)

#### 탭에서 이동할 때 슬롯 함수를 사용해 버튼 누름이 첫번째 탭으로 이동하는 것을 구현해 본다.
#### 처음 실행 화면부터 정보입력 창이 실행되는 메세지가 출력된다. 이후 클릭 순서에 따라 메세지가 출력된다
        # &amp;lt;추가 실습 과제4&amp;gt; 두 번째 탭에서 첫 번째 탭으로 이동하는 슬롯
        def go_to_first_tab(self):
            # 현재 위젯(self) 안에서 QTabWidget 타입의 자식 위젯을 찾아온다.
            tab_widget = self.findChild(QTabWidget)

            # 탭 위젯을 정상적으로 찾았는지 확인한다.
            if tab_widget is not None:
                # 인덱스 0번 탭으로 이동한다.
                # 0 &amp;rarr; 첫 번째 탭: &quot;정보 입력&quot;
                # 1 &amp;rarr; 두 번째 탭: &quot;버튼들&quot;
                tab_widget.setCurrentIndex(0)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge 레이아웃 첫화면 탭&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;탭레이아웃 첫화면탭.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;943&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2nCB0/dJMcahYRS7q/f5FYuPkXI0YS6k0LKbPGF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2nCB0/dJMcahYRS7q/f5FYuPkXI0YS6k0LKbPGF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2nCB0/dJMcahYRS7q/f5FYuPkXI0YS6k0LKbPGF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2nCB0%2FdJMcahYRS7q%2Ff5FYuPkXI0YS6k0LKbPGF0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;868&quot; height=&quot;788&quot; data-filename=&quot;탭레이아웃 첫화면탭.png&quot; data-origin-width=&quot;1039&quot; data-origin-height=&quot;943&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge 스크롤 레이아웃 항목 추가 하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크롤레이아웃.png&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1KlOc/dJMcahYRS9w/AENddYDzblCY9HDGTkgyz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1KlOc/dJMcahYRS9w/AENddYDzblCY9HDGTkgyz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1KlOc/dJMcahYRS9w/AENddYDzblCY9HDGTkgyz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1KlOc%2FdJMcahYRS9w%2FAENddYDzblCY9HDGTkgyz1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1004&quot; height=&quot;966&quot; data-filename=&quot;스크롤레이아웃.png&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;966&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;main.py&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1779969155773&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 위젯파일과 메인파일로 분리해서 메인파일을 실행시키면 엡창이 실행된다.
#### tab_scroll_area.py 에서 메인에 분리할 참조 내용들 ####
#from PySide6.QtWidgets import (
#    QWidget, QVBoxLayout, QScrollArea,
#    QLabel, QPushButton
#)
#from PySide6.QtCore import Qt
#class ScrollAreaTab(QWidget):
#    def __init__(self, parent=None):
#        super().__init__(parent)

#### Widget에서 분리 생성된 main.py 내용들 ####
import sys
from PySide6.QtWidgets import QApplication, QMainWindow

# widget.py 파일에서 class 부분 ScrollAreaTab 클래스를 가져오기
from widget import ScrollAreaTab

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(&quot;Scroll Area Tab Example&quot;)
        self.resize(400, 500)

        # 위젯 생성 후 메인 윈도우의 중앙 위젯으로 설정
        self.tab_widget = ScrollAreaTab()
        self.setCentralWidget(self.tab_widget)

if __name__ == &quot;__main__&quot;:   # 스크립트가 직접 실행될 때만 코드 실행하기
    app = QApplication(sys.argv)   # 애플리케이션 객체를 생성, 명령행 인수를 전달해 Qt 환경을 초기화 함
    w = MainWindow()  # 위젯파이에서 클래스 위젯을 가리키며, 위젯 객체(윈도우 창)를 생성 한다.
    w.show()          # 생성한 위젯 창을 화면에 표시 한다.
    sys.exit(app.exec())   # Qt의 메인 이벤트 루프를 시작, 프로그램 종료시 안전하게 리소스를 해제한다&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;widget.py&lt;/p&gt;
&lt;pre id=&quot;code_1779969207173&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tab_scroll_area.py
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QScrollArea,
    QLabel, QPushButton
)
from PySide6.QtCore import Qt


class ScrollAreaTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        self.add_button = QPushButton(&quot;항목 추가&quot;)
        self.add_button.clicked.connect(self.add_item)
        layout.addWidget(self.add_button)

# QScrollArea 사용하기
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        layout.addWidget(self.scroll_area)

 # 스크롤 안에서 실제 내용은 별도의 QWidget + QVBoxLayout  실행한다. 내용이 많으면 자동스크롤바 생성
        self.content_widget = QWidget()
        self.content_layout = QVBoxLayout(self.content_widget)
        self.content_layout.setAlignment(Qt.AlignTop)

        self.scroll_area.setWidget(self.content_widget)

        self.item_count = 0
        for i in range(5):
            self.add_label(f&quot;초기 항목 {i + 1}&quot;)
        self.item_count = 5

    def add_label(self, text: str):
        label = QLabel(text)
        self.content_layout.addWidget(label)

    def add_item(self):
        self.item_count += 1
        new_text = f&quot;추가된 항목 {self.item_count}&quot;
        self.add_label(new_text)
        print(new_text)
# 항목 추가시 자동으로 맨 아래로 스크롤바 생성
        bar = self.scroll_area.verticalScrollBar()
        bar.setValue(bar.maximum())&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge&amp;nbsp; 스크롤 바 생성하기&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크롤바 생성.png&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;951&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H4ElW/dJMcagMt6Y0/2Yui2AOa4BBW5B0RAZ3RJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H4ElW/dJMcagMt6Y0/2Yui2AOa4BBW5B0RAZ3RJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H4ElW/dJMcagMt6Y0/2Yui2AOa4BBW5B0RAZ3RJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH4ElW%2FdJMcagMt6Y0%2F2Yui2AOa4BBW5B0RAZ3RJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;982&quot; height=&quot;951&quot; data-filename=&quot;스크롤바 생성.png&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;951&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge 스크롤 로그 추가 하기&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크롤 로그 추가.png&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;951&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b14EAw/dJMcagFIDbC/u7rqCF07SPV7KqqcUDkTkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b14EAw/dJMcagFIDbC/u7rqCF07SPV7KqqcUDkTkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b14EAw/dJMcagFIDbC/u7rqCF07SPV7KqqcUDkTkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb14EAw%2FdJMcagFIDbC%2Fu7rqCF07SPV7KqqcUDkTkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;982&quot; height=&quot;951&quot; data-filename=&quot;스크롤 로그 추가.png&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;951&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.py&lt;/p&gt;
&lt;pre id=&quot;code_1779969291623&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 스크롤을 사용자가 편집하지 못하게 전형적인 로그창 스타일 실습하기
import sys
from PySide6.QtWidgets import QApplication, QMainWindow

# widget.py 파일에서 class 부분 ScrollAreaTab 클래스를 가져오기
from widget import LogTextEditTab

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(&quot;LogTextEditTab&quot;)
        self.resize(400, 500)

        # 위젯 생성 후 메인 윈도우의 중앙 위젯으로 설정
        self.tab_widget = LogTextEditTab()
        self.setCentralWidget(self.tab_widget)

if __name__ == &quot;__main__&quot;:   # 스크립트가 직접 실행될 때만 코드 실행하기
    app = QApplication(sys.argv)   # 애플리케이션 객체를 생성, 명령행 인수를 전달해 Qt 환경을 초기화 함
    w = MainWindow()  # 위젯파이에서 클래스 위젯을 가리키며, 위젯 객체(윈도우 창)를 생성 한다.
    w.show()          # 생성한 위젯 창을 화면에 표시 한다.
    sys.exit(app.exec())   # Qt의 메인 이벤트 루프를 시작, 프로그램 종료시 안전하게 리소스를 해제한다&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;widget.py&lt;/p&gt;
&lt;pre id=&quot;code_1779969317055&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tab_log_textedit.py
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout,
    QPushButton, QTextEdit
)
from PySide6.QtGui import QTextCursor


class LogTextEditTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        self.log_textedit = QTextEdit()
        self.log_textedit.setReadOnly(True)
        layout.addWidget(self.log_textedit)

        self.log_button = QPushButton(&quot;로그 추가&quot;)
        self.log_button.clicked.connect(self.add_log)
        layout.addWidget(self.log_button)

        self.log_count = 0

    def add_log(self):
        self.log_count += 1
        message = f&quot;[로그] {self.log_count}번째 메시지입니다.&quot;
        self.log_textedit.append(message)
        print(message)

        cursor = self.log_textedit.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.log_textedit.setTextCursor(cursor)
        self.log_textedit.ensureCursorVisible()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge&amp;nbsp; 스크롤 통합 (스크롤 영역)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크롤 통합1.png&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Oqyf5/dJMcaiDumVj/1eFDaXCUQjFSKmJvhnts81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Oqyf5/dJMcaiDumVj/1eFDaXCUQjFSKmJvhnts81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Oqyf5/dJMcaiDumVj/1eFDaXCUQjFSKmJvhnts81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOqyf5%2FdJMcaiDumVj%2F1eFDaXCUQjFSKmJvhnts81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;946&quot; data-filename=&quot;스크롤 통합1.png&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge 스크롤 통합 리스트 작성 (리스트 스크롤)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크로롤통합리스트.png&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhqUHe/dJMcagZV3bU/5IMhUk9DE2ZwB5jkkM6qSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhqUHe/dJMcagZV3bU/5IMhUk9DE2ZwB5jkkM6qSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhqUHe/dJMcagZV3bU/5IMhUk9DE2ZwB5jkkM6qSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhqUHe%2FdJMcagZV3bU%2F5IMhUk9DE2ZwB5jkkM6qSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;946&quot; data-filename=&quot;스크로롤통합리스트.png&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge 스크롤 통합 로그 실습 (로그 스크롤)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;통합스크롤 로그.png&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k0jYK/dJMcafz0YcV/ZKaGC26MuO2F76o40kgWiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k0jYK/dJMcafz0YcV/ZKaGC26MuO2F76o40kgWiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k0jYK/dJMcafz0YcV/ZKaGC26MuO2F76o40kgWiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk0jYK%2FdJMcafz0YcV%2FZKaGC26MuO2F76o40kgWiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1044&quot; height=&quot;946&quot; data-filename=&quot;통합스크롤 로그.png&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;QTab Widge&amp;nbsp; 스크롤 통합 로그&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크롤 통합 메인파이.png&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;791&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FFDnY/dJMcaipXgEH/5E1Nv5ukcIOsFlNuNDC0r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FFDnY/dJMcaipXgEH/5E1Nv5ukcIOsFlNuNDC0r1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FFDnY/dJMcaipXgEH/5E1Nv5ukcIOsFlNuNDC0r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFFDnY%2FdJMcaipXgEH%2F5E1Nv5ukcIOsFlNuNDC0r1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1038&quot; height=&quot;791&quot; data-filename=&quot;스크롤 통합 메인파이.png&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;791&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main.py&lt;/p&gt;
&lt;pre id=&quot;code_1779969464377&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 스크롤을 사용자가 편집하지 못하게 전형적인 로그창 스타일 실습하기
import sys
from PySide6.QtWidgets import QApplication, QMainWindow

# widget.py 파일에서 class 부분 ScrollAreaTab 클래스를 가져오기
from widget import LogTextEditTab

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(&quot;LogTextEditTab&quot;)
        self.resize(400, 500)

        # 위젯 생성 후 메인 윈도우의 중앙 위젯으로 설정
        self.tab_widget = LogTextEditTab()
        self.setCentralWidget(self.tab_widget)

if __name__ == &quot;__main__&quot;:   # 스크립트가 직접 실행될 때만 코드 실행하기
    app = QApplication(sys.argv)   # 애플리케이션 객체를 생성, 명령행 인수를 전달해 Qt 환경을 초기화 함
    w = MainWindow()  # 위젯파이에서 클래스 위젯을 가리키며, 위젯 객체(윈도우 창)를 생성 한다.
    w.show()          # 생성한 위젯 창을 화면에 표시 한다.
    sys.exit(app.exec())   # Qt의 메인 이벤트 루프를 시작, 프로그램 종료시 안전하게 리소스를 해제한다&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;widget.py&lt;/p&gt;
&lt;pre id=&quot;code_1779969490632&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tab_log_textedit.py
from PySide6.QtWidgets import (
    QWidget, QVBoxLayout,
    QPushButton, QTextEdit
)
from PySide6.QtGui import QTextCursor


class LogTextEditTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        self.log_textedit = QTextEdit()
        self.log_textedit.setReadOnly(True)
        layout.addWidget(self.log_textedit)

        self.log_button = QPushButton(&quot;로그 추가&quot;)
        self.log_button.clicked.connect(self.add_log)
        layout.addWidget(self.log_button)

        self.log_count = 0

    def add_log(self):
        self.log_count += 1
        message = f&quot;[로그] {self.log_count}번째 메시지입니다.&quot;
        self.log_textedit.append(message)
        print(message)

        cursor = self.log_textedit.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.log_textedit.setTextCursor(cursor)
        self.log_textedit.ensureCursorVisible()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(예시 )&lt;span&gt; Layout Widget 위에서 실습한 파일들 분리하기&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;※ 소스코드를 분리하는 핵심 이유&lt;/b&gt;&lt;br /&gt;- 가독성 향상 : 한 파일이 수천 줄이 되는 것을 방지하여 코드를 쉽게 읽을 수 있다.&lt;br /&gt;- 유지보수 용이 :&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;u&gt;버튼 기능을 수정할 때 buttons_tab.py만 열어서 고치면 되므로&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다른 코드를 건드릴 위험이 줄어든다.&lt;br /&gt;- 코드 재사용 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&lt;u&gt;form_tab.py에서 만든 입력 양식을 다른 화면이나 다른 프로젝트에서 그대로 가져다 쓸 수&lt;/u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;있다.&lt;br /&gt;- 협업 수월 : 여러 개발자가 동시에 작업할 때, 파일이 분리되어 있으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;깃(Git) 충돌&lt;/u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;없이 각자 맡은 화면을 개발할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1779969777675&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# __init__.py &quot;&quot;&quot; Layout 복합적인 레이아웃 예제 학습 내용이다.&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1779969815140&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# main.py

import sys

if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1779969872061&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tab_list_widget.py 클래스에서 리스트 분리

from PySide6.QtWidgets import (
    QWidget, QVBoxLayout,
    QPushButton, QListWidget
)


class ListWidgetTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        self.add_button = QPushButton(&quot;항목 추가&quot;)
        self.add_button.clicked.connect(self.add_item)
        layout.addWidget(self.add_button)

        self.list_widget = QListWidget()
        layout.addWidget(self.list_widget)

        self.item_count = 0
        for i in range(10):
            self.list_widget.addItem(f&quot;초기 항목 {i + 1}&quot;)
        self.item_count = 10

    def add_item(self):
        self.item_count += 1
        text = f&quot;추가 항목 {self.item_count}&quot;
        self.list_widget.addItem(text)
        print(text)

        self.list_widget.scrollToBottom()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1779969949276&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tab_log_textedit.py  클래스에서 로그 텍스트에디트 부분 분리

class LogTextEditTab(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        self.log_textedit = QTextEdit()
        self.log_textedit.setReadOnly(True)
        layout.addWidget(self.log_textedit)

        self.log_button = QPushButton(&quot;로그 추가&quot;)
        self.log_button.clicked.connect(self.add_log)
        layout.addWidget(self.log_button)

        self.log_count = 0

    def add_log(self):
        self.log_count += 1
        message = f&quot;[로그] {self.log_count}번째 메시지입니다.&quot;
        self.log_textedit.append(message)
        print(message)

        cursor = self.log_textedit.textCursor()
        cursor.movePosition(QTextCursor.End)
        self.log_textedit.setTextCursor(cursor)
        self.log_textedit.ensureCursorVisible()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1779970000716&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# tab_scroll_area.py 클래스에서 스크롤 부분 분리

class ScrollAreaTab(QWidget):
    
   def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        self.add_button = QPushButton(&quot;항목 추가&quot;)
        self.add_button.clicked.connect(self.add_item)
        layout.addWidget(self.add_button)

        self.scroll_area = QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        layout.addWidget(self.scroll_area)

        self.content_widget = QWidget()
        self.content_layout = QVBoxLayout(self.content_widget)
        self.content_layout.setAlignment(Qt.AlignTop)

        self.scroll_area.setWidget(self.content_widget)

        self.item_count = 0
        for i in range(5):
            self.add_label(f&quot;초기 항목 {i + 1}&quot;)
        self.item_count = 5

    def add_label(self, text: str):
        label = QLabel(text)
        self.content_layout.addWidget(label)

    def add_item(self):
        self.item_count += 1
        new_text = f&quot;추가된 항목 {self.item_count}&quot;
        self.add_label(new_text)
        print(new_text)

        bar = self.scroll_area.verticalScrollBar()
        bar.setValue(bar.maximum())&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1779970074774&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# widget.py 위젯 클래스(부모) 
# from PyQt6.QtWidgets import QWidget  # 또는 PySide6.QtWidgets

class Widget(QWidget):  # QWidget(기본 위젯 클래스)을 상속받아 새로운 위젯 클래스를 정의함

    def __init__(self, parent=None):  # 클래스가 생성될 때 자동으로 실행되는 초기화 메서드(생성자)
    
       # 부모 클래스(QWidget)의 생성자를 호출하여 위젯을 올바르게 초기화하고 부모-자식 관계를 설정함
        super().__init__(parent)  


        self.setWindowTitle(&quot;스크롤 예제 통합 (QTabWidget)&quot;)
        self.resize(420, 340)

        layout = QVBoxLayout(self)

        self.tab_widget = QTabWidget()
        layout.addWidget(self.tab_widget)

        scroll_tab = ScrollAreaTab(self)
        list_tab = ListWidgetTab(self)
        log_tab = LogTextEditTab(self)

        self.tab_widget.addTab(scroll_tab, &quot;스크롤 영역&quot;)
        self.tab_widget.addTab(list_tab, &quot;리스트 스크롤&quot;)
        self.tab_widget.addTab(log_tab, &quot;로그 스크롤&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;※ widget.py&amp;nbsp;위젯&amp;nbsp;클래스(부모)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt; &amp;nbsp;from PyQt6.QtWidgets import QWidget&amp;nbsp; &amp;nbsp;# 또는 PySide6.QtWidgets&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp;class Widget(QWidget):&amp;nbsp; &amp;nbsp;# QWidget(기본 위젯 클래스)을 상속받아 새로운 위젯 클래스를 정의함&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp;def __init__(self, parent=None):&amp;nbsp;&amp;nbsp;# 클래스가 생성될 때 자동으로 실행되는 초기화 메서드(생성자)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(parent)&amp;nbsp; &amp;nbsp;# 부모 클래스(QWidget)의 생성자를 호출해 위젯을 초기화 하고 부모-자식 관계를 설정함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;end.&lt;/span&gt;&lt;/p&gt;</description>
      <category>학습 로그/Python3</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/49</guid>
      <comments>https://goodjop79.tistory.com/49#entry49comment</comments>
      <pubDate>Thu, 28 May 2026 21:15:57 +0900</pubDate>
    </item>
    <item>
      <title>D+35 [Layout] 레이아웃 종합 예제 학습(1)</title>
      <link>https://goodjop79.tistory.com/48</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ㅇ 일자&amp;nbsp; : 2026년 5월 27일(수)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ㅇ 내용 : Layout 가상환경에서 종합 예제 학습 하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 1)&amp;nbsp; 사이즈 정책&amp;nbsp; 실습&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ main.py 실행하면 윈도우위젯 화면에서 버튼이 출력되고, 텍스트를 입력할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;레이예1 스크린샷 2026-05-27 13-52-10.png&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9Rd12/dJMcaf003d5/mR7C6XIfJFuodv8JUecNf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9Rd12/dJMcaf003d5/mR7C6XIfJFuodv8JUecNf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9Rd12/dJMcaf003d5/mR7C6XIfJFuodv8JUecNf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9Rd12%2FdJMcaf003d5%2FmR7C6XIfJFuodv8JUecNf1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1107&quot; height=&quot;377&quot; data-filename=&quot;레이예1 스크린샷 2026-05-27 13-52-10.png&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779857759443&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# main.py 실행부 파일이다.

from PySide6.QtWidgets import QApplication
from widget import SizePolicyExample
import sys

if __name__ == &quot;__main__&quot;:
    app = QApplication(sys.argv)
    w = SizePolicyExample()
    w.show()
    sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1779857866875&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# widget.py 레이아웃 종합 예제 실습하기

from PySide6.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSizePolicy, QLineEdit, QPushButton

class SizePolicyExample(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle(&quot;사이즈 정책(SizePolicy) 및 스트레치 학습&quot;)

        # [1] SizePolicy 설정
        # SizePolicy는 부모 창의 크기가 변할 때 위젯의 크기를 어떻게 조절할 것인지 결정하는 정책입니다.
        label = QLabel(&quot;텍스트 입력: &quot;)
        line_edit = QLineEdit()

        # 가로 방향은 가능한 한 늘어나고(Expanding), 세로 방향은 고정(Fixed)
        line_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        # [2] 첫 번째 가로 레이아웃 : 텍스트 + 입력창
        h_layout_1 = QHBoxLayout()
        h_layout_1.addWidget(label)
        h_layout_1.addWidget(line_edit)

        # [3] 버튼 3개 생성
        button_1 = QPushButton(&quot;버튼1&quot;)
        button_2 = QPushButton(&quot;버튼2&quot;)
        button_3 = QPushButton(&quot;버튼3&quot;)

        # [4] 스트레치 설정
        # 버튼1은 stretch=2 &amp;rarr; 2배 넓은 공간 차지
        # 버튼2, 버튼3은 stretch=1 &amp;rarr; 동일 비율로 차지
        h_layout_2 = QHBoxLayout()
        h_layout_2.addWidget(button_1, 2)
        h_layout_2.addWidget(button_2, 1)
        h_layout_2.addWidget(button_3, 1)

        # [5] 최종 전체 수직 레이아웃
        v_layout = QVBoxLayout()
        v_layout.addLayout(h_layout_1)
        v_layout.addLayout(h_layout_2)

        self.setLayout(v_layout)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 2)&amp;nbsp; 창의 좌우 마우스로 늘려서 가장 많이 늘어나는 사이즈&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※&amp;nbsp; 버튼 1이 가장 크기가 크고 나머지는 동일하다. 값을 수정해 주면 된다. 1,1,1,&amp;nbsp; ----&amp;gt;&lt;span style=&quot;color: #ef5369;&quot;&gt; 2,1,1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-27 14-10-29.png&quot; data-origin-width=&quot;1095&quot; data-origin-height=&quot;481&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIoQbU/dJMb99Nf5XY/QiKlYEKpPYbogtuFduHd81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIoQbU/dJMb99Nf5XY/QiKlYEKpPYbogtuFduHd81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIoQbU/dJMb99Nf5XY/QiKlYEKpPYbogtuFduHd81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIoQbU%2FdJMb99Nf5XY%2FQiKlYEKpPYbogtuFduHd81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1095&quot; height=&quot;481&quot; data-filename=&quot;스크린샷 2026-05-27 14-10-29.png&quot; data-origin-width=&quot;1095&quot; data-origin-height=&quot;481&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779873732522&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;    h_layout_2.addWidget(button_1, 2)
    h_layout_2.addWidget(button_2, 1)
    h_layout_2.addWidget(button_3, 1)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 버튼 1은 크고, 버튼 2, 3번은 크기가 동일한 크기로 조정 (stretch)&amp;nbsp; stretch 값 수정&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-27 14-14-19.png&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;671&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyhd8d/dJMcaaMbT0l/XrkSLt0jkuWRYZhOw1fAzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyhd8d/dJMcaaMbT0l/XrkSLt0jkuWRYZhOw1fAzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyhd8d/dJMcaaMbT0l/XrkSLt0jkuWRYZhOw1fAzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdyhd8d%2FdJMcaaMbT0l%2FXrkSLt0jkuWRYZhOw1fAzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1096&quot; height=&quot;671&quot; data-filename=&quot;스크린샷 2026-05-27 14-14-19.png&quot; data-origin-width=&quot;1096&quot; data-origin-height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779871369234&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# widget.py 레이아웃 종합 예제 실습하기

from PySide6.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QSizePolicy, QLineEdit, QPushButton

class SizePolicyExample(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle(&quot;사이즈 정책(SizePolicy) 및 스트레치 학습&quot;)

        # [1] SizePolicy 설정
        # SizePolicy는 부모 창의 크기가 변할 때 위젯의 크기를 어떻게 조절할 것인지 결정하는 정책입니다.
        label = QLabel(&quot;텍스트 입력: &quot;)
        line_edit = QLineEdit()

        # 가로 방향은 가능한 한 늘어나고(Expanding), 세로 방향은 고정(Fixed)
        line_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        # [2] 첫 번째 가로 레이아웃 : 텍스트 + 입력창
        h_layout_1 = QHBoxLayout()
        h_layout_1.addWidget(label)
        h_layout_1.addWidget(line_edit)

        # [3] 버튼 3개 생성
        button_1 = QPushButton(&quot;버튼1&quot;)
        button_2 = QPushButton(&quot;버튼2&quot;)
        button_3 = QPushButton(&quot;버튼3&quot;)

        # [4] 스트레치 설정
        # 버튼1은 stretch=2 &amp;rarr; 2배 넓은 공간 차지
        # 버튼2, 버튼3은 stretch=1 &amp;rarr; 동일 비율로 차지
        h_layout_2 = QHBoxLayout()
        h_layout_2.addWidget(button_1, 2)
        h_layout_2.addWidget(button_2, 1)
        h_layout_2.addWidget(button_3, 1)

        # [5] 최종 전체 수직 레이아웃
        v_layout = QVBoxLayout()
        v_layout.addLayout(h_layout_1)
        v_layout.addLayout(h_layout_2)

        self.setLayout(v_layout)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 2-2) stretch 값을 버튼 3에 많이 주고 나머지는 작은 값을 주어 크기를 조절한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※&amp;nbsp; 버튼1이 가장 크기가 크고 나머지는 동일하다. 값을 수정해 주면 된다. 1,1,1,&amp;nbsp; ----&amp;gt; 1,1,&lt;span style=&quot;color: #ef5369;&quot;&gt;2&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-27 14-24-33.png&quot; data-origin-width=&quot;1095&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4zRO9/dJMb99T3KKj/lF4WNDSQdkGACRHVlpKlzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4zRO9/dJMb99T3KKj/lF4WNDSQdkGACRHVlpKlzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4zRO9/dJMb99T3KKj/lF4WNDSQdkGACRHVlpKlzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4zRO9%2FdJMb99T3KKj%2FlF4WNDSQdkGACRHVlpKlzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1095&quot; height=&quot;564&quot; data-filename=&quot;스크린샷 2026-05-27 14-24-33.png&quot; data-origin-width=&quot;1095&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779872427832&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        # [4] 레이아웃 설정 (비율)
        # 버튼3의 stretch 비율을 2로 하여 버튼1,2보다 2배 넓게 차지하도록 설정
        h_layout_2 = QHBoxLayout()
        h_layout_2.addWidget(button_1, 1)
        h_layout_2.addWidget(button_2, 1)
        h_layout_2.addWidget(button_3, 2)

        # [5] 전체 메인 레이아웃 구성
        v_layout = QVBoxLayout()
        v_layout.addLayout(h_layout_1)
        v_layout.addLayout(h_layout_2)
        
        self.setLayout(v_layout)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 2-3) 사이즈 정책에서 스트레치 값을 조정하여 크기 조절&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ line_edit를 한줄 더 추가해서 텍스트 입력창의 행을 늘려준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2026-05-27 14-30-35.png&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;782&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lKaEm/dJMcad3bmrA/fTIChVdMh90YYtnAPsez40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lKaEm/dJMcad3bmrA/fTIChVdMh90YYtnAPsez40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lKaEm/dJMcad3bmrA/fTIChVdMh90YYtnAPsez40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlKaEm%2FdJMcad3bmrA%2FfTIChVdMh90YYtnAPsez40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1027&quot; height=&quot;782&quot; data-filename=&quot;스크린샷 2026-05-27 14-30-35.png&quot; data-origin-width=&quot;1027&quot; data-origin-height=&quot;782&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779873605486&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 텍스트 입력창에 라인에디트 한줄을 더 추가하여 입력 행을 늘려 준다.
# [2] 첫 번째 가로 레이아웃 : 텍스트 + 입력창
        h_layout_1 = QHBoxLayout()
        h_layout_1.addWidget(label)
        h_layout_1.addWidget(line_edit)
        h_layout_1.addWidget(line_edit)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 2-4) 입력창 높이를 더 크게 늘리기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 복합 레이아웃 적용 : 텍스트 입력창 크기, 버튼 3번 크게 하기, 전체적인 창크기 고정 아닌 가능한 늘어나게 하기 (수정한 부분)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;입력창 높이를 더 크게 늘리기.png&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;711&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxcRXz/dJMcah5FFum/kZpqF3kzNqkI1kocDatZw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxcRXz/dJMcah5FFum/kZpqF3kzNqkI1kocDatZw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxcRXz/dJMcah5FFum/kZpqF3kzNqkI1kocDatZw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxcRXz%2FdJMcah5FFum%2FkZpqF3kzNqkI1kocDatZw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1031&quot; height=&quot;711&quot; data-filename=&quot;입력창 높이를 더 크게 늘리기.png&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;711&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779873782423&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        # 수정한 부분 / 로컬 변수 대신 self.line_edit로 선언 (인스턴스 변수화)
        self.input_field.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)


        # 가로 방향은 가능한 한 늘어나고(Expanding), 세로 방향은 고정(Fixed)
        line_edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        # 수정한 부분 [2] 첫 번째 가로 레이아웃 : 텍스트 + 입력창
        h_layout_1 = QHBoxLayout()
        h_layout_1.addWidget(label)
        h_layout_1.addWidget(line_edit)
        h_layout_1.addWidget(line_edit)

        # [3] 버튼 3개 생성
        button_1 = QPushButton(&quot;버튼1&quot;)
        button_2 = QPushButton(&quot;버튼2&quot;)
        button_3 = QPushButton(&quot;버튼3&quot;)

        # [4] 스트레치 설정
        # 버튼1은 stretch=2 &amp;rarr; 2배 넓은 공간 차지
        # 버튼2, 버튼3은 stretch=1 &amp;rarr; 동일 비율로 차지
        h_layout_2 = QHBoxLayout()
        h_layout_2.addWidget(button_1, 1)
        h_layout_2.addWidget(button_2, 1)
        h_layout_2.addWidget(button_3, 2)  # 수정한 부분&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 2-5) 라벨과 입력창 사이 간격을 추가하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 텍스트 입력창과 글자 입력창이 조화롭지 않게 보인다. 좀더 보기 좋은 화면을 위해서는 버튼3 크기와 텍스트 입력창 크기를 조절해 줘야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;라벨과 입력창 사이 간격 추가하기.png&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;711&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oCiFR/dJMcacDijIZ/jwI08a1KQkUrU0ndXd0Zi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oCiFR/dJMcacDijIZ/jwI08a1KQkUrU0ndXd0Zi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oCiFR/dJMcacDijIZ/jwI08a1KQkUrU0ndXd0Zi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoCiFR%2FdJMcacDijIZ%2FjwI08a1KQkUrU0ndXd0Zi1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1031&quot; height=&quot;711&quot; data-filename=&quot;라벨과 입력창 사이 간격 추가하기.png&quot; data-origin-width=&quot;1031&quot; data-origin-height=&quot;711&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(예제 2-6) &lt;b&gt;버튼을 클릭했을 때 QLineEdit 위젯에 입력한 값 터미널 화면에 출력하기&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;수정전 초기&amp;gt;&amp;nbsp;&lt;/b&gt; 문제점 : 코드 수정을 달리하여&amp;nbsp; main.py 화면창만 만들어 졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; self.setWindowTitle (&quot;위젯 크기 정책(SizePolicy)&quot;) 이 main.py가 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;레이아웃 터미널에 함수로 출력 기능 구현 초기.png&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yeQkA/dJMcahkjzJ4/kZSEhog5nx1gtuzLZ8YP71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yeQkA/dJMcahkjzJ4/kZSEhog5nx1gtuzLZ8YP71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yeQkA/dJMcahkjzJ4/kZSEhog5nx1gtuzLZ8YP71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyeQkA%2FdJMcahkjzJ4%2FkZSEhog5nx1gtuzLZ8YP71%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1046&quot; height=&quot;522&quot; data-filename=&quot;레이아웃 터미널에 함수로 출력 기능 구현 초기.png&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;lt;구문 수정 후&amp;gt; &lt;/b&gt;버튼을 클릭했을 때 QLineEdit 위젯에 입력한 값이 터미널 화면에 출력되도록 수정되었다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1779874879391&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    def init_ui(self):
        self.setWindowTitle(&quot;QLineEdit 입력값 출력&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XcsrL/dJMcad3bo2Z/f6pIFZ29QHiJh94NR5lu51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XcsrL/dJMcad3bo2Z/f6pIFZ29QHiJh94NR5lu51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XcsrL/dJMcad3bo2Z/f6pIFZ29QHiJh94NR5lu51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXcsrL%2FdJMcad3bo2Z%2Ff6pIFZ29QHiJh94NR5lu51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;865&quot; height=&quot;929&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779873837479&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from PySide6.QtWidgets import QWidget, QVBoxLayout, QLineEdit, QPushButton

class MyWidget(QWidget):

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle(&quot;QLineEdit 입력값 출력&quot;)
        self.resize(300, 150)
        # 레이아웃 생성
        layout = QVBoxLayout()
#### 버튼을 클릭했을 때 QLineEdit 위젯에 입력한 값 터미널화면에 출력하기
        # QLineEdit 생성
        self.input_line_edit = QLineEdit(self)
        self.input_line_edit.setPlaceholderText(&quot;텍스트를 입력하세요.&quot;)

        # QPushButton 생성
        self.print_btn = QPushButton(&quot;터미널에 출력&quot;, self)
        self.print_btn.clicked.connect(self.print_input_value)

        # 레이아웃에 위젯 추가
        layout.addWidget(self.input_line_edit)
        layout.addWidget(self.print_btn)
        self.setLayout(layout)

    def print_input_value(self):
        # QLineEdit 입력값 변수로 가져오는 방법
        input_data = self.input_line_edit.text().strip()

        # 터미널에 출력
        print(f&quot;입력된 값: {input_data}&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>학습 로그/Python3</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/48</guid>
      <comments>https://goodjop79.tistory.com/48#entry48comment</comments>
      <pubDate>Wed, 27 May 2026 18:43:27 +0900</pubDate>
    </item>
    <item>
      <title>D+34 [SQL] 프로그램 설치 및 환경 설정 가이드</title>
      <link>https://goodjop79.tistory.com/47</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ㅇ 일&amp;nbsp; 자 : 2026년 5월 26일(화)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Maria DB&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;MariaDB 서버는 가장 인기 있는 오픈 소스 관계형 데이터베이스 중 하나인데, MySQL의 초기 개발자들이 만들었으며, 앞으로도 오픈 소스로 유지될 것이 보장되어 있다. 클라우드 서비스에 포함되어 있으며, 대부분의 Linux 배포판에서 기본으로 제공된다.&lt;br /&gt;MariaDB는 성능, 안정성, 개방성이라는 가치를 기반으로 구축되었으며, MariaDB 재단은 기술적 우수성을 기준으로 기여를 수용할 것을 보장한다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;2. Mysql, MariaDB 실행 환경 설정&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1779795675284&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql&amp;gt; SELECT @golbal.time_zene, @session.time_zone;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;마리아1 스크린샷 2026-05-26 14-24-56.png&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n47VQ/dJMcafzZa8R/K8KRaak0iQjFVfmdATLwrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n47VQ/dJMcafzZa8R/K8KRaak0iQjFVfmdATLwrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n47VQ/dJMcafzZa8R/K8KRaak0iQjFVfmdATLwrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn47VQ%2FdJMcafzZa8R%2FK8KRaak0iQjFVfmdATLwrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;861&quot; height=&quot;220&quot; data-filename=&quot;마리아1 스크린샷 2026-05-26 14-24-56.png&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 시간대 설정 및 날짜 확인&lt;/p&gt;
&lt;pre id=&quot;code_1779795704755&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql&amp;gt; exit   // 나가기
:~$ sudo timedatectl set-timezone 'Asia/Seoul' //터미널에서 시간대 설정
:~$ date  // 날짜, 시간 출력
2026. 5. 26.(화) 14:00:20 [kkk]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 접속 실행 하기&lt;/p&gt;
&lt;pre id=&quot;code_1779795740708&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:~$ sudo mysql -u root  // 접속 실행 하기 
mysql&amp;gt; sudo systemctl restart mysqld
     &amp;gt; ET GLOBAL time_zone='+09:00';
mysql&amp;gt;SET time_zone='+09:00';&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;마리아2스크린샷 2026-05-26 14-43-24.png&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Xrint/dJMcafzZa9b/jvBlUPwIjKk6oN9kibGuvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Xrint/dJMcafzZa9b/jvBlUPwIjKk6oN9kibGuvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Xrint/dJMcafzZa9b/jvBlUPwIjKk6oN9kibGuvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXrint%2FdJMcafzZa9b%2FjvBlUPwIjKk6oN9kibGuvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;861&quot; height=&quot;331&quot; data-filename=&quot;마리아2스크린샷 2026-05-26 14-43-24.png&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;※ 터미널 창에서 입력시&lt;u&gt; :~$&amp;nbsp;&lt;/u&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;SQL루트에서 입력시&amp;nbsp; &lt;u&gt;mysql&amp;gt;&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 1.&amp;nbsp; MariaDB 외부 접속 허용, 방화벽 허용&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1779796155535&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:~$ sudo vi /etc/mysql/mariadb.conf.d/50-server.cnf // 외부 접속 허용
:~$ GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '패스워드'; // 모든 ip 허용
:~$ GRANT ALL PRIVILEGES ON *.* TO 'root'@'172.10.0.%' IDENTIFIED BY '패스워드';  // 특정대역대 ip 허용
:~$ GRANT ALL PRIVILEGES ON *.* TO 'root'@'172.10.0.254' IDENTIFIED BY '패스워드'; // 특정 ip 허용
:~$ DELETE FROM mysql.user WHERE Host='%' AND User='아이디'; // ip 허용상태 원복
:~$ FLUSH PRIVILEGES;             // ip 상태 적용하기
:~$ firewall-cmd --list-all-zones // 방화벽 설정 확인
:~$ firewall-cmd --permanent --zone=public --add-port=3306/tcp // 방화벽 허용 설정&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;2. 2. Timezone 설정 하기&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1779796246904&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:~$ sudo mysql -u root -p   // 루트 접속
mysql&amp;gt; SELECT @@global.time_zone, @@session.time_zone;  // 접속 시간대 확인
mysql&amp;gt; exit  // 종료 나가기
:~$ sudo timedatectl set-timezone 'Asia/Seoul'  // 아시아 서울 시간대 설정하기
:~$ date   // 설정한 결과 출력하기
:~$ sudo mysql -u root -p  // sql 루트 변경    
mysql&amp;gt; sudo systemctl restart mysqld  // sql에서 시간대 설정
mysql&amp;gt; SET GLOBAL time_zone='+09:00';  // 09시 표준시간대 설정
     &amp;gt; SET time_zone='+09:00';
     &amp;gt; ctrl + c  // 입력 줄 나가기 
mysql&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;2. 3. MariaDB, root 비밀번호 재설정&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1779796262183&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;mysql&amp;gt; update user set plugin='' where User='root';
mysql&amp;gt; set password = password('비번입력');
mysql&amp;gt; flush privileges;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 4. MariaDB, C 컴파일 테스트&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp; * MariaDB 공식 홈페이지&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;*&amp;nbsp;C++&amp;nbsp;Programs&amp;nbsp;to&amp;nbsp;MariaDB&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;*&amp;nbsp;C++&amp;nbsp;헤더&amp;nbsp;파일&amp;nbsp;다운&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;*&amp;nbsp;CPP&amp;nbsp;test&amp;nbsp;파일&amp;nbsp;git&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1779796301024&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# mysql -h는  MySQL서버에 접속할 때, 원격 호스트(IP 주소 또는 도메인)를 지정하는 명령어 옵션, 주로 로컬이 아닌 원격 서버의 데이터베이스에 접근할 때 사용함
:~$ sudo apt install libmysqlclient-dev -y  // mysql.h 없을 경우 다운로드 해서 설치한다.
:~$ mysql_config --cflags                  // mysql.h의 위치 찾기    
:~$ #include &quot;/usr/include/mysql/mysql.h&quot;  // mysql.h 경로로 추가하기&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 5. MariaDB Timezone 비밀번호 재설정&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1779796354864&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo mysql
mysql&amp;gt; update user set plugin='' where User='root';
mysql&amp;gt; set password = password('비번입력');
mysql&amp;gt; flush privileges;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 6. MariaDB, C 컴파일 테스트&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp; &amp;nbsp; * MariaDB 공식 홈페이지 :&amp;nbsp;&lt;a href=&quot;https://mariadb.org/download/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://mariadb.org/download/&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;C++&amp;nbsp;Programs&amp;nbsp;to&amp;nbsp;MariaDB&amp;nbsp;:&amp;nbsp;링크&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;C++&amp;nbsp;헤더&amp;nbsp;파일&amp;nbsp;다운&amp;nbsp;:&amp;nbsp;링크&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*&amp;nbsp;CPP&amp;nbsp;test&amp;nbsp;파일&amp;nbsp;git&amp;nbsp;:&amp;nbsp;링크&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 후&amp;nbsp; 기&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;Maria DB를 활용한 오픈소스 공동개발자(Frank Karlitscheck. Nextcloud) 대화 영상시청 내용 :&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;- 오픈소스 = 디지털 주도권 이다.&lt;br /&gt;- 오픈소스 커뮤티티에는 넥스트 클라우드, 마리아db처럼 고객과 직원, 개발자를 보유하고 오픈 소스 s/w 개발에&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp; 도움 주고, 독점 클라우드 서비스에 의존하고 있는 현실에서 오픈소스는 개발자들에게 유용하게 사용되기도 한다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;그러나&amp;nbsp; SQL은 수많은 빅데이터를 관리, 분석, 활용하는 만큼 안정성과 팩트 경향성 등이 중요하다. 몇가지 간단한 문법들을 공부하면서 데이터를 분석해서 결과값을 가지고 각종 정책 반영 및 아이디어 제공 등에 활용된다. 공공데이터 개방을 잘 활용하는 것도 그것이다. &quot;도전은 계속된다.&quot;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>환경 설정</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/47</guid>
      <comments>https://goodjop79.tistory.com/47#entry47comment</comments>
      <pubDate>Tue, 26 May 2026 21:01:12 +0900</pubDate>
    </item>
    <item>
      <title>D+34 [아두이노] Aduino '전자키보드 만들기' 실습</title>
      <link>https://goodjop79.tistory.com/46</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ㅇ 일&amp;nbsp; 자 : 2026년 5월 26일(화)&lt;/b&gt;&lt;/h4&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 아두이노 환경에서 전자키보드를 만드는 보드와 회로 연결하기&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1761&quot; data-origin-height=&quot;925&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xj9YN/dJMcah5EUwM/z1d6pYqxzrnKPK3d84Vwr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xj9YN/dJMcah5EUwM/z1d6pYqxzrnKPK3d84Vwr1/img.png&quot; data-alt=&quot;아두이노 회로와 코드 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xj9YN/dJMcah5EUwM/z1d6pYqxzrnKPK3d84Vwr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxj9YN%2FdJMcah5EUwM%2Fz1d6pYqxzrnKPK3d84Vwr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1761&quot; height=&quot;925&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1761&quot; data-origin-height=&quot;925&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아두이노 회로와 코드 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1779792460482&quot; class=&quot;bash&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// 예제 [전자 키보드 만들기] 365p

const int melody[] = {   // 음계별 주파수를 저장한 변수 선언
  262,     // 도 주파수
  294,     // 레 주파수
  330,     // 미 주파수
  349,     // 파 주파수
  392,     // 솔 주파수
  440,     // 라 주파수
  494,     // 시 주파수
  523,     // 도 주파수
};

const int PIEZO_PIN = 13;  // 피에조(검은색 원형 볼륨모양) 스피커에 연결된 디지털 핀번호 

void setup() {

  for (int i=6; i&amp;lt;=13; i++) {    // 디지털 버튼 6-13번 핀
    pinMode(i, INPUT);           // 디지털 핀을 입력 모드로 설정     
  }
  
  Serial.begin(9600);  // 직렬 통신 초기화
}

void loop() {      

  int index0fMelody = readNote();     // 누름 버튼을 구분해서 음계 선택
  
  if (index0fMelody &amp;gt; -1)    
    tone(PIEZO_PIN, melody[index0fMelody], 200);  // 선택된 음계를 200ms 동안 재생
    
  delay(50);   // 버튼 누른 시간 고려 일정시간 지연시킨다.
}

int readNote() {     // 누른 버튼에 따라 melody 배열의 인덱스값을 반환하는 함수
  int index = -1;    //인덱스 초기값

for (int i=6; i&amp;lt;=13; i++) {          // 디지털 버튼 6번-13번 
  int buttonValue = digitalRead(i);  // 버튼의 입력값 읽기 반복
  if (buttonValue == HIGH)           // 버튼을 누르면
    index = i-6;                     // melody의 인덱스값 계산 
}
Serial.println(index);               // 직렬 모니터에 인덱스값 출력
return index;                        // 인덱스값 반환
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;기술의 발전&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전자피아노를 예로 들면 피아노에 기본적인 음악 사운드를 저장해 놓고 건반으로 입력하여 연주를 하기도 한다.&amp;nbsp;전자키보드는 시그널을 보내 소스코드 값을 지정한데로 출력하고, 키보드를 눌러 소리를 낸다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년에는 국내 최초로 AI 작곡가(이봄)를 개발하여 배틀에 음악들을 사용했다.&amp;nbsp;빅데이터가 필요한 기존 생성형 AI와는 다른 기술이 적용됐다. 즉 개발자 안 소장이 연구 중인 &amp;lsquo;합성형 AI&amp;rsquo; 기술이 활용됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는&amp;nbsp; &amp;rdquo;기존 생성형 AI처럼 데이터만 넣고 끝나는 게 아니라 데이터 사용은 최소화하고 이론적인 지식들을 함께 믹스하는 방식&amp;ldquo;이다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #020817; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이봄은 음악 콘텐츠만 대량으로 학습하는 게 아니라 음악 이론을 기초로 음을 익히고, 코드를 학습한 뒤 작곡과 연주를 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #020817; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;전문가 지식과 노하우를 접목했기 때문에 일반 생성형 AI처럼 많은 데이터가 필요하지 않다. 데이터 사용을 최소화해 에너지 소모를 줄이고 노트북으로도 구동이 가능하다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #020817; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문자를 만들고 도시 문명을 이루고 수학과 과학 지식을 발견한 인류는 21세기 들어 '로봇자동화'를 통한 스마트 제조, 초고속 무선 인터넷 통신 등 최첨단 기술을 개발했다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #020817; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아두이노는 이러한 첨단기술에 앞서 어떠한 기계와 프로그램간 연동을 통해 더 낳은 기술에 적용하고 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 프로그램을 개발 하는 구성원&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;프로그램을 개발하는데는 다양한 구성원이 함께 하여 하나의 프로젝트가 완성된다. 이처럼 다양한 직위에 구성원들이 있기에 개발자가 아니더라도 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;프로그램 '기획'에 대해 이끌어 가는 기획자도 고민해 볼 만 하다. 책과 &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;전공지식 등 개인이 공부 것에 대한 카테고리에 따라 어떤 프로그램을 개발해 볼수 있을까 기획을 해볼 수도 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;b&gt;&lt;span data-subtree=&quot;aimfl&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;프로그램을 개발하는 팀은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;기획, 디자인, 개발, 관리, 품질 보증 등 다양한 역할을 가진 전문가들로 구성&lt;/b&gt;&lt;/p&gt;
&lt;div data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgHEAA&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 1. 관리 및 기획 (Management &amp;amp; Planning)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgPEAA&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;PM (Project Manager / 제품 관리자)&lt;/b&gt;: 프로젝트의 전체 일정, 예산, 리소스를 관리하며 팀 간의 의견을 조율&lt;/span&gt;&lt;/li&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgPEAE&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;PO (Product Owner / 제품 책임자)&lt;/b&gt;: 제품의 비전과 요구사항을 정의하고, 개발할 기능의 우선순위를 결정&lt;/span&gt;&lt;/li&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgPEAI&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;기획자 (Product Designer / Planner)&lt;/b&gt;: 사용자 요구사항을 분석하여 프로그램의 구조와 상세 기능 흐름을 설계&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-animation-nesting=&quot;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 2. 디자인 (Design)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgSEAA&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;UI/UX 디자이너&lt;/b&gt;: 사용자가 프로그램을 편리하고 아름답게 사용할 수 있도록 화면 구성(UI)과 사용자 경험(UX)을 디자인함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-animation-nesting=&quot;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 3. 개발 (Engineering)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgWEAA&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;PL (Project Leader / 개발 리더)&lt;/b&gt;: 개발 파트의 리더로서 기술적인 설계를 책임지고 개발자들을 가이드 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgWEAE&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;프론트엔드 개발자 (Frontend Engineer)&lt;/b&gt;: 사용자가 직접 눈으로 보고 조작하는 웹사이트나 앱의 화면을 개발 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgWEAI&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;백엔드 개발자 (Backend Engineer)&lt;/b&gt;: 눈에 보이지 않는 서버, 데이터베이스, API를 구축하고 데이터 로직을 처리 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgWEAM&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;풀스택 개발자 (Full-Stack Engineer)&lt;/b&gt;: 프론트엔드와 백엔드 개발을 모두 수행할 수 있는 개발자&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-animation-nesting=&quot;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;2. 4. 품질 및 운영 (QA &amp;amp; DevOps)&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgbEAA&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;QA 엔지니어 / 테스터 (Quality Assurance)&lt;/b&gt;: 완성된 프로그램에 오류가 없는지 테스트, 품질 표준을 만족하는지 검증&lt;/span&gt;&lt;/li&gt;
&lt;li data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-hveid=&quot;CAIIAAgbEAE&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;span data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;&lt;b&gt;데브옵스 엔지니어 (DevOps / Infra)&lt;/b&gt;: 개발된 프로그램이 서버에 안정적으로 배포, 원활하게 운영되도록 시스템 인프라 관리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 후 기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아두이노는 좁은 범위에서부터 큰 범위에 이르기까지 전기전자 및 컴퓨터 공학을 두루 어루러지게 하는 학습이다. 일상생활에서 사용하는 모든 기계와 관련된 용품들이 그렇다. 우리는 편리하게 사용하는 전자제품과 기계 설비 들이 모두 백그라운드에서 상호 연동되어 실시간 프로그램으로 가동되는 것을 알고 있는 사실이다. 그렇다면 좀더 편하고 좀더 저렴하고, 좀더 빠르게 구동할 수 있는 개발 방식은 어떤 것들이 있는지에 대한 의문이 생긴다. 과학의 발전은 호기심에서 시작된다는 말이 있듯이 모든 개발은 호기심과 관심에서 시작된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로그램을 개발하는 데는 많든 구성원들이 한팀이 되어 움직이듯 관리, 기획, 디자인, 개발 등 세분화 되어 다양한 업무를 분담하게 된다. 전혀 다른 분야에 새로운 도전은 호기심이 많은 분야이다. 앞으로&amp;nbsp; &quot;도전은 계속된다.&quot;&lt;/p&gt;</description>
      <category>학습 로그/Aduino</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/46</guid>
      <comments>https://goodjop79.tistory.com/46#entry46comment</comments>
      <pubDate>Tue, 26 May 2026 20:39:24 +0900</pubDate>
    </item>
    <item>
      <title>D+33 [SQL]  빅쿼리(BigQuery)가 뭐야?</title>
      <link>https://goodjop79.tistory.com/45</link>
      <description>&lt;p data-path-to-node=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;ㅇ 일 자 : 2026년 5월 22일(금)&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-path-to-node=&quot;0&quot; data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;빅쿼리(BigQuery)란?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;구글 클라우드 플랫폼(GCP)의 가장 강력한 무기이자, &lt;br /&gt;데이터 엔지니어링과 분석 분야에서 업계 표준으로 자리 잡은 빅쿼리(BigQuery)&lt;br /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;009&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/axz_keditor/emoticon/friends1/large/009.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/axz_keditor/emoticon/friends1/large/009.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;h4 data-path-to-node=&quot;2&quot; data-ke-size=&quot;size20&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;빅쿼리(BigQuery)란?&lt;/h4&gt;
&lt;p data-path-to-node=&quot;3&quot; data-ke-size=&quot;size16&quot;&gt;구글이 내부에서 엄청난 양의 로그 데이터를 처리하기 위해 쓰던 '드레멜(Dremel)'이라는 기술을 외부 사용자들이 쓸 수 있게 상용화한 &lt;b data-index-in-node=&quot;77&quot; data-path-to-node=&quot;3&quot;&gt;초고속&amp;middot;대용량 데이터 웨어하우스(Data Warehouse)&lt;/b&gt; 서비스 이다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;쉽게 말해, &quot;엄청나게 거대한 엑셀 파일들을 모아두고, 아무리 양이 많아도 눈 깜짝할 사이에 원하는 데이터를 찾아주는 창고&quot;&lt;/p&gt;
&lt;p data-path-to-node=&quot;4&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;6&quot; data-ke-size=&quot;size20&quot;&gt;2. 빅쿼리의 압도적인 강점 3가지&lt;/h4&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size18&quot;&gt;1) 서버리스 (Serverless) &amp;mdash; &quot;서버 관리가 필요 없다&quot;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;일반적인 데이터베이스는 데이터가 늘어나면 서버의 컴퓨터 사양을 업그레이드(Scale-up)하거나 서버 대수를 늘리는(Scale-out) 복잡한 엔지니어링 작업이 필요한데 빅쿼리는 서버관리가 필요 없다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빅쿼리는 사용자가 서버를 전혀 신경 쓸 필요가 없다. 구글이 알아서 수천 대의 컴퓨터를 동원해 연산을 처리하므로, 사용자는 오직 데이터와 쿼리문(SQL)에만 집중하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size18&quot;&gt;2) 상상을 초월하는 속도 (테라바이트를 몇 초 만에)&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;일반 데이터베이스에 수십억 건의 데이터(테라바이트 단위를 넘어 페타바이트 단위)를 넣고 검색하면 서버가 멈추거나 몇 시간이 걸린다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빅쿼리는 데이터를 &lt;b data-index-in-node=&quot;10&quot; data-path-to-node=&quot;12,0,0&quot;&gt;컬럼(Column, 열) 기반&lt;/b&gt;으로 저장하고, 수천 대의 구글 서버가 동시에 나누어 계산(분산 컴퓨팅)하기 때문에, &lt;b data-index-in-node=&quot;73&quot; data-path-to-node=&quot;12,0,0&quot;&gt;수십억 건의 데이터도 단 몇 초 만에&lt;/b&gt; 분석해 낸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;13&quot; data-ke-size=&quot;size18&quot;&gt;3) 친숙한 표준 SQL 지원&lt;/p&gt;
&lt;p data-path-to-node=&quot;14&quot; data-ke-size=&quot;size16&quot;&gt;아무리 혁신적인 기술이라도 사용법이 어려우면 쓸 수 없겠죠. 빅쿼리는 개발자나 데이터 분석가들이 기존에 쓰던 표준 SQL(데이터베이스 조회 언어)을 그대로 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;15&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SELECT * FROM 테이블 WHERE 조건 같은 &lt;b&gt;기본 문법&lt;/b&gt;만 알면 누구나 이 엄청난 성능을 바로 활용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-path-to-node=&quot;17&quot; data-ke-size=&quot;size20&quot;&gt;3. 비용 산정 방식 (⚠️ 주의할 점)&lt;/h4&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;빅쿼리는 서버를 켜놓은 시간에 돈을 받지 않고, &quot;내가 쿼리를 날려서 스캔한 데이터의 양&quot;에 따라 비용을 청구한다. (기본적으로 매달 1TB의 쿼리 스캔은 무료로 제공된다.)&lt;/p&gt;
&lt;p data-path-to-node=&quot;18&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666; letter-spacing: 0px; font-family: 'Noto Serif KR', serif; text-align: center;&quot;&gt;  &lt;/span&gt;&lt;b data-index-in-node=&quot;3&quot; data-path-to-node=&quot;19,0&quot;&gt;실무 팁:&lt;/b&gt;&lt;span style=&quot;color: #666666; letter-spacing: 0px; font-family: 'Noto Serif KR', serif; text-align: center;&quot;&gt; 만약 100TB짜리 데이터 정렬창고에서 SELECT * (모든 데이터 다 가져와)를 무심코 실행하면 순식간에 수십만 원의 비용이 청구될 수 있다. 그래서 &lt;u&gt;실무에서는 필요한 열(Column)만 콕 집어서 조회하는 습관&lt;/u&gt;이 필수적임&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size20&quot;&gt;4. 리눅스 / 개발자 과정과의 연결고리&lt;/h4&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b data-index-in-node=&quot;10&quot; data-path-to-node=&quot;22&quot;&gt;리눅스 환경&lt;/b&gt;이나 &lt;b data-index-in-node=&quot;19&quot; data-path-to-node=&quot;22&quot;&gt;파이썬(PyCharm)&lt;/b&gt; 코드에서 &quot;빅쿼리 라이브러리&quot;를 설치하면, 서버에서 발생하는 수많은 로그 데이터를 빅쿼리로 바로 쏘아 보낼 수 있다. 그렇게 쌓인 빅데이터를 빅쿼리로 분석하고, 그 결과를 바탕으로 머신러닝(AI) 모델을 돌리는 것이 현대 백엔드 / 데이터 개발의 표준적인 흐름이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-path-to-node=&quot;22&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;5. 기&amp;nbsp; 타&lt;/b&gt;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;SQL 기본문법을 통해 데이터를 분석해 내는 인공지능 기능을 사용함에 있어서&amp;nbsp; 관련된 데이타 제공에 대한 보안성의 문제는 간과해서는 안될 문제라고 생각한다. 일반적인 빅데이터 분석에 빅쿼리를 활용하는 것은 기업체에서 머신러닝을 어떤 방법으로 활용하는지도 연계해서 생각해 봐야 한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;어차피 데이터 자동분석도 비용과 연관되어 있는 문제로서 기업 입장에서는 무조건 도입해서 사용하기에는 부담스러울 수도 있다. 그러나 빅데이터 분석이 아주 빈번한 곳에서 3인이 분석하던 것을 빅쿼리 하나가 하고 있다면 기업에서는 도입하지 않을 이유가 없다고 생각한다. 하루가 빠르게 변하고 있는 AI 시대에 빅데이터 분석에 대한 생각을 다시한번 하게 된다. 그러나 기본에 충실하는 &quot;도전은 계속된다.&quot;&lt;/p&gt;</description>
      <category>인공지능 AI</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/45</guid>
      <comments>https://goodjop79.tistory.com/45#entry45comment</comments>
      <pubDate>Tue, 26 May 2026 07:00:43 +0900</pubDate>
    </item>
    <item>
      <title>D+33 [PySide6] 핵심 프레임워크는 무엇 일까?</title>
      <link>https://goodjop79.tistory.com/44</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ㅇ 일 자 : 2026년 5월 22일(금)&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; PySide6 핵심 프레임워크의 방대한 내용을 한눈에 파악하고 구조적으로 이해할 수 있도록 정리 했다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. PySide6 핵심 아키텍처 및 UI 컴포넌트&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1.1. PySide6 핵심 아키텍처 &amp;amp; GUI 기본 구조&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BCRA7/dJMcaii8XzM/wLGVKxPeEFc91Y9RtGEkpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BCRA7/dJMcaii8XzM/wLGVKxPeEFc91Y9RtGEkpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BCRA7/dJMcaii8XzM/wLGVKxPeEFc91Y9RtGEkpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBCRA7%2FdJMcaii8XzM%2FwLGVKxPeEFc91Y9RtGEkpK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1408&quot; height=&quot;768&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QApplication:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 전체 앱의 생명 주기와 사용자 입력(마우스, 키보드) 등 모든 이벤트를 관리하는 최상위 엔진&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QMainWindow:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 메뉴바, 툴바, 상태바를 기본으로 포함하는 완성형 메인 윈도우 구조틀&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QWidget:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 화면에 표시되는 모든 UI 구성요소(위젯)의 최상위 부모 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QAction:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 메뉴나 툴바 아이템처럼 사용자의 '명령 행동'을 추상화하여 관리하는 객체&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Signal &amp;amp; Slot (이벤트 처리 구조)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PySide6에서 컴포넌트 간 데이터를 주고받고 이벤트를 처리하는 핵심 소통 방식&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Signal (신호):&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 위젯에 이벤트(클릭, 값 변경 등)가 발생했을 때 외부에 알리는 발생 장치&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Slot (슬롯):&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Signal을 전달받아 실제 비즈니스 로직을 수행하는 연결된 함수(Function)&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Signal &amp;amp; Slot 처리 구조&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNN2hq/dJMcabK9wyE/bnOZfzMiLKi2FbQaAHsy40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNN2hq/dJMcabK9wyE/bnOZfzMiLKi2FbQaAHsy40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNN2hq/dJMcabK9wyE/bnOZfzMiLKi2FbQaAHsy40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNN2hq%2FdJMcabK9wyE%2FbnOZfzMiLKi2FbQaAHsy40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1408&quot; height=&quot;768&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 레이아웃 매니저 (Layout Managers)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;화면 크기가 변하더라도 위젯들을 절대 좌표가 아닌, 수학적&amp;middot;구조적 규칙에 따라 자동 배치하는 도구&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;레이아웃 클래스&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;배치 방식 및 특징&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주요 활용 예시&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QVBoxLayout&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위젯을 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;세로(Vertical)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 방향으로 일렬 배치&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메인 메뉴, 입력 폼 세로 정렬&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QHBoxLayout&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위젯을 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가로(Horizontal)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 방향으로 일렬 배치&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하단 확인/취소 버튼 바&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QGridLayout&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;행(Row)과 열(Column)의 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;바둑판 표&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 형태로 배치&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계산기 키패드, 대시보드&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QFormLayout&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;왼쪽에 레이블, 오른쪽에 입력창을 갖는 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2열 구조&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로그인 화면, 회원가입 양식&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중첩 레이아웃:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 레이아웃 안에 또 다른 레이아웃을 넣어 복잡한 화면을 설계하는 방식&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Stretch &amp;amp; Spacing:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;stretch&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;는 위젯 간의 확장 비율을, &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;spacing&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;은 위젯 사이의 간격(여백)을 조정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 카테고리별 핵심 위젯 (Widgets) 요약&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;① 기본 입력 위젯 (Input Widgets)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QLineEdit:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 단일 행 텍스트 입력창 (ID, 비밀번호 등).&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QTextEdit:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 여러 줄 문장 입력 및 서식(Rich Text) 지원 창 (본문 작성).&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QCheckBox / QRadioButton:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 다중 선택 체크박스 및 택일형 라디오 버튼.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QComboBox:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 공간을 절약하는 드롭다운 선택 상자.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QSpinBox / QDoubleSpinBox:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 각각 정수 및 실수를 화살표나 타이핑으로 입력받는 창.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QDateEdit / QTimeEdit:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 날짜 및 시간 선택 위젯.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;② 표시 및 상태 위젯 (Display Widgets)&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QLabel:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 화면에 텍스트, 이미지(&lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;QPixmap&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;), 스타일을 표현하는 출력 위젯.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QProgressBar:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 작업 진행 상태(%)를 시각적으로 보여주는 바.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QLCDNumber:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 디지털시계처럼 숫자만 LCD 형태로 크게 표시하는 위젯.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 고급 기능 및 데이터 프레임워크&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.1. 컨테이너 및 대화상자 (Containers &amp;amp; Dialogs)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위젯들을 묶어서 화면을 효율적으로 분할하거나, 별도의 팝업 창을 띄워 소통하는 구조&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;① 컨테이너 위젯 (화면 공간 관리)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QGroupBox:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 연관된 위젯들을 그룹 테두리로 묶고 제목을 붙여 시각적 분류 제공.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QTabWidget:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 상단 탭을 눌러 한 공간에서 여러 페이지를 전환하며 보기.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QStackedWidget:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 탭 없이 코드 제어를 통해 화면 전체를 통째로 전환 (페이지 넘기기)&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QScrollArea:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 컨텐츠가 화면보다 클 때 스크롤바를 자동 생성.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QSplitter:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 사용자가 마우스로 경계선을 끌어서 좌우/상하 영역 크기를 조절하는 분할&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;② 표준 다이얼로그 (Standard Dialogs)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QMessageBox:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 경고, 알림, 예/아니오 확인 등 단순 팝업 메시지 창.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QFileDialog:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 운영체제 표준 파일 열기 / 저장 창.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QColorDialog / QFontDialog:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 색상 피커 및 폰트 변경 표준 창.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QInputDialog:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 사용자에게 간단한 한 줄 텍스트나 숫자를 즉시 입력받는 팝업.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;6. 데이터 표시 프레임워크: Widget형 vs Model/View형&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Widget 방식 (QListWidget, QTableWidget, QTreeWidget):&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 데이터와 화면 컴포넌트가 결합하여 코드가 직관적이고 다루기 쉬우나, 데이터가 아주 많아지면 무거워집니다.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Model/View 방식 (QListView, QTableView, QTreeView):&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 데이터 모델(&lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;Model&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)과 화면 출력(&lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;View&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)을 철저히 분리합니다. 수만 개 이상의 대용량 데이터를 처리하거나 실시간 필터링(&lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;QSortFilterProxyModel&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)을 구현할 때 매우 효율적입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필터 정렬 (Filter / Sort) : QSortFilter Proxy Model&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPCdUX/dJMcabK9wzx/d1Bmxqe7omaj1VKGwI6le1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPCdUX/dJMcabK9wzx/d1Bmxqe7omaj1VKGwI6le1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPCdUX/dJMcabK9wzx/d1Bmxqe7omaj1VKGwI6le1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPCdUX%2FdJMcabK9wzx%2Fd1Bmxqe7omaj1VKGwI6le1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1408&quot; height=&quot;768&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;7. 스타일링 및 성능 최적화 (Styling &amp;amp; Threads)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;① UI 디자인 (Style)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;setStyleSheet():&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 웹의 CSS와 유사한 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QSS(Qt Style Sheets)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 문법을 사용하여 위젯의 배경색, 테두리, 둥글기, 폰트 등을 자유롭게 꾸밀 수 있습니다. 애플리케이션 전체에 일괄 적용하여 다크 모드 등을 쉽게 구현합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;② 백그라운드 처리 (Performance)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QTimer:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 대기 상태 없이 일정 주기(ms 단위)마다 특정 Slot 함수를 반복 실행합니다. (디지털시계, 카운트다운 등에 필수).&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: disc; color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QThread &amp;amp; Worker 구조:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 대용량 파일 읽기나 네트워크 다운로드처럼 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오래 걸리는 작업&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 메인 GUI 스레드와 분리하여 백그라운드에서 실행합니다. 만약 분리하지 않으면 화면이 얼어붙는(먹통) 현상이 발생합니다. 작업 완료 후 &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;Signal/Slot&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 통해 안전하게 GUI에 결과값이나 진행률을 전달합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;8. 개발 생산성 및 프로젝트 구조화&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현업 수준의 유지보수 가능한 애플리케이션 개발을 위한 관리 기법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;① Qt Designer 도구 체인&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Qt Designer:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 마우스 드래그 앤 드롭으로 UI 화면을 배치하고 &lt;/span&gt;.ui&lt;span style=&quot;color: #000000;&quot;&gt; 파일로 저장하는 시각적 저작 도구.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pyside6-uic:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 터미널 명령어를 통해 &lt;/span&gt;.ui&lt;span style=&quot;color: #000000;&quot;&gt; 파일의 XML 구조를 Python 코드(&lt;/span&gt;.py&lt;span style=&quot;color: #000000;&quot;&gt;)로 자동 변환하는 컴파일러.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;objectName:&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 개발자가 Designer에서 지정한 위젯 고유의 이름으로, 파이썬 코드에서 &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;self.ui.objectName&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 형태로 접근하여 로직을 연결&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;② 이상적인 프로젝트 폴더 구조 (구조화)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단일 파일 코딩의 한계를 극복하고, 파일별 역할을 분리하여 협업과 유지보수를 극대화&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;my_project/ &lt;/b&gt;&lt;br /&gt;&lt;b&gt;├──&amp;nbsp;main.py&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;앱&amp;nbsp;실행&amp;nbsp;및&amp;nbsp;QApplication&amp;nbsp;초기화&amp;nbsp;담당 &lt;/b&gt;&lt;br /&gt;&lt;b&gt;├──&amp;nbsp;widget.py&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;비즈니스&amp;nbsp;로직&amp;nbsp;및&amp;nbsp;이벤트(Slot)&amp;nbsp;바인딩&amp;nbsp;수행 &lt;/b&gt;&lt;br /&gt;&lt;b&gt;├──&amp;nbsp;ui_form.py&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;Qt&amp;nbsp;Designer에서&amp;nbsp;변환된&amp;nbsp;UI&amp;nbsp;클래스&amp;nbsp;파일&amp;nbsp;(.py) &lt;/b&gt;&lt;br /&gt;&lt;b&gt;├──&amp;nbsp;config.json&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;창&amp;nbsp;크기,&amp;nbsp;테마&amp;nbsp;등&amp;nbsp;환경&amp;nbsp;설정&amp;nbsp;데이터 &lt;/b&gt;&lt;br /&gt;&lt;b&gt;└──&amp;nbsp;resources/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;아이콘,&amp;nbsp;이미지,&amp;nbsp;QSS&amp;nbsp;스타일시트&amp;nbsp;등&amp;nbsp;리소스&amp;nbsp;폴더&lt;/b&gt;&lt;/p&gt;</description>
      <category>IT 컴퓨터</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/44</guid>
      <comments>https://goodjop79.tistory.com/44#entry44comment</comments>
      <pubDate>Tue, 26 May 2026 01:16:32 +0900</pubDate>
    </item>
    <item>
      <title>D+32 [Qt for Python]  Designer 적용 구조 및 Layout 이해</title>
      <link>https://goodjop79.tistory.com/43</link>
      <description>&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ㅇ 주 제 : 프로그램 및 문서의 전체 흐름 이해 (Layout)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ㅇ 목 표 :&amp;nbsp; &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;1. GUI 프로그램 화면 전체의 구조를 설계하는 방법을 이해한다.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;2. PySide6 환경에서 Designer 적용구조 및 Layout 을 활용한다.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ㅇ 내 용&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 전체 흐름 이해하기&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;가. 각종 회의록&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 요약해서 저장하는 경우&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (예) Slack -----&amp;gt;&amp;nbsp; GPT Wrokspace&amp;nbsp; ------&amp;gt;&amp;nbsp; Google Drive&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;uarr; 협업툴&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;uarr; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Github&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;나. 환경설정은 각 기업체의 특성과 이익과 연계되는 한 해결이 다소 어렵다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각각의 프로그램이 연동되는지가 관건 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;---&amp;gt; 프로그램간 연동을 가능케 하는 버젼의 드라이버를 별도로 설치해야 하는 번거로움&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- &amp;gt;&amp;gt; 발전방향 :&amp;nbsp; 모든과정의 자동화&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 시대적 흐름의 변화에 적응하는 자세&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;가. 스스로 노력하고 교육 내용을 이해 하지 않으면 발전이 없다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;나. 인공지능 서버는 편하지만 편한 것만 사용하면서 현실에 안주해서는 안된다. 무언가 발전을 위해 노력을 해야만 한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;다. AI가 프롬프트에 의해 코드생성은 해 주지만 본인이 알고 이해할 수 있어야 한다.&amp;nbsp; 직접 작성을 해보고 고민해 봐야 한다.&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. PySide6 환경에서 Layout&amp;nbsp; 이해 &amp;nbsp; &amp;nbsp;&lt;/b&gt;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3.1. 레이아웃 (배치, 구성, 배열 방식)&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;가.&amp;nbsp; 어디에, 어떤 크기로, 어떤 순서로 배치할 것인가?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;나. GUI 프로그램 : 버튼, 라벨, 입력창 같은 위젯을 화면에 조화롭게 배치한다&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;다. Qt 레이아웃 시스템 : 프로그램 부모위젯 안에서 자식 위젯 들의 위치, 크기를 자동관리 해주는 구조 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (직접 좌표로 배치하는 방식이 아니라, 위젯 위치/크기를 &quot;자동&quot;관리)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;라. 레이아웃은 창 크기 변화에 맞춰 화면을 자동 정리 해주는 역할&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(예) 아이디 입력창, 비밀번호 입력창, 로그인 버튼, 기타 안내문구 등&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;마.&amp;nbsp; 창의 바탕화면(=부모 위젯),&amp;nbsp; 바탕에 버튼, 라벨, 입력창, 문구 등(=자식 위젯)&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;b&gt;3.2. 레이아웃 종류&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- QVBoxLayout : 세로 배치형&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- QHBoxLayout : 가로 배치형&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- QGridLayotut : 표 형태&amp;nbsp; (계산기 버튼과 같이 규칙적인 표 구조에 유용)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- QFormLayout : 라벨 + 입력폼 (회원가입, 로그인, 설정화면 등 입력창 구조 적합)&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;b&gt;3.3. 레이아웃 중첩과 공간 제어&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp; 중첩&amp;nbsp; :&amp;nbsp; 복잡한 GUI화면에서 레이아웃 안에 또다른 레이아웃을 포함시키는 중첩 방식 사용&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (예) 전체화면 세로방향(QVBoxLayout),&amp;nbsp; 버튼 묶음들은 가로방향(QHBoxLayout )&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- 공간 제어&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Stretch Facto : 위젯 간 공간비율 조절 ( 1:2:1 공간 배분)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SpacerIteam : 빈 공간을 늘어나게 함&amp;nbsp; (버튼 사이 간격 벌이기)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SizePolicy : 위젯의 가로,세로 확장 정책 (Fixed, Expanding)&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;※ 프로그램 개발시 복잡한 화면 구성을 할 때에는 레이아웃 종류와 중첩, 공간 제어를 통합해서 사용하는 것이 효과적이다.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[예제 1] Layout 이해하기 실습&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #777777;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; 파이참에서 코드를 실행하면 &quot;윈도우젯 레이아웃 살펴보기&quot; 화면이 생성된다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;987&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qdcfW/dJMcabYCgOm/TKOnloLsRcGeJHC32NfpK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qdcfW/dJMcabYCgOm/TKOnloLsRcGeJHC32NfpK1/img.png&quot; data-alt=&quot;파이참 에서 &amp;quot;레이아웃 살펴보기&amp;quot; 실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qdcfW/dJMcabYCgOm/TKOnloLsRcGeJHC32NfpK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqdcfW%2FdJMcabYCgOm%2FTKOnloLsRcGeJHC32NfpK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;841&quot; height=&quot;987&quot; data-origin-width=&quot;841&quot; data-origin-height=&quot;987&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;파이참 에서 &quot;레이아웃 살펴보기&quot; 실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 단계별 분석&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 98.7209%; height: 671px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단 계 별&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구 문&amp;nbsp; 활 용&amp;nbsp; 분 석&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1단계&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;필요한 클래스 &lt;br /&gt;가져오기&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; from PySide6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QVBoxLayout, QHBoxLayout&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;from PySide6.QtWidgets(파이사이드 환경에서 기본창 만들기)&amp;nbsp; import QApplication, QWidget, QLabel(텍스트 표시), QPushButton(버튼 만듬), QVBoxLayout(위젯 세로배치), QHBoxLayout(버튼 가로배치)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2단계&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위젯 생성&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;title_label = QLabel(&quot;레이아웃 예제&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;description_label = QLabel(&quot;버튼을 가로로 배치하고, 전체 화면은 세로로 구성합니다.&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;button_ok = QPushButton(&quot;확인&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;button_cancel = QPushButton(&quot;취소&quot;)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;// 화면에 표시할 위젯 생생 후 아직 화면에 배치된 것이 아니므로 레이아웃에 추가해서 실제 화면 구조가 만들어짐&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3단계&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;버튼 영영 가로 레이아웃 만들기&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;button_layout = QHBoxLayout() &amp;nbsp; // 레이아웃 가로 배치&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;button_layout.addWidget(button_ok)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;button_layout.addWidget(button_cancel)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ok 확인버튼과 cancel 취소버튼의 레이아웃을 가로로 배치한다.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4단계&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 화면 세로 레이아웃 만들기&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;main_layout = QVBoxLayout()&amp;nbsp; &amp;nbsp; // 레이아웃 세로 배치&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;main_layout.addWidget(title_label)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;main_layout.addWidget(description_label)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;main_layout.addLayout(button_layout)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;전체 화면을 세로 방향으로 구성한다.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그리고 , title제목, description 설명, button버튼을 레이아웃에 추가한다.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5단계&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부모 위젯에 레이아웃 적용&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;window.setLayout(main_layout)&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;셋레이아웃(부모위젯에 레이아웃 적용)을 호출하면 메인 레이아웃이 윈도우 레이아웃으로 적용된다.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;5.&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;QT Creator 환경에서 Layout 구현하기&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.1. Widget Design&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;새프로젝트 만들기 --&amp;gt; 파일명 작성 --&amp;gt; Widget class명을 선택 --&amp;gt; 인터프리터를 PySide6을 선택 --&amp;gt; Kits 선택 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;--&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;파일 목록 확인 후 마침 --&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&amp;nbsp;Design Layout&amp;nbsp;&lt;/span&gt;&lt;br /&gt;① 새프로젝트 만들기 : Qt for Python - Window UI 선택 (윈도우 화면에 구현할 버튼을 포함한 Layout 준비를 한다)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;833&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0c5ty/dJMcaicn4aq/KFRNWZtKDWwiF8kV1vVWwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0c5ty/dJMcaicn4aq/KFRNWZtKDWwiF8kV1vVWwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0c5ty/dJMcaicn4aq/KFRNWZtKDWwiF8kV1vVWwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0c5ty%2FdJMcaicn4aq%2FKFRNWZtKDWwiF8kV1vVWwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1258&quot; height=&quot;833&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;833&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;② 사용할 파일명을 작성 입력 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;613&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/phgHs/dJMcaaekLG8/ahaeTlkOf3yAnZ3VHfUgGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/phgHs/dJMcaaekLG8/ahaeTlkOf3yAnZ3VHfUgGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/phgHs/dJMcaaekLG8/ahaeTlkOf3yAnZ3VHfUgGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FphgHs%2FdJMcaaekLG8%2FahaeTlkOf3yAnZ3VHfUgGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;876&quot; height=&quot;613&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;613&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;③ Widget class명을 선택한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uHXaF/dJMcaayDB9V/c6yqtjp1oYiPUyus7N23k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uHXaF/dJMcaayDB9V/c6yqtjp1oYiPUyus7N23k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uHXaF/dJMcaayDB9V/c6yqtjp1oYiPUyus7N23k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuHXaF%2FdJMcaayDB9V%2Fc6yqtjp1oYiPUyus7N23k1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;989&quot; height=&quot;620&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;④ 인터프리터를 PySide6을 선택한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFQgi8/dJMcaf0XwHc/KLIHwtj2YgkKAszoNR4BNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFQgi8/dJMcaf0XwHc/KLIHwtj2YgkKAszoNR4BNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFQgi8/dJMcaf0XwHc/KLIHwtj2YgkKAszoNR4BNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFQgi8%2FdJMcaf0XwHc%2FKLIHwtj2YgkKAszoNR4BNK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;989&quot; height=&quot;620&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑤ Kits 선택하기 : 파이썬 버전을 선택한다. 나중에 파일분리 할 때&amp;nbsp; install 창이 뜨면 클릭하여 설치를&amp;nbsp; 적용할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/61Bgl/dJMcadPz1Q0/7Nj5IS2C6kKQPzike2gIMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/61Bgl/dJMcadPz1Q0/7Nj5IS2C6kKQPzike2gIMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/61Bgl/dJMcadPz1Q0/7Nj5IS2C6kKQPzike2gIMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F61Bgl%2FdJMcadPz1Q0%2F7Nj5IS2C6kKQPzike2gIMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;989&quot; height=&quot;620&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑥ 하단 목록에서 추가할 파일 목록 확인 후 추가 없으면 None 선택 후 마침 (Finish)&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GYHSG/dJMb990OsTQ/mB8B8zCGs6QTSGNkgOYJKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GYHSG/dJMb990OsTQ/mB8B8zCGs6QTSGNkgOYJKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GYHSG/dJMb990OsTQ/mB8B8zCGs6QTSGNkgOYJKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGYHSG%2FdJMb990OsTQ%2FmB8B8zCGs6QTSGNkgOYJKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;973&quot; height=&quot;624&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑦ Widget.py 파일이 생성됨 : 이때 파이사이드 6에서 설치 버전이 필요하면 install 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oB0Dv/dJMcadouFOJ/bIsTTbFcqNaATQC6JMTk6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oB0Dv/dJMcadouFOJ/bIsTTbFcqNaATQC6JMTk6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oB0Dv/dJMcadouFOJ/bIsTTbFcqNaATQC6JMTk6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoB0Dv%2FdJMcadouFOJ%2FbIsTTbFcqNaATQC6JMTk6k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1043&quot; height=&quot;707&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑧ 좌측에 Design 버튼 클릭하여 화면으로 이동해서 Layout 구성하자 (이때&lt;b&gt; &lt;u&gt;.ui 파일이 선택&lt;/u&gt;&lt;/b&gt;되어 있어야만 디자인 버튼이 활성화)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;707&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eaDO9N/dJMcadB0G9N/UjB2p07p6uXUnGrkbP7Sq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eaDO9N/dJMcadB0G9N/UjB2p07p6uXUnGrkbP7Sq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eaDO9N/dJMcadB0G9N/UjB2p07p6uXUnGrkbP7Sq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeaDO9N%2FdJMcadB0G9N%2FUjB2p07p6uXUnGrkbP7Sq1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1043&quot; height=&quot;707&quot; data-origin-width=&quot;1043&quot; data-origin-height=&quot;707&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑨&amp;nbsp; Design Layout 화면 : 만들고 싶은 디자인을 좌측 버튼에서 마우스로 끌어와서 중앙 Layout 화면에 배치하여 구성한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oQr73/dJMcadvgn1F/odupkf70JrQc3v0lQxf73k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oQr73/dJMcadvgn1F/odupkf70JrQc3v0lQxf73k/img.png&quot; data-alt=&quot;디자인 선택 화면 (form.ui@PySide Widgets)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oQr73/dJMcadvgn1F/odupkf70JrQc3v0lQxf73k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoQr73%2FdJMcadvgn1F%2Fodupkf70JrQc3v0lQxf73k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;960&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;960&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디자인 선택 화면 (form.ui@PySide Widgets)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lgUYf/dJMcafNvueG/xRO9VEIKp20w71khbhxQRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lgUYf/dJMcafNvueG/xRO9VEIKp20w71khbhxQRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lgUYf/dJMcafNvueG/xRO9VEIKp20w71khbhxQRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlgUYf%2FdJMcafNvueG%2FxRO9VEIKp20w71khbhxQRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1091&quot; height=&quot;784&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;784&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⑩&amp;nbsp; Layout에 디자인이 되었다면 좌측상단에 Edit를 클릭해서 Widget 화면으로 돌아간다.&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZkyDZ/dJMcabxu0sn/npwQBDfPKhRqeGdrtvrbRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZkyDZ/dJMcabxu0sn/npwQBDfPKhRqeGdrtvrbRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZkyDZ/dJMcabxu0sn/npwQBDfPKhRqeGdrtvrbRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZkyDZ%2FdJMcabxu0sn%2FnpwQBDfPKhRqeGdrtvrbRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1091&quot; height=&quot;784&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;784&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5.2. &amp;nbsp;Widget.py 에서 main.py 파일을 분리하여 만들기&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;① 메인파일 만들기 :&amp;nbsp; Qt 메뉴창에서 File -- New file (ctrl + n) 선택한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1071&quot; data-origin-height=&quot;783&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbdI3i/dJMcaiQVfhm/Uq4oOtxQLpV4IVy1UCwojk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbdI3i/dJMcaiQVfhm/Uq4oOtxQLpV4IVy1UCwojk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbdI3i/dJMcaiQVfhm/Uq4oOtxQLpV4IVy1UCwojk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbdI3i%2FdJMcaiQVfhm%2FUq4oOtxQLpV4IVy1UCwojk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1071&quot; height=&quot;783&quot; data-origin-width=&quot;1071&quot; data-origin-height=&quot;783&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;② main.py 파일일 생성 후 분리하기 : 메인 파일 선택 후 화면과 같이 Split Side by Side 선택한다. 그러면 파일이 분리된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1085&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRPLLr/dJMb990Os4z/QOu7iKbYucODGOeFZ3MoL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRPLLr/dJMb990Os4z/QOu7iKbYucODGOeFZ3MoL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRPLLr/dJMb990Os4z/QOu7iKbYucODGOeFZ3MoL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRPLLr%2FdJMb990Os4z%2FQOu7iKbYucODGOeFZ3MoL0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1085&quot; height=&quot;754&quot; data-origin-width=&quot;1085&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;③ Widget.py와 main.py 분리하기 : 위젯 파일에서 메인파이의 코드만 잘라내어 붙인 후 좌하단의 모니터를 실행시켜 본다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1070&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k1ndR/dJMcaayDEfi/6eqedk8hxzp0ojzTmI1DW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k1ndR/dJMcaayDEfi/6eqedk8hxzp0ojzTmI1DW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k1ndR/dJMcaayDEfi/6eqedk8hxzp0ojzTmI1DW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk1ndR%2FdJMcaayDEfi%2F6eqedk8hxzp0ojzTmI1DW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1070&quot; height=&quot;954&quot; data-origin-width=&quot;1070&quot; data-origin-height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;④ 실행시켰을 때 &quot;애러&quot; 메시지가 발생한다면 main.py에서 문법에 맞게 코드를 수정해 주어야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;847&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nNMBT/dJMcacpGqNn/GwzbP9a4mTa7hewiJSdK30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nNMBT/dJMcacpGqNn/GwzbP9a4mTa7hewiJSdK30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nNMBT/dJMcacpGqNn/GwzbP9a4mTa7hewiJSdK30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnNMBT%2FdJMcacpGqNn%2FGwzbP9a4mTa7hewiJSdK30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1038&quot; height=&quot;847&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;847&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑤ Widget.py 와 main.py가 분리되었으니 모두 저장(Save All) 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dp5OUW/dJMb99T2kI8/52uXIDdZHBKdQHkVIPpt9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dp5OUW/dJMb99T2kI8/52uXIDdZHBKdQHkVIPpt9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dp5OUW/dJMb99T2kI8/52uXIDdZHBKdQHkVIPpt9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdp5OUW%2FdJMb99T2kI8%2F52uXIDdZHBKdQHkVIPpt9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;773&quot; height=&quot;683&quot; data-origin-width=&quot;714&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;⑥ main.py를 선택하고 좌하단의 ▷ 실행버튼을 클릭하면 아래 화면과 같이 윈도우 Widget가 실행되었다.&lt;br /&gt;&amp;nbsp; &amp;nbsp; 이것은 윈도우 웹브라우저에서 화면의 Layout를 표현해 준다.&amp;nbsp;이때 from &lt;u&gt;파일경로 꼭 확인&lt;/u&gt; import *&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgLuHi/dJMcacb7REC/lih36DHvWKKi8qbqRXmhu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgLuHi/dJMcacb7REC/lih36DHvWKKi8qbqRXmhu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgLuHi/dJMcacb7REC/lih36DHvWKKi8qbqRXmhu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgLuHi%2FdJMcacb7REC%2Flih36DHvWKKi8qbqRXmhu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1212&quot; height=&quot;954&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;5.2.1. 실습 간 오류 수정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클래스 정의 추가 : &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;Ui_Widget&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;은 디자인 틀일 뿐이며, 이를 화면에 띄우려면 &lt;/span&gt;&lt;span style=&quot;color: #188038;&quot;&gt;QWidget&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 &lt;i&gt;&lt;b&gt;상속받은 실제 클래스가 필요하다&lt;/b&gt;&lt;/i&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #188038;&quot;&gt;setupUi(self)&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; 호출&lt;/b&gt;: 이 메서드를 실행해야만 Qt Designer에서 배치한 버튼, 텍스트 상자 등의 컴포넌트가 화면에 실제로 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인스턴스 접근 : 추후 버튼 클릭 이벤트 등을 연결할 때는 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #188038;&quot;&gt;self.ui.버튼이름&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; 형태로 접근하게 된다&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# This Python file uses the following encoding: utf-8
import sys

from PySide6.QtWidgets import QApplication, QWidget

# Important:
# You need to run the following command to generate the ui_form.py file
#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pyside6-uic form.ui -o ui_form.py, or
#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pyside2-uic form.ui -o ui_form.py
from ui_form import Ui_Widget

class Widget(QWidget):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;def __init__(self, parent=None):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;super().__init__(parent)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.ui = Ui_Widget()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self.ui.setupUi(self)


if __name__ == &quot;__main__&quot;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;app = QApplication(sys.argv)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;widget = Widget()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;widget.show()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sys.exit(app.exec())&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ㅇ 교육 후기&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; - 파이썬과 C++ 언어의 수많은 코드들을 작성하고 다 외울수는 없으나, 이제 이해하고 해석은 할 수 있겠다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; class의 사용이 다양한&amp;nbsp; 환경과 프로그램에서 사용되듯이 대다수 많은 반복되는 프로그램 환경들이 그렇겠다는 생각이 든다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; -&amp;nbsp; 처음에는 낯선 용어들이 점차 익숙해지고, 복잡한 UI 환경이 조금씩 이해되면서 우리가 흔히 사용하고 있는 인터넷 웹브라우저 환경, 응용프로그램 들이 모두 유사한 코드로 구현되고 있겠구나 생각이 든다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; - &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;웹브라우저 화면을 이해하고 구현하는데 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파이참, Qt 환경에서 class,&amp;nbsp; 모듈, 라이브러리, Signal, Slot, Layout를 복합적으로 활용할 수 있다면 교육의 성과는 있었다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; - 비전공자로서 각종 함수 문법을 잘 작성하지는 못해도 찾아보고 이해하는 데는 많은 도움이 되었다. 앞으로 어떤 환경에서 프로그램 개발을 위한 일원이 될지 알 수 없지만 &quot;도전은 계속된다.&quot;&lt;/span&gt;&lt;/p&gt;</description>
      <category>학습 로그/Python3</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/43</guid>
      <comments>https://goodjop79.tistory.com/43#entry43comment</comments>
      <pubDate>Thu, 21 May 2026 19:38:16 +0900</pubDate>
    </item>
    <item>
      <title>D+31 [아두이노] Aduino 환경에서 조건문, 함수 활용한 제어 실습</title>
      <link>https://goodjop79.tistory.com/42</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ㅇ 일 자 : 2026년 5월 20일(수)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;ㅇ 아두이노 환경에서 조건문과 함수 활용한 제어 실습&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;1.&amp;nbsp; 반복문으로 디지털 반딧불이 만들기 (교재 222P)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// [반복문으로 디지털 반딧불이 만들기]교재224p

void setup() 
{
&amp;nbsp;&amp;nbsp;pinMode(11,OUTPUT);
&amp;nbsp;&amp;nbsp;pinMode(10,OUTPUT);
&amp;nbsp;&amp;nbsp;pinMode(9,OUTPUT);
}

void loop() 
{&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;int i = random(3);&amp;nbsp;&amp;nbsp; // 임의의 수 반환 (0~(N-1)
&amp;nbsp;&amp;nbsp;int pinNumber = i+9;&amp;nbsp;&amp;nbsp;// PWM을 지원하는 핀 번호 가져오기
&amp;nbsp;&amp;nbsp;int intensity = 0;

&amp;nbsp;&amp;nbsp;while (intensity &amp;lt;= 255) {&amp;nbsp;&amp;nbsp; // 서서히 밝아지게 만들기
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;analogWrite(pinNumber, intensity++);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delay(10);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;while (intensity &amp;gt;=0) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// 서서히 어두워지게 만들기 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;analogWrite(pinNumber, intensity--);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delay(10);
&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;841&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kSSPv/dJMcabxuaYF/yZsehr3KDOAMsTHbUQc6mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kSSPv/dJMcabxuaYF/yZsehr3KDOAMsTHbUQc6mK/img.png&quot; data-alt=&quot;디지털 반딧물 만들기 (아두이노, 회로 팅거링 화면)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kSSPv/dJMcabxuaYF/yZsehr3KDOAMsTHbUQc6mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkSSPv%2FdJMcabxuaYF%2FyZsehr3KDOAMsTHbUQc6mK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1848&quot; height=&quot;841&quot; data-origin-width=&quot;1848&quot; data-origin-height=&quot;841&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디지털 반딧물 만들기 (아두이노, 회로 팅거링 화면)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;2.&amp;nbsp; DC 모터의 방향 제어하기 (237P)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// [DC 모터의 방향 제어하기] 교재237P
// DC모터는 기본 시계방향으로 회전하는데 단자에 연결된 선의 위치를 바꿔서, 
// ,모터의 회전을 반시계 방향으로 바꾸어서 제어하기

void setup() 
{
&amp;nbsp;&amp;nbsp;// PWM을 지원하는 디지털 9번, 10번 핀을 출력 모드로 설정
&amp;nbsp;&amp;nbsp;pinMode(9, OUTPUT);
&amp;nbsp;&amp;nbsp;pinMode(10, OUTPUT);

 // 스위치의 입력을 받기 위해 디지털 8번 핀을 입력 모드로 설정
&amp;nbsp;&amp;nbsp;pinMode(8, INPUT);
}

void loop() 
{
&amp;nbsp;&amp;nbsp;// 가변저항의 입력값 범위를 map() 함수로 변환
&amp;nbsp;&amp;nbsp;int inputValue = analogRead(A0);
&amp;nbsp;&amp;nbsp;int convertedValue = map(inputValue, 0, 1023, 0, 255);

&amp;nbsp;&amp;nbsp;//스위치의 입력값에 따라 DC 모터의 방향을 제어
&amp;nbsp;&amp;nbsp;int inputSwitch = digitalRead(8);
&amp;nbsp;&amp;nbsp;if (inputSwitch == LOW) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;analogWrite(9, convertedValue);&amp;nbsp;&amp;nbsp;// LOW값을 읽으면 9번 핀에 전원을 공급
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;analogWrite(10, 0);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;}
else {
&amp;nbsp;&amp;nbsp;analogWrite(9, 0);
&amp;nbsp;&amp;nbsp;analogWrite(10, convertedValue);&amp;nbsp;&amp;nbsp;// LOW 값을 읽지 않으면 10번 핀에 전원 공급
&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1844&quot; data-origin-height=&quot;877&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d6HTZB/dJMcabxua1J/BfJz6qcLumuPfHDsQUG8cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d6HTZB/dJMcabxua1J/BfJz6qcLumuPfHDsQUG8cK/img.png&quot; data-alt=&quot;모터방향 제어하기 (아두이노, 회로 팅거링 화면)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d6HTZB/dJMcabxua1J/BfJz6qcLumuPfHDsQUG8cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd6HTZB%2FdJMcabxua1J%2FBfJz6qcLumuPfHDsQUG8cK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1844&quot; height=&quot;877&quot; data-origin-width=&quot;1844&quot; data-origin-height=&quot;877&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;모터방향 제어하기 (아두이노, 회로 팅거링 화면)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;3.&amp;nbsp; 초음파 센서로 거리 측정하기 (249P)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// [물체 사이의 거리에 반응하는 LED 만들기] 249p

void setup() 
{
&amp;nbsp;&amp;nbsp;pinMode(7, OUTPUT);
&amp;nbsp;&amp;nbsp;pinMode(6, OUTPUT);
&amp;nbsp;&amp;nbsp;pinMode(5, OUTPUT);
}
&amp;nbsp;&amp;nbsp;
void loop() 
{
 // 초음파 신호 송신
 
&amp;nbsp;&amp;nbsp;pinMode(9, OUTPUT);
&amp;nbsp;&amp;nbsp;digitalWrite(9, LOW);
&amp;nbsp;&amp;nbsp;delayMicroseconds(2);
&amp;nbsp;&amp;nbsp;digitalWrite(9, HIGH);
&amp;nbsp;&amp;nbsp;delayMicroseconds(5);
&amp;nbsp;&amp;nbsp;digitalWrite(9, LOW);

// 초음파 신호 수신

&amp;nbsp;&amp;nbsp;pinMode(9, INPUT);
&amp;nbsp;&amp;nbsp;double duration= pulseIn(9, HIGH);
&amp;nbsp;&amp;nbsp;double cm = duration * 340 / 10000 / 2;

// 물체의 측정 거리에 따라 LED 제어

&amp;nbsp;&amp;nbsp;if (cm &amp;lt; 20) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(7, HIGH);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(6, LOW);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(5, LOW);
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;else if (cm &amp;lt; 60) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(7, LOW);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(6, HIGH);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(5, LOW);
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;else {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(7, LOW);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(6, LOW);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;digitalWrite(5, HIGH);
&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;delay(100);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1805&quot; data-origin-height=&quot;896&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oGtoY/dJMcahRZUHk/jMHi9Mk5j22Vhw0rqeb2Fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oGtoY/dJMcahRZUHk/jMHi9Mk5j22Vhw0rqeb2Fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oGtoY/dJMcahRZUHk/jMHi9Mk5j22Vhw0rqeb2Fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoGtoY%2FdJMcahRZUHk%2FjMHi9Mk5j22Vhw0rqeb2Fk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1805&quot; height=&quot;896&quot; data-origin-width=&quot;1805&quot; data-origin-height=&quot;896&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;4. 네오픽셀 다루기 (교재397p)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// [네오픽셀 다루기 1] 교재397&amp;nbsp;&amp;nbsp;

// 가. 네오픽셀 라이브러리 설치하기 (툴,라이브러리관리자 - 검색어 NeoPixel - Adafruit NeoPixel 선택후 설치)
// 나. 회로 구성하기 (구성요소 기본 - 검색어 neo - 구성요소에서 활용)
// 다. 스케치 코드 작성&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;라. 스케치 코드읽기

# include &amp;lt;Adafruit_NeoPixel.h&amp;gt;

#define PIN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 제어를 위한 디지털 핀 번호
#define NUMPIXELS&amp;nbsp;&amp;nbsp;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 네오픽셀의 LED 수

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
&amp;nbsp;&amp;nbsp;// 네오픽셀 라이브러리 초기화
&amp;nbsp;&amp;nbsp;pixels.begin();
&amp;nbsp;&amp;nbsp;
}

void loop() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setColor();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delay(100);
}

// 임의의 RGB 색상을 변경하는 함수
void setColor() {
&amp;nbsp;&amp;nbsp;int redColor = random(0, 256);
&amp;nbsp;&amp;nbsp;int greenColor = random(0, 256);
&amp;nbsp;&amp;nbsp;int blueColor = random(0, 256);
&amp;nbsp;&amp;nbsp;pixels.setPixelColor(0, pixels.Color(redColor,greenColor,blueColor));
&amp;nbsp;&amp;nbsp;pixels.show();&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1822&quot; data-origin-height=&quot;838&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2pAj0/dJMcaaSU2uE/QuRoRzd8TxVMckyuuNxvy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2pAj0/dJMcaaSU2uE/QuRoRzd8TxVMckyuuNxvy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2pAj0/dJMcaaSU2uE/QuRoRzd8TxVMckyuuNxvy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2pAj0%2FdJMcaaSU2uE%2FQuRoRzd8TxVMckyuuNxvy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1822&quot; height=&quot;838&quot; data-origin-width=&quot;1822&quot; data-origin-height=&quot;838&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;5. 네오픽셀 다루기 2 (교재 400p)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;// [스틱형 네오픽셀 다루기 2] 교재400&amp;nbsp;&amp;nbsp;

// 가. 네오픽셀 라이브러리 설치하기 (툴,라이브러리관리자 - 검색어 NeoPixel - Adafruit NeoPixel 선택후 설치)
// 나. 회로 구성하기 (구성요소 기본 - 검색어 neo - 구성요소에서 활용)
// 다. 스케치 코드 작성&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;라. 스케치 코드읽기

# include &amp;lt;Adafruit_NeoPixel.h&amp;gt;

#define PIN&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 제어를 위한 디지털 핀 번호
#define NUMPIXELS&amp;nbsp;&amp;nbsp; 4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // 네오픽셀의 LED 수

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
&amp;nbsp;&amp;nbsp;// 네오픽셀 라이브러리 초기화
&amp;nbsp;&amp;nbsp;pixels.begin();
&amp;nbsp;&amp;nbsp;
}

void loop() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;setColor();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;delay(100);
}

// 임의의 RGB 색상을 변경하는 함수
void setColor() {

&amp;nbsp;&amp;nbsp;for (int i=0; i&amp;lt;4; i++) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int redColor = random(0, 256);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int greenColor = random(0, 256);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int blueColor = random(0, 256);
&amp;nbsp;&amp;nbsp;pixels.setPixelColor(0, pixels.Color(redColor,greenColor,blueColor));
&amp;nbsp;&amp;nbsp;pixels.show();&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1831&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMKrAV/dJMcajvwUlT/23dlUzEtIhvh6d90W4alPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMKrAV/dJMcajvwUlT/23dlUzEtIhvh6d90W4alPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMKrAV/dJMcajvwUlT/23dlUzEtIhvh6d90W4alPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMKrAV%2FdJMcajvwUlT%2F23dlUzEtIhvh6d90W4alPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1831&quot; height=&quot;894&quot; data-origin-width=&quot;1831&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&lt;b&gt;6. 실습 후기&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;&lt;/b&gt;아두이노 환경에서 실습간&amp;nbsp; 포트설정이 잘못되어 애러가 잠시 있었고, 보드를 연결하여 실습하였다. 물론 보드 구성품이 교재와&amp;nbsp; 다르거나 완전하지 않아서 시뮬레이션으로 몇가지는 진행했다. 잘되는 부분도 있었지만 '모터방향 제어하기' 부분은 시뮬레이션만으로는 확인이 제한되었다. 각각의 제품 라이브러리 마다 상이한 경우 해당 버젼 파일을 모두 설치해 주어야 하는 번거로움도 있었다.&lt;br /&gt;&amp;nbsp; 조건문과 함수, C언어를 사용하여 구현하는 부분에서는 다소 애로사항이 있어서 교재와 웹브라우저를 활용, 찾아보면서 이해하려고 하였다.&lt;br /&gt;&amp;nbsp; 그러나 여러가지 실습을 통해 작동원리 및 산업현장에서 기계와 프로그램이 연동되어 어떻게 작동하는지 원리를 조금은 이해할 수 있게 되었다. &quot; 도전은 계속된다&quot;&lt;/p&gt;</description>
      <category>학습 로그/Aduino</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/42</guid>
      <comments>https://goodjop79.tistory.com/42#entry42comment</comments>
      <pubDate>Wed, 20 May 2026 20:22:47 +0900</pubDate>
    </item>
    <item>
      <title>D+30 [아두이노] AI 시대 Arduino 기업에서 활용 어떻게 해?</title>
      <link>https://goodjop79.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;☆ 일자 : 2026년 5월 19일(화)&amp;nbsp;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;009&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/axz_keditor/emoticon/friends1/large/009.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/axz_keditor/emoticon/friends1/large/009.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;교육 30일 차가 되었다. 그동안 컴퓨터는 전공해 본 적이 없는 비전공자로써 공부습관을 들이는 게 먼저였고,&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;낯선 컴퓨터 용어와 코딩 소스코드들을 작성하면서 이해하기 바빴다.&amp;nbsp; PC 저장장치 교체, 리눅스 환경 설정,&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;우분투 환경에서 파이참 설치 및 UI 설정, &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;개인 블로그 개설 및 학습로그 기록, &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;팀 프로젝트, 클래스 이해, &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;모듈&amp;amp;패키지&amp;amp;라이브러리 이해 및 활용, &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;아두이노까지 바쁘게 시간은 흘러갔다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;그럼&lt;b&gt; AI 시대에 아두이노를 기업에서는 어떻게 활용해야 할까?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 사물인터넷(IoT : Internet of Things)&lt;/b&gt;에 사용할 기기, 즉 스마트 디바이스를 만들기 위해 &lt;span style=&quot;letter-spacing: 0px;&quot;&gt;소형 컴퓨터 장치와 &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;3D 프린팅 기술 등이 발달하면서 메이커들도 자기만의 스마트 디바이스를 만들기 시작했는데&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이것이 오픈소스 하드웨어인 &lt;b&gt;아두이노(Arduino)&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-streaming-container=&quot;&quot; data-sfc-cb=&quot;&quot; data-wiz-uids=&quot;aEjgbf_45&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-tr-rsts=&quot;false&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-scope-id=&quot;turn&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-subtree=&quot;aimc&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-hveid=&quot;CAAIAhAA&quot; data-ved=&quot;2ahUKEwj_2IfPk8WUAxWTf_UHHX2FMpwQ2O0OegYIAAgCEAA&quot; data-sfc-cb=&quot;&quot; data-wiz-uids=&quot;FGTBUe_3&quot; data-sfc-root=&quot;c&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-ved=&quot;2ahUKEwj_2IfPk8WUAxWTf_UHHX2FMpwQ3KYQegYIAAgCEAE&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-xid=&quot;VpUvz&quot; data-container-id=&quot;main-col&quot;&gt;
&lt;blockquote data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-root=&quot;c&quot; data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #1b711d;&quot;&gt;AI 시대 아두이노(Arduino)의 효율성&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;강력한 엣지 컴퓨팅 구현&lt;/b&gt;&lt;br /&gt;TinyML(초소형 머신러닝)의 발전, 아두이노 보드 자체에서 가벼운 AI 모델을 직접 실행할 수 있어 데이터 처리 속도가 빠르다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;초고속 프로토타이핑&lt;/b&gt;&lt;br /&gt;Gemini, ChatGPT, Claude 같은 생성형 AI에게 명령하면 아두이노 소스 코드(C++)와 회로도를 몇 초 만에 짜주므로 개발 시간이 대폭 단축된다. 그러나 코딩의 코드 이해가 선행되어야 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;지능형 IoT 허브 역할&lt;/b&gt;&lt;br /&gt;아두이노가 수집한 환경 데이터를 클라우드 AI로 보내고, AI의 분석 결과를 받아 기계를 정밀 제어하는 가성비 좋은 '손발' 역할을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;≫&amp;nbsp; AI 시대의 아두이노는 복잡한 코딩과 시행착오를 AI가 대신 해결해 주기 때문에 과거보다 개발 효율성이 향상되었다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 4px 0px 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 500; margin: 0px 8px 0px 0px; text-decoration: none; border-bottom: 0px rgb(86, 89, 94);&quot; data-processed=&quot;true&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;blockquote data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 500; margin: 0px 8px 0px 0px; text-decoration: none; border-bottom: 0px rgb(86, 89, 94);&quot; data-processed=&quot;true&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;인터넷에 없는 독립형 AI 기계&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 24px 0px 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-tr-rsts=&quot;false&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-streaming-container=&quot;&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-scope-id=&quot;turn&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-subtree=&quot;aimc&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-hveid=&quot;CAAIARAA&quot; data-ved=&quot;2ahUKEwiIkO_yk8WUAxVZgq8BHV8rJjkQ2O0OegYIAAgBEAA&quot; data-sfc-cb=&quot;&quot; data-wiz-uids=&quot;gRbR0e_3&quot; data-sfc-root=&quot;c&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-ved=&quot;2ahUKEwiIkO_yk8WUAxVZgq8BHV8rJjkQ3KYQegYIAAgBEAE&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-xid=&quot;VpUvz&quot; data-container-id=&quot;main-col&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBRAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;부품 선택&lt;/b&gt;&lt;br /&gt;일반 아두이노 Uno 대신 AI 연산이 가능한 고성능 프로세서와 카메라, 마이크가 내장된 &lt;b&gt;Arduino Nano 33 BLE Sense&lt;/b&gt; 또는 &lt;b&gt;ESP32-S3&lt;/b&gt; 보드를 주로 사용한다.&amp;nbsp; 물론 개발자 자신에게 맞는 최적화된 개발도구가 우선이다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBRAB&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;개발 도구&lt;/b&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;Edge Impulse&lt;/b&gt;&lt;/u&gt; 같은 무료 TinyML 플랫폼을 사용하면 데이터 수집, AI 모델 학습, 아두이노 코드 변환까지 코딩 없이 마우스 클릭만으로 구현할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBRAC&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;핵심 장점&lt;/b&gt;&lt;br /&gt;인터넷 연결이 필요 없어 &lt;b&gt;보안성&lt;/b&gt;이 뛰어나고, 데이터 전송 지연이 없는 &lt;b&gt;실시간 제어&lt;/b&gt; 가능, 통신 부품이 빠져 &lt;b&gt;소형화와 전력 절감&lt;/b&gt;에 유리하다.&lt;/span&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-streaming-container=&quot;&quot; data-sfc-cb=&quot;&quot; data-wiz-uids=&quot;Pvhddd_45&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-tr-rsts=&quot;false&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-scope-id=&quot;turn&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-subtree=&quot;aimc&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIARAC&quot; data-ved=&quot;2ahUKEwisoP3tqsWUAxWsr1YBHfA1MZsQ2O0OegYIAAgBEAI&quot; data-sfc-cb=&quot;&quot; data-wiz-uids=&quot;WpH0m_e&quot; data-sfc-root=&quot;c&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot;&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 14px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-ved=&quot;2ahUKEwisoP3tqsWUAxWsr1YBHfA1MZsQ3KYQegYIAAgBEAM&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-xid=&quot;VpUvz&quot; data-container-id=&quot;main-col&quot;&gt;
&lt;blockquote data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAhAA&quot; data-sfc-root=&quot;c&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;&lt;u&gt;제조업의 AI 도입 트렌드 :&amp;nbsp; 엣지 AI가 바꾸는 공장의 미래&lt;/u&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAhAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAxAA&quot; data-sfc-root=&quot;c&quot; data-ke-size=&quot;size16&quot;&gt;인플레이션으로 인한 비용 상승과 노동력 부족에 직면한 제조업계가 '엣지 AI(Edge AI)'를 돌파구로 삼고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAxAA&quot; data-sfc-root=&quot;c&quot; data-ke-size=&quot;size16&quot;&gt;데이터가 생성되는 현장에서 실시간으로 지능형 처리를 수행하는 엣지 AI는 스마트 제조의 핵심 기반으로 자리 잡고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAxAA&quot; data-sfc-root=&quot;c&quot; data-ke-size=&quot;size16&quot;&gt;글로벌 리더들을 대상으로 한 설문조사 결과를 바탕으로&lt;b&gt; &quot;제조업 AI 도입의 5가지 핵심 트렌드&quot;&lt;/b&gt;를 요약한 내용이다.&lt;/p&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAxAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIAxAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 생산 최적화와 품질 향상이 최우선 목표&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBRAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;핵심 영역&lt;/b&gt;: 제조업체들은 제조 공정(1위), 생산 품질(2위), 장비 관리(3위)를 AI 도입의 최우선 영역으로 꼽았다. (p. 3).&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBRAB&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;도입 동인&lt;/b&gt;: 일반 시장 기업은 '제품 품질(67%)'을, 기술 전문 기업들은 '혁신(56%)'을 가장 큰 도입 비즈니스 등 (p. 4). 품질을 유지하면서 더 빠르고 똑똑하게 생산하는 것이 핵심이다 (p. 3).&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 현장 실시간 데이터 기반의 수익성 개선&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBxAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;실시간 대응&lt;/b&gt;: 클라우드를 거치지 않고 현장에서 실시간으로 데이터에 반응하여 사소한 문제가 커지기 전에 개입한다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIBxAB&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;주요 측정 항목&lt;/b&gt;: 공장 내 온도, 공기 품질, 습도, 소음, 시각 이벤트(컴퓨터 비전) 등을 센서로 정밀하게 모니터링한다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;3. 작업자 안전 및 신체 건강 모니터링 강화&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAICRAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;안전 솔루션&lt;/b&gt;: 개인보호장비(PPE) 착용 여부 준수, 낙상 감지, 위험 구역 접근 제어 등에 AI가 적극적으로 도입되고 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAICRAB&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;신체 모니터링&lt;/b&gt;: 근무 중인 작업자의 체온, 심박수 등 신체적 건강 상태를 파악하여 현장 안전성을 높이고 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;4. 성공의 걸림돌과 조직적 과제&lt;/span&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAICxAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;최대 장벽&lt;/b&gt;: 예산 제약이 가장 큰 걸림돌이며, 기존 시스템과의 통합 어려움 및 내부 전문성 부족이 그 뒤를 이었다 (p. 6).&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAICxAB&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;b&gt;전문 조직 부재&lt;/b&gt;: 전담 AI 팀을 보유한 기업은 10명 중 1명에 불과, 여전히 CTO/CIO나 IT 부서가 겸임하는 구조가 많다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;5. 앞으로 주목해야 할 AI 도입 계획&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; &amp;nbsp; 가. &lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span data-subtree=&quot;aimfl&quot; data-processed=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 600; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;내부 전문성 확보와 조직 체계화가 AI 도입의 핵심 성공 열쇠다 (pp. 2, 6).&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(1) &lt;b&gt;최대 걸림돌&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;: 예산 제약이 가장 큰 장벽이며, 기존 시스템과의 통합 어려움과&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;내부 전문 인력 부족&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이 그 뒤를 이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(2) &lt;/span&gt;&lt;b&gt;전담 팀 부재&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;: AI 전담 팀을 갖춘 기업은&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;10명 중 1명&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;에 불과하며, 여전히 CTO, CIO, IT 부서가 겸임하고 있다. (p. 6).&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(3) &lt;/span&gt;&lt;b&gt;파트너십 요구&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot; data-sfc-cp=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cb=&quot;&quot; data-complete=&quot;true&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot;&gt;: 제조업체의&amp;nbsp;&lt;b&gt;70%&lt;/b&gt;는 자사뿐만 아니라&amp;nbsp;&lt;/span&gt;&lt;b&gt;공급망 파트너사들도 AI 프로세스를 도입&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;해야 한다고 강조한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;(4) &lt;/span&gt;&lt;b&gt;성공 요인&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;: 복잡한 전체 머신러닝 프로세스(MLOps)를 이해하고 현장에 통합할 수 있는&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;내부 도메인 전문가 육성&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이 필수적&lt;/span&gt;&lt;/p&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 20px; font-weight: 600; margin: 24px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot; data-animation-nesting=&quot;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIDRAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&amp;nbsp; &amp;nbsp;** 향후 제조업체들이 도입할 가능성이 매우 높은 주요 기술 순위&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 12px 0px 16px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-processed=&quot;true&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIDhAA&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;예측 유지보수 (59%) (p. 7)&amp;nbsp;&lt;/span&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIDhAB&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;배송 및 물류 (57%) (p. 7)&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIDhAC&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;자산 및 재고 추적&amp;middot;관리 (55%) (p. 7)&lt;/span&gt;&lt;/li&gt;
&lt;li data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px 0px 12px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-sae=&quot;&quot; data-complete=&quot;true&quot; data-hveid=&quot;CAAIDhAD&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;&lt;span data-copy-service-computed-style=&quot;font-family: Arial, sans-serif; font-size: 16px; font-weight: 400; margin: 0px; text-decoration: none; border-bottom: 0px rgb(10, 10, 10);&quot; data-complete=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-root=&quot;c&quot; data-sfc-cp=&quot;&quot;&gt;제품&amp;middot;직원 시각 검사 (55%) (p. 7)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/mFhCJ/dJMcacb6eKQ/y86tbmfqT0UojkQMmQBjfk/_%20%EC%A0%9C%EC%A1%B0%EC%97%85_AI%EB%8F%84%EC%9E%85_5%EB%8C%80_%ED%8A%B8%EB%A0%8C%EB%93%9C_%ED%95%9C%EA%B8%80%EB%B2%88%EC%97%AD.docx.pdf?attach=1&amp;amp;knm=tfile.pdf&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;_ 제조업_AI도입_5대_트렌드_한글번역.docx.pdf&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;0.41MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;☆ 결&amp;nbsp; 론&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; 인공지능 응용시스템 개발자 양성교육 한 달째를 맞이하면서 프로그래밍의 기본 원리를 이해하고, AI를 적용하는 다양한 웹브라우저와 응용프로그램 들이 구현되는 과정을 이해하려고 한다.&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; 개발자, 기획자, PM, 빅데이터 분석가 등등 기업이 필요로 하고 사용자가 요구하는 프로그램을 구현하도록 하는 것이 이 과정의 취지가 아닐까 다시 한번 생각하게 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;AI 시대 아두이노(Arduino)를 기업에서 어떻게 활용할 것인지는 이익을 추구하는 기업에서는 투자 대비 이익을 고려하여 판단할 것이다.&amp;nbsp; &quot;배움과 활용의 도전은 계속된다.&quot;&lt;/p&gt;</description>
      <category>IT 컴퓨터</category>
      <category>AI #아두이노 #사물인터넷 #기업 #Edge Impulse</category>
      <author>goodjop79 님의 블로그</author>
      <guid isPermaLink="true">https://goodjop79.tistory.com/41</guid>
      <comments>https://goodjop79.tistory.com/41#entry41comment</comments>
      <pubDate>Tue, 19 May 2026 21:54:32 +0900</pubDate>
    </item>
  </channel>
</rss>