<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>From_Base</title>
    <link>https://basecoding.tistory.com/</link>
    <description>컴퓨터공학 기초공부에 대한 정리</description>
    <language>ko</language>
    <pubDate>Sun, 26 Jul 2026 00:07:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>base_coding</managingEditor>
    <image>
      <title>From_Base</title>
      <url>https://tistory1.daumcdn.net/tistory/6604459/attach/cceac2cdd4414d468e2981a53f2174eb</url>
      <link>https://basecoding.tistory.com</link>
    </image>
    <item>
      <title>[Docker] 도커(Docker)란 무엇인가? (1): 컨테이너 개념/ 다중 컨테이너 관리/ 실시간 개발 모드</title>
      <link>https://basecoding.tistory.com/entry/Docker-%EB%8F%84%EC%BB%A4Docker%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-1-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EA%B0%9C%EB%85%90-%EB%8B%A4%EC%A4%91-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EA%B4%80%EB%A6%AC-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EA%B0%9C%EB%B0%9C-%EB%AA%A8%EB%93%9C</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGWFpp/dJMcaiaOu4S/t2ToKZ2RZOzg8qxdIpuFu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGWFpp/dJMcaiaOu4S/t2ToKZ2RZOzg8qxdIpuFu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGWFpp/dJMcaiaOu4S/t2ToKZ2RZOzg8qxdIpuFu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGWFpp%2FdJMcaiaOu4S%2Ft2ToKZ2RZOzg8qxdIpuFu0%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;442&quot; height=&quot;114&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;114&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS 버전, 라이브러리 충돌, 복잡한 의존성 문제 등&amp;hellip;&lt;br /&gt;&quot;내 컴퓨터에서는 되는데 왜 서버에서는 안 되지?&quot;라는 상황도 프로젝트를 진행해오면서 많이 겪었던거 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결해 주는 핵심 기술인 &lt;b&gt;Docker&lt;/b&gt;(도커)와 &lt;b&gt;Container&lt;/b&gt;(컨테이너)의 기본 개념,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 실무에서 필수적인 &lt;b&gt;Docker Compose&lt;/b&gt;를 이용한 다중 컨테이너 관리 방법까지 정리해보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  1-1. Container란 무엇인가? (What is a container?)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6I74k/dJMcagRA9PR/P7ai0Zel6mJD58ZwnR2ADk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6I74k/dJMcagRA9PR/P7ai0Zel6mJD58ZwnR2ADk/img.png&quot; data-alt=&quot;선박에 실린 수많은 컨테이너과 이를 관리하는 관리자(Containers &amp;amp;amp; Docker) image by Gemini&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6I74k/dJMcagRA9PR/P7ai0Zel6mJD58ZwnR2ADk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6I74k%2FdJMcagRA9PR%2FP7ai0Zel6mJD58ZwnR2ADk%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;500&quot; height=&quot;273&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;선박에 실린 수많은 컨테이너과 이를 관리하는 관리자(Containers &amp;amp; Docker) image by Gemini&lt;/figcaption&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;컨테이너를 간략히 표현하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;프로젝트를 위한 격리된 환경(Isolated Environment)을 제공해주는 가상화 기술&lt;/b&gt;이라고 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컨테이너&lt;/b&gt;는 애플리케이션을 구동하는 데 필요한 &lt;b&gt;소스 코드, 라이브러리, 환경 설정 파일 등을 하나로 묶어(Package) 격리된 공간에서 실행&lt;/b&gt;하는 기술을 말합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;쉽게 말해, 어떤 환경에서든 실행 가능하도록 만든 &lt;b&gt;'소프트웨어 패키지 상자' &lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;12&quot; data-ke-size=&quot;size23&quot;&gt;  주요 특징: 환경의 격리&lt;/h3&gt;
&lt;p data-path-to-node=&quot;13&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;14&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;App A는 Python 3.8을 사용&lt;/li&gt;
&lt;li&gt;App B는 Python 2.7을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;이 경우 로컬 환경에서 이를 동시에 세팅하다 보면 PATH 충돌이나 의존성 문제(Dependency Hell)가 발생하곤 합니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;컨테이너는 이 애플리케이션들을 서로 &lt;b&gt;완벽하게 격리(Isolation)&lt;/b&gt; 시켜, 하나의 서버 안에서도 서로 간섭 없이 독립적으로 실행되게 만들어주는 &lt;span style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot;&gt;컨테이너 플랫폼입니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;16&quot; data-ke-size=&quot;size23&quot;&gt;  VM(가상머신) vs 컨테이너&lt;/h3&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;컨테이너를 이해할 때 기존의 가상화 기술인 &lt;b&gt;VMware(Virtual Machine)&lt;/b&gt; 와의 유사성을 느낄 수 있습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;17&quot; data-ke-size=&quot;size16&quot;&gt;둘 다 '격리된 환경'을 제공하지만, 그 무게와 구조는 엄연히 다릅니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-path-to-node=&quot;18&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;비교 항목&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;가상머신 (VM)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;컨테이너 (Docker)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,1,0,0&quot;&gt;&lt;b&gt;구조&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,1,1,0&quot;&gt;하드웨어를 가상화하여 &lt;b&gt;Guest OS를 통째로 설치&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,1,2,0&quot;&gt;&lt;b&gt;Host OS의 커널(Kernel)을 공유&lt;/b&gt;하여 프로세스만 격리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,2,0,0&quot;&gt;&lt;b&gt;무게&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,2,1,0&quot;&gt;무거움 (수 GB)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,2,2,0&quot;&gt;가벼움 (수 MB ~ 수백 MB)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,3,0,0&quot;&gt;&lt;b&gt;속도&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,3,1,0&quot;&gt;느림 (부팅 시간 필요)&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,3,2,0&quot;&gt;&lt;b&gt;매우 빠름&lt;/b&gt; (프로세스 실행 속도)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,4,0,0&quot;&gt;&lt;b&gt;성능&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,4,1,0&quot;&gt;오버헤드가 큼&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span data-path-to-node=&quot;18,4,2,0&quot;&gt;네이티브 성능에 근접&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-path-to-node=&quot;19&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VM은 집 전체(OS)를 새로 짓는 것이라면, 컨테이너는 기존 건물의 수도와 전기(Kernel)를 공유하면서 내 방(User Space) 만 따로 격리해서 쓰는 방식.&lt;br /&gt;&lt;br /&gt;그래서 훨씬 가볍고 빠름&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-path-to-node=&quot;21&quot; data-ke-size=&quot;size26&quot;&gt;  1-2. 도커(Docker)란 무엇인가?&lt;/h2&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;컨테이너 기술(LXC 등) 자체는 리눅스에 예전부터 존재해왔습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;하지만 사용하기가 매우 복잡하고 어려웠다는 문제점이 있었는데,&amp;nbsp; &lt;b&gt;도커(Docker)&lt;/b&gt;는 이 &lt;b&gt;컨테이너 기술을 쉽고 편하게 사용할 수 있도록 만든 컨테이너 플랫폼&lt;/b&gt;으로 등장하여 범용적으로 사용되고 있습니다.&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;h3 data-path-to-node=&quot;23&quot; data-ke-size=&quot;size23&quot;&gt;  표준화된 소프트웨어 운송&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;92&quot; data-origin-height=&quot;92&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WJTee/dJMcafZsn7B/n8IPkHgFVrR3EAY9lGnKPK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WJTee/dJMcafZsn7B/n8IPkHgFVrR3EAY9lGnKPK/img.jpg&quot; data-alt=&quot;도커 메인 로고&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WJTee/dJMcafZsn7B/n8IPkHgFVrR3EAY9lGnKPK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWJTee%2FdJMcafZsn7B%2Fn8IPkHgFVrR3EAY9lGnKPK%2Fimg.jpg&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;100&quot; height=&quot;100&quot; data-origin-width=&quot;92&quot; data-origin-height=&quot;92&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커 메인 로고&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-path-to-node=&quot;24&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;24&quot; data-ke-size=&quot;size16&quot;&gt;도커의 로고인 고래를 보면 등에 컨테이너 박스를 싣고 있는 모습을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;24&quot; data-ke-size=&quot;size16&quot;&gt;마찬가지로 이는 물류 시스템의 &lt;b&gt;'컨테이너'&lt;/b&gt;와 &lt;b&gt;'컨테이너 관리자'&lt;/b&gt;인 Docker 개념을 소프트웨어로 가져온 것 입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;25&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;p data-path-to-node=&quot;26&quot; data-ke-size=&quot;size16&quot;&gt;도커도 마찬가지 입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;26&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;26&quot; data-ke-size=&quot;size16&quot;&gt;내가 짠 코드가 Java든, Python이든, Node.js든 상관없이, &lt;b&gt;도커 컨테이너&lt;/b&gt;라는 표준 규격에 담기만 하면 AWS든, Azure든, 내 노트북이든 &lt;b&gt;어디서나 100% 동일하게 실행됨을 보장&lt;/b&gt;해줍니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-path-to-node=&quot;28&quot; data-ke-size=&quot;size26&quot;&gt;  1-3. Docker 핵심 요소: 이미지(Image)와 컨테이너(Container)&lt;/h2&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;도커를 학습할 때 가장 먼저 이해해야 할 두 가지 개념은 &lt;b&gt;이미지&lt;/b&gt;와 &lt;b&gt;컨테이너&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;29&quot; data-ke-size=&quot;size16&quot;&gt;개발자에게 익숙한 &lt;b&gt;객체 지향 프로그래밍(OOP)&lt;/b&gt; 개념에 빗대어 이해하면 쉽습니다.&lt;/p&gt;
&lt;h3 data-path-to-node=&quot;30&quot; data-ke-size=&quot;size23&quot;&gt;  도커 이미지 (Docker Image)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;31&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;개념:&lt;/b&gt; 컨테이너를 생성하기 위한 &lt;b&gt;'읽기 전용(Read-only) 템플릿'&lt;/b&gt; 입니다. 애플리케이션 실행에 필요한 코드, 런타임, 라이브러리, 설정값 등이 모두 포함되어 있는 파일입니다.&lt;b&gt;(&lt;u&gt;Dockerfile&lt;/u&gt;)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비유:&lt;/b&gt; 붕어빵 틀, 또는 클래스(Class)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특징:&lt;/b&gt; 이미지는 상태 값을 가지지 않으며(Stateless), 변하지 않음(Immutable).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-path-to-node=&quot;32&quot; data-ke-size=&quot;size23&quot;&gt;  도커 컨테이너 (Docker Container)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;33&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;개념:&lt;/b&gt; 이미지를 실행하여 메모리에 로드된 &lt;b&gt;'프로세스(Process)'&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비유:&lt;/b&gt; 붕어빵, 또는 &lt;b&gt;인스턴스(Instance)&lt;/b&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;background-color: #f6e199;&quot;&gt;&amp;ldquo;&lt;b&gt;도커 이미지&lt;/b&gt;는 OOP의 &lt;u&gt;클래스(.java)&lt;/u&gt;와 같고,&lt;b&gt; 컨테이너&lt;/b&gt;는 이를 기반으로 실행되어 &lt;u&gt;JVM 상에서 동작하는 실제 생성된 객체 인스턴스&lt;/u&gt;에 해당&amp;rdquo; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특징:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;33,2,1&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 이미지로 여러 개의 컨테이너를 생성할 수 있음&lt;/li&gt;
&lt;li&gt;컨테이너 안에서 파일을 수정하거나 데이터를 저장할 수 있음 (&lt;u&gt;단, 컨테이너가 삭제되면 데이터도 날아가므로 별도의 Volume 처리가 필요&lt;/u&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwjx9q2-uMORAxUAAAAAHQAAAAAQ1wM&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;[이미지 (Class)]      ---(실행)---&amp;gt;      [컨테이너 (Instance)]
- ubuntu:latest                           - 내 컨테이너 1 (실행 중)
- redis:alpine                            - 내 컨테이너 2 (실행 중)
(파일 형태, 불변)                         (프로세스 형태, 가변)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이러한 컨테이너 기술을 이해하는 가장 좋은 방법은 직접 실습해 보는 것입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Docker Desktop에서 이 기초 실습 프로세스를 제공해주고 있는데, 가장 첫 단계로 welcome-to-docker라는 튜토리얼 컨테이너 기반 실습 먼저 진행해보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-1. welcome-to-docker 컨테이너 실행 및 포트 포워딩 (Port Forwarding)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rti6W/dJMb99St05K/T6rHz6et3PFkl9prlALaKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rti6W/dJMb99St05K/T6rHz6et3PFkl9prlALaKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rti6W/dJMb99St05K/T6rHz6et3PFkl9prlALaKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frti6W%2FdJMb99St05K%2FT6rHz6et3PFkl9prlALaKk%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;738&quot; height=&quot;61&quot; data-origin-width=&quot;738&quot; data-origin-height=&quot;61&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;위 실행 화면에서 주목해야 할 부분은 Port(s) 컬럼의 8088:80입니다.&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;80 (Container Port)&lt;/b&gt;: 컨테이너 내부의 웹 서버가 사용하고 있는 포트&lt;/li&gt;
&lt;li&gt;&lt;b&gt;8088 (Host Port)&lt;/b&gt;: 내 컴퓨터(Host)에서 접근할 포트&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 브라우저에서 localhost:8088로 접속하면 도커가 이를 컨테이너 내부의 80번 포트로 연결해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 덕분에 내 PC의 환경 설정을 건드리지 않고도 웹 서버를 띄울 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1918&quot; data-origin-height=&quot;908&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd0ovc/dJMcaaDQvdE/sPSK3MovOSZHklhXMqbje0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd0ovc/dJMcaaDQvdE/sPSK3MovOSZHklhXMqbje0/img.png&quot; data-alt=&quot;localhost:8088 접속 시 welcome-to-docker 컨테이너의 80포트에서 서빙 중인 프론트 화면을 확인 가능&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd0ovc/dJMcaaDQvdE/sPSK3MovOSZHklhXMqbje0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd0ovc%2FdJMcaaDQvdE%2FsPSK3MovOSZHklhXMqbje0%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;1918&quot; height=&quot;908&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;908&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;localhost:8088 접속 시 welcome-to-docker 컨테이너의 80포트에서 서빙 중인 프론트 화면을 확인 가능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-2. 격리된 파일 시스템&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너를 선택하고 Files 탭을 확인해 보면, 내 컴퓨터(Windows/Mac)와는 전혀 다른 리눅스 파일 시스템 구조가 보입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/plP4Z/dJMcad1ADTv/MLXgMyg0g3npEbjUo3RsG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/plP4Z/dJMcad1ADTv/MLXgMyg0g3npEbjUo3RsG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/plP4Z/dJMcad1ADTv/MLXgMyg0g3npEbjUo3RsG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FplP4Z%2FdJMcad1ADTv%2FMLXgMyg0g3npEbjUo3RsG0%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;1272&quot; height=&quot;582&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;582&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;/b&gt;을 가집니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  3. 이미지 빌드 및 실행 (How do I run a container?)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번에서 진행했던 컨테이너의 경우엔 Docker Desktop 설치 시 기본으로 제공해주는 샘플 컨테이너였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 더 나아가 직접 소스 코드를 받아&lt;b&gt; 이미지(Image)&lt;/b&gt;를 빌드하여 도출된 컨테이너를 실행하는 과정을 진행하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-1. 소스 코드 가져오기 (Git Clone)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 실습할 샘플 깃허브 오픈소스 프로젝트를 가져옵니다.&lt;/p&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;git clone https://github.com/docker/welcome-to-docker
cd welcome-to-docker
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-2. Dockerfile과 이미지 빌드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 폴더 내의 Dockerfile은 &lt;b&gt;&quot;어떤 환경에서, 어떤 의존성을 가지고, 어떤 코드를 돌릴지&quot;&lt;/b&gt;를 정의한 설계도입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파일을 바탕으로 이미지를 빌드합니다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# -t : 이미지에 이름(Tag)을 붙이는 옵션 (여기서는 welcome-to-docker)
# .  : 현재 디렉토리의 Dockerfile을 찾으라는 의미
docker build -t welcome-to-docker .
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-3. 빌드한 이미지 실행 (Run)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드가 완료되면 Images 탭에 welcome-to-docker 이미지가 생성됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 이미지를 기반으로 컨테이너를 생성하게 되는데, 이때 해당 컨테이너의 Host 포트를 지정해 주어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;컨테이너 이름은 Practice_Container 로 지정하겠습니다.&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;Host Port&lt;/b&gt;: 8089&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;(직접 선택 가능)&lt;/u&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Container Port&lt;/b&gt;: 3000&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOYrP3/dJMcahprWUh/p3DKK3GLfUeEZbnZNvx9B1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOYrP3/dJMcahprWUh/p3DKK3GLfUeEZbnZNvx9B1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOYrP3/dJMcahprWUh/p3DKK3GLfUeEZbnZNvx9B1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOYrP3%2FdJMcahprWUh%2Fp3DKK3GLfUeEZbnZNvx9B1%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;788&quot; height=&quot;776&quot; data-origin-width=&quot;788&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Run버튼을 클릭하면 Image를 구워서 설정한 옵션값으로 컨테이너가 만들어집니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;758&quot; data-origin-height=&quot;90&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpsknx/dJMcacVXOfU/UnmPesz8myPYxFdtRzy4oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpsknx/dJMcacVXOfU/UnmPesz8myPYxFdtRzy4oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpsknx/dJMcacVXOfU/UnmPesz8myPYxFdtRzy4oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbpsknx%2FdJMcacVXOfU%2FUnmPesz8myPYxFdtRzy4oK%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;758&quot; height=&quot;90&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;90&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;이제 localhost:8089에 접속하면 내가 빌드한 애플리케이션이 정상적으로 동작하는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  4. 다중 컨테이너 관리 (Multi-container applications)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 단일 컨테이너만 사용하는 경우는 거의 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 &lt;b&gt;Frontend + Backend + Database&lt;/b&gt; 등 여러 서비스가 유기적으로 연결된 복합 시스템을 다루곤 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 시스템 구동시마다 각 컨테이너를 하나씩 각각 실행하는 것은 매우 비효율적인 반복 동작일 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 작업을 단순화해주는 것이 바로 &lt;b&gt;Docker Compose &lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-1. Multi-container 앱 준비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깃허브에 있는 Docker Compose 실습 예제 (Node.js 기반의 Todo 앱과 MongoDB)를 활용하여 진행해보겠습니다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone https://github.com/docker/multi-container-app
cd multi-container-app
&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;해당 프로젝트를 IDE를 통해서 열어보면 &lt;b&gt;compose.yaml&lt;/b&gt; 이라는 핵심 파일을 확인해볼 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1765945175722&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;services:
  todo-app:
    build:
      context: ./app
    depends_on:
      - todo-database
    environment:
      NODE_ENV: production
    ports:
      - 3000:3000
      - 35729:35729
    develop:
      watch:
        - path: ./app/package.json
          action: rebuild
        - path: ./app
          target: /usr/src/app
          action: sync

  todo-database:
    image: mongo:6
    #volumes: 
    #  - database:/data/db
    ports:
      - 27017:27017&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;프로젝트 내의 compose.yaml 파일은 마치 전체 시스템의 오케스트라 지휘자와 같은 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;웹 앱과 DB를 같이 실행하고, 서로 네트워크로 연결하라&quot;는 명세가 담겨 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 의존성은 &lt;b&gt;depends_on &lt;/b&gt;속성을 통해서 구성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-2. 한 번에 실행하기 (Compose Up)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 시스템의 지휘자인 compose.yaml에게 지휘 명령을 내려볼 시간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하단 명령어 한 줄로 compose.yaml 파일을 실행하여 이 안에 정의된 모든 서비스를 실행해볼 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;# -d : 백그라운드 모드(Detached mode)로 실행
docker compose up -d
&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;compose.yaml이 일련의 시간을 거쳐 처리가되면 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;multi-container-app라는 컨테이너가 하나 생성됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Docker Desktop을 확인해보면 &lt;b&gt;todo-app&lt;/b&gt;과 &lt;b&gt;todo-database&lt;/b&gt; 두 개의 컨테이너가 &lt;b&gt;하나의 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;multi-container-app라는&lt;/span&gt; &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&lt;b&gt;컨테이너에 포함&lt;/b&gt;되는 &lt;/span&gt;&lt;b&gt;App Stack&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;473&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pxbUx/dJMcagYmCPr/fRkIkOLDzbmDRM8gGRkOx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pxbUx/dJMcagYmCPr/fRkIkOLDzbmDRM8gGRkOx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pxbUx/dJMcagYmCPr/fRkIkOLDzbmDRM8gGRkOx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpxbUx%2FdJMcagYmCPr%2FfRkIkOLDzbmDRM8gGRkOx1%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;473&quot; height=&quot;247&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-3. 실시간 개발 모드 (Compose Watch)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 중 코드가 변경될 때마다 이미지를 다시 빌드하는 것은 번거롭습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Docker Compose Watch&lt;/b&gt;를 사용하면 소스 코드 변경을 실시간으로 감지하여 컨테이너에 반영해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 리액트 개발 모드 중 실시간 코드 변경을 반영하여 핫 리로딩(Hot Reloading)해주는 것과 같은 편리성을 제공해줍니다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;docker compose watch
&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;802&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H8otA/dJMcahiFRBg/U1p61X4mfMB945FJy82pY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H8otA/dJMcahiFRBg/U1p61X4mfMB945FJy82pY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H8otA/dJMcahiFRBg/U1p61X4mfMB945FJy82pY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH8otA%2FdJMcahiFRBg%2FU1p61X4mfMB945FJy82pY1%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;1560&quot; height=&quot;802&quot; data-origin-width=&quot;1560&quot; data-origin-height=&quot;802&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 4-1의 프로젝트에서 프론트 소스 코드(app/views/todos.ejs 등)를 수정하고 저장하면, 실시간으로 변경 사항이 즉시 적용된 것을 확인해 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4-4. 서비스 종료 및 주의사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4-2에서 생성했던 컨테이너 스택을 삭제하고 싶다면 다음 명령어를 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;docker compose down
&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;주의: 데이터 휘발성 (Data Persistence)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 방식으로 DB 컨테이너를 삭제하고 다시 실행하면, 기존에 입력했던 Todo 목록(데이터)이 모두 사라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너는 기본적으로 상태를 저장하지 않는(&lt;b&gt;Stateless&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;Docker Volume&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;/p&gt;</description>
      <category>Container/Docker</category>
      <category>docker</category>
      <category>도커</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/41</guid>
      <comments>https://basecoding.tistory.com/entry/Docker-%EB%8F%84%EC%BB%A4Docker%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-1-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EA%B0%9C%EB%85%90-%EB%8B%A4%EC%A4%91-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88-%EA%B4%80%EB%A6%AC-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EA%B0%9C%EB%B0%9C-%EB%AA%A8%EB%93%9C#entry41comment</comments>
      <pubDate>Wed, 17 Dec 2025 13:38:45 +0900</pubDate>
    </item>
    <item>
      <title>기업연계 프로젝트 with Qualcomm: RubikPi와 함께한 On-Device AI 개발</title>
      <link>https://basecoding.tistory.com/entry/%EA%B8%B0%EC%97%85%EC%97%B0%EA%B3%84-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-with-Qualcomm-RubikPi%EC%99%80-%ED%95%A8%EA%BB%98%ED%95%9C-On-Device-AI-%EA%B0%9C%EB%B0%9C</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;지금까지 Qualcomm측과의 기업연계 프로젝트를 진행하며 RubikPi로 On-Device AI 개발하며 겪은 모든 것&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 졸업작품을 준비하면서 뜻밖의 기회가 생겼다. 바로 Qualcomm과의 산학협력 프로젝트에 선정된 것이다. 주제는 최대한 개발하면서 나도 흥미를 느낄 수 있으며 사회적 솔루션으로 접근하고자 &amp;lsquo;On-Device AI 기반 스마트 배리어프리 키오스크 플랫폼&amp;rsquo;으로 제안하였다. 처음엔 &amp;lsquo;On-Device AI&amp;rsquo;라는 말 자체가 생소했다. AI는 대부분 클라우드에서 동작하는 거라 생각했는데, 디바이스 자체에서 추론까지 수행한다는 개념을 이번 프로젝트를 시작하면서 알게되었고 프로젝트를 진행하며 개발용으로 받은 RubikPi라는 장비와 함께 On-Device AI서비스 개발을 진행하게되었다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;RubikPi란?&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20250327_170722.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cM1DCP/btsN1dYR4VB/ouzk331F4pfoUzG6FLVtNK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cM1DCP/btsN1dYR4VB/ouzk331F4pfoUzG6FLVtNK/img.jpg&quot; data-alt=&quot;RubikPi&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cM1DCP/btsN1dYR4VB/ouzk331F4pfoUzG6FLVtNK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcM1DCP%2FbtsN1dYR4VB%2Fouzk331F4pfoUzG6FLVtNK%2Fimg.jpg&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;300&quot; height=&quot;225&quot; data-filename=&quot;20250327_170722.jpg&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RubikPi&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;618&quot; data-start=&quot;442&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;618&quot; data-start=&quot;442&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Qualcomm QCS6490 칩셋 기반의 RubikPi는 Thundercomm에서 제작한 온디바이스 AI 전용 IoT 보드다. 라즈베리파이처럼 생겼지만 GPU가 아닌 NPU(Neural Processing Unit)가 탑재되어 있어, 클라우드 도움 없이도 학습된 AI 모델을 빠르게 실행할 수 있도록 설계돼 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;618&quot; data-start=&quot;442&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;820&quot; data-start=&quot;620&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Qualcomm은 RubikPi용 AI 모델을 지원하는 &lt;a href=&quot;https://aihub.qualcomm.com/&quot; data-end=&quot;697&quot; data-start=&quot;651&quot;&gt;Qualcomm AI Hub&lt;/a&gt;도 함께 운영 중이다. 여기에서 YOLOv8 같은 사전 학습된 모델을 Quantized된 형태로 제공하고, AI Hub를 통해 컴파일된 .dlc나 .tflite 모델을 RubikPi에 바로 올려 테스트할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;854&quot; data-start=&quot;822&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하지만 문제는, 이 플렛폼 및 보드 자체가 출시된지 얼마되지않은 상태이기에 관련 레퍼런스가 거의 없다싶이하니, 처음엔 정말 막막했다. 관련 정보를 얻고자하면 공식 document 혹은 커뮤니티를 통해 해외 담당자 혹은 회원들을 통해서 정보를 얻어야했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;854&quot; data-start=&quot;822&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20250508_021204.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cI5CWs/btsN2IbY41C/UbSsOPALAeClrQSV1DuxSK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cI5CWs/btsN2IbY41C/UbSsOPALAeClrQSV1DuxSK/img.jpg&quot; data-alt=&quot;RubikPi에 CSI카메라 연결하여 스트리밍&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cI5CWs/btsN2IbY41C/UbSsOPALAeClrQSV1DuxSK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcI5CWs%2FbtsN2IbY41C%2FUbSsOPALAeClrQSV1DuxSK%2Fimg.jpg&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;300&quot; height=&quot;400&quot; data-filename=&quot;20250508_021204.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RubikPi에 CSI카메라 연결하여 스트리밍&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;854&quot; data-start=&quot;822&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1064&quot; data-start=&quot;881&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;처음 RubikPi를 받고 한 건 카메라 테스트였다. 하지만 OpenCV로 카메라 띄우는 것조차 실패했는데, 이유는 RubikPi의 OS가 일반적인 배포판 리눅스가 아니기 때문. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Qualcomm&lt;/span&gt;에서 자체 커스터마이징한 wayland/weston 기반의 Qualcom Linux였고, V4L2도 지원이 제한적이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1161&quot; data-start=&quot;1066&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;결국 공식문서를 따라가며 qtiqmmfsrc GStreamer 소스를 사용해 스트리밍을 테스트하게 됐다. 이 과정에서 GStreamer라는 생소한 툴로 고군분투 해야했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1161&quot; data-start=&quot;1066&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1189&quot; data-start=&quot;1163&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;YOLOv8 Quantized 모델 돌리기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;1374&quot; data-start=&quot;1191&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;AI 모델은 Qualcomm AI Hub에서 제공하는 YOLOv8 Quantized 모델을 사용했다. 문제는 이것도 단순히 tflite 파일만 있다고 되는 게 아니었다. RubikPi에서 이를 돌리기 위해선 GStreamer 파이프라인 안에서 qtimltflite, qtimlvdetection 등의 특수 플러그인들을 사용해야 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1580&quot; data-start=&quot;1376&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;처음 파이프라인을 돌렸을 땐 화면 출력은 되지만, 추론 결과가 없었다. 그 뒤부터는 메타데이터를 받아오려 appsink에 연결하고, text/x-raw,format=utf8 포맷으로 바꿔야 한다는 것도 알게 됐다. 한 줄 한 줄 파이프라인을 추가하고 바꾸면서 겨우&amp;nbsp; 메타데이터 추출에 성공했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1580&quot; data-start=&quot;1376&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1580&quot; data-start=&quot;1376&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;내가 원하는건 해당 카메라 스트림으로부터 YOLO 모델이 의자 및 사람을 동시에 탐지됐을 때만 이벤트를 발생시키는 것이다. 사람이 앉아있는경우에 Arduino에 시리얼 통신으로 리니어 액추에이터를 구동시키도록 제어하는 것이 배리어프리 키오스크의 핵심 기능이었기 때문이다. 일단은 간단하게 접근했다. 단순히 라벨 배열을 저장하고, 그 안에 person과 chair가 동시에 포함돼 있는지를 판단해서 콘솔에 출력하게 구성했다. 이걸 구현하기까지 GStreamer의 appsink에서 버퍼를 받아오는 것부터, 메타데이터 문자열 파싱, 추론 결과 필터링까지, 한 줄 한 줄 디버깅하면서 오랜시간을 보내왔던 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1580&quot; data-start=&quot;1376&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-start=&quot;1163&quot; data-end=&quot;1189&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 경험을 통해 얻은 점&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;2482&quot; data-start=&quot;2320&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;처음에는 막막했다. OpenCV도 잘 안 돌아가고, 생소한 GStreamer을 통해 카메라 스트림을 처리해야했고 온디바이스AI에 대한 베이스도 없다보니 상당부분을 많은 시간을 투자하여 노력해왔다. 국내에선 물론 해외에도 정보가 많이 없어 거의 외국 커뮤니티와 Qualcomm 포럼에서 실마리를 찾아야 했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2591&quot; data-start=&quot;2484&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하지만 시간이 지나며 이 RubikPi를 다룬 경험이 단순히 AI 디바이스 조작경험이 아니라, Qualcomm이라는 플렛폼 생태계에서 어떻게 자사 칩셋과 자사 Ai Hub를 연계하여 온디바이스 AI 개발을 최적화하는지를 직접 느껴볼 수 있었던 좋은 실전 경험이었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2693&quot; data-start=&quot;2593&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;내가 직접 YOLO 모델을 양자화하고, 이를 tflite로 변환하고, RubikPi에서 실행하며 NPU를 활용한 결과를 메타데이터로 뽑아낸다는 것 자체가 엄청난 성장의 과정이었다고 본다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;2703&quot; data-end=&quot;2830&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;2703&quot; data-end=&quot;2830&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재는 의자와 사람이 동시에 감지되었을 때, Arduino로 시리얼 신호를 보내 리니어 액추에이터를 제어하여 휠체어 키오스크의 높낮이를 자동 조절하는&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #001d35; text-align: start;&quot;&gt;AIoT&lt;/span&gt;플렛폼 구조의 설계 및 구현이 완료되었다. 그동안 내가 흥미를 느끼고 관심있던 분야인 AI+ IOT 서비스를 직접 개발해본 값진 경험이었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-start=&quot;2832&quot; data-end=&quot;2971&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 RubikPi 프로젝트를 통해 On-Device AI의 시작을 경험했다. 단순히 모델을 &amp;ldquo;돌리는 것&amp;rdquo;이 아닌, 실제 환경에서 최적화된 형태로 &quot;연결하고 통제하는 법&quot;을 배웠다. 이번 프로젝트를 통해, 앞으로도 이러한 다양한 경험을 해나가면 성장하고자하는 목표가 생겼다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;854&quot; data-start=&quot;822&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI/Qualcomm</category>
      <category>ondevice ai</category>
      <category>qualcomm ai hub</category>
      <category>rubikpi</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/40</guid>
      <comments>https://basecoding.tistory.com/entry/%EA%B8%B0%EC%97%85%EC%97%B0%EA%B3%84-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-with-Qualcomm-RubikPi%EC%99%80-%ED%95%A8%EA%BB%98%ED%95%9C-On-Device-AI-%EA%B0%9C%EB%B0%9C#entry40comment</comments>
      <pubDate>Sun, 18 May 2025 12:57:04 +0900</pubDate>
    </item>
    <item>
      <title>[iOS Programming] 5. 프로그래밍으로 View 구성&amp;amp;배치(프로그래밍 뷰)</title>
      <link>https://basecoding.tistory.com/entry/iOS-Programming-5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9C%BC%EB%A1%9C-View-%EA%B5%AC%EC%84%B1%EB%B0%B0%EC%B9%98%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B7%B0</link>
      <description>&lt;h3 data-end=&quot;175&quot; data-start=&quot;164&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  주요 목차&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;415&quot; data-start=&quot;177&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;204&quot; data-start=&quot;177&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;프로그래밍으로 뷰를 배치하는 방법을 이해하자&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;243&quot; data-start=&quot;205&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;safeAreaLayoutGuide의 역할과 위치를 이해하자.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;286&quot; data-start=&quot;244&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃에서 사용되는 10가지 Anchor를 익히고 활용해보자.&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;356&quot; data-start=&quot;287&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LayoutGuide와 10가지 Anchor를 이용하여 스토리보드(&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;시각적인 인터페이스 빌더 - Interface Builder)&lt;/span&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;style6&quot; /&gt;
&lt;h3 data-end=&quot;436&quot; data-start=&quot;422&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1️⃣ 프로젝트 준비&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;614&quot; data-start=&quot;438&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;468&quot; data-start=&quot;438&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;프로젝트 이름: &lt;b&gt;programmingView&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;468&quot; data-start=&quot;438&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Navagator에서 ViewController.swift &amp;rarr; ConversionViewController.swift로 파일이름 변경 및 해당 파일 추가&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;614&quot; data-start=&quot;469&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ViewController.swift파일에서 해당 클래스 이름을 ConversionViewController로 이름 변경(class ViewController: UIViewController &amp;rarr; class ConversionViewController)&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;614&quot; data-start=&quot;469&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Main.storyboard에서 4번째 Indentity Inspector에서 클래스를 ConversionViewController로 변경하여 해당 ViewController의 Custom Class를 ConversionViewController로 수정&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;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오토레이아웃 프로그래밍의 핵심: &lt;span style=&quot;color: #ee2323;&quot;&gt;Layout Guide &amp;amp; Anchor&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ LayoutGuide &amp;amp; 10개의 Anchor&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃을 위한 가상의 사각형 영역&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;레이아웃 가이드는 10개의 앵커(Anchor)를 가지고 있다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;8개의 앵커는 뷰의 좌표관련 앵커이며 나머지 2개(wdithAnchor, heightAnchor)는 뷰의 크기관련 앵커이다&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-origin-width=&quot;1594&quot; data-origin-height=&quot;842&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmKmmH/btsNprvlZVL/kO0fm4wj4IoN8xx84kYvZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmKmmH/btsNprvlZVL/kO0fm4wj4IoN8xx84kYvZ0/img.png&quot; data-alt=&quot;LayoutGuide의 10개의 앵커들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmKmmH/btsNprvlZVL/kO0fm4wj4IoN8xx84kYvZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmKmmH%2FbtsNprvlZVL%2FkO0fm4wj4IoN8xx84kYvZ0%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;700&quot; height=&quot;370&quot; data-origin-width=&quot;1594&quot; data-origin-height=&quot;842&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LayoutGuide의 10개의 앵커들&lt;/figcaption&gt;
&lt;/figure&gt;
&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;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ &amp;nbsp;&lt;/span&gt;프로그래밍 오토레이아웃 기본 순서&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1104&quot; data-start=&quot;953&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;964&quot; data-start=&quot;953&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰 객체를 생성 (UILabel, UIButton ...)&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1022&quot; data-start=&quot;965&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;해당 뷰 객체의 translatesAutoresizingMaskIntoConstraints 속성값 = false 설정&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1050&quot; data-start=&quot;1023&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LayoutGuide에서 10개의 Anchor중 (x, y), (w, h)를 결정할 수 있는 앵커 중 원하는 Anchor를 선택하여 제약조건으로 추가 (ex. 수평 중앙 맞추고싶으면 &lt;b&gt;해당뷰 객체.centerXAnchor.constraint(...)&lt;/b&gt; )&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1050&quot; data-start=&quot;1023&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;앵커 설정 후, 해당 뷰 객체에 isActive 속성 값 = true 로 설정해주어야 해당 뷰에 걸린 앵커를 활성화 해주어야함&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1104&quot; data-start=&quot;1051&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;NSLayoutConstraint.activate([])를 활용해 앵커 설정들을 리스트안에 담아서 한 번에 활성화 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  &lt;u&gt;translatesAutoresizingMaskIntoConstraints&lt;/u&gt; 속성을 왜 false 로?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;해당 속성은 해당 뷰 객체에 기본적으로 설정되어있는 오토리사이징Autoresizing 기능을 해제해주는 설정이다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Autoresizing은 초기 iOS에서 다양한 Device 크기를 만족하는 App을 만들기 위해서 오토 리사이징 개념을 도입하였으나, 그러나 이는 다양성을 지원하기에는 한계가 있어 추후 autolayout를 추가하게 된 것. 우리는 오토리사이징이 아닌 이 오토레이아웃을 사용해야한다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Interface Builder: 인터페이스 빌더에서 컨트롤(뷰 아이템)을 놓으면, 자동으로 Autoresizing은 리셋되어, autolayout만 적용됨. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;반면, Programming 방식에서는 autoresizing이 디폴트로 설정되어있어 기본적으로 동작하도록 설정됨.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;그래서&amp;nbsp; 프로그래밍 방식으로 뷰 생성 및 배치시에는 해당 뷰 객체에 적용된 이 오토리사이징 기능을 해제하기 위해서 translatesAutoresizingMaskIntoConstraints를 false로 설정해주어야한다!&lt;/b&gt;&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️&amp;nbsp;&amp;nbsp;&lt;/span&gt;절대 레이아웃 프로그래밍&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;일단 오토레이아웃을 적용하기전에 먼저 기본 절대 레이아웃 방식으로 뷰를 생성배치 해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;ldquo;Hello, Autolayout&amp;rdquo;텍스트가 적힌 Label을 만들어보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1744867753592&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ConversionViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let helloLabel = UILabel(frame: CGRect(x: 100, y: 100, width: 200, height: 30))
helloLabel.text = &quot;Hello, Autolayout&quot;
helloLabel.backgroundColor = UIColor.green
helloLabel.font = UIFont.systemFont(ofSize: 30, weight: .bold)
helloLabel.textAlignment = .center
view.addSubview(helloLabel)
}
}&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. UILabel(frame: CGRect(x: 100, y: 100, width: 200, height: 30)) 로 사각형 레이블을 생성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. 해당 레이블에 텍스트 설정&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3. 배경색 및 폰트, 텍스트 중앙정렬 설정&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;4. 최상위 뷰 컨테이너인 view객체에 레이블 객체를 add하여 부착&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;자, 이제 위에서 배치한 레이블에 오토레이아웃을 적용시켜 배치해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️&amp;nbsp;&amp;nbsp;&lt;/span&gt;오토레이아웃 프로그래밍 실습1&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;화면의 중앙으로 &amp;ldquo;Hello, autolayout&amp;rdquo; 레이블을 레이아웃해보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1744868291387&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ConversionViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
... // 앞의 코드를 복사
// view.addSubview(helloLabel) 주석처리

helloLabel.translatesAutoresizingMaskIntoConstraints = false // 오토리사이징 해제
let centerXConstraint = helloLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0)
let centerYConstraint = helloLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0)

centerXConstraint.isActive = true // 각 제약조건 활성화
centerYConstraint.isActive = true // 각 제약조건 활성화
view.addSubview(helloLabel)
}
}&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;위처럼 생성된 뷰 객체(UILabel)에 프로그래밍으로 제약조건 방정식을 각각 작성해주고, 활성화시킨 다음 뷰 컨테이너에 부착해주면 화면에 오토레이아웃이 적용되어 나타난다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 코드를 보면 2개의 제약조건 방정식이 기술된 것을 확인해볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;let centerXConstraint = helloLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0) &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;let centerYConstraint = helloLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0) &lt;/span&gt;&lt;/blockquote&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. 헬로우레이블의 CenterX 좌표를 view의 CenterX와 동일시하라. 즉 레이블의 수평위치를 화면의 수평중앙으로.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. 헬로우레이블의 CenterY 좌표를 view의 CenterY와 동일시하라. 즉 레이블의 수직위치를 화면의 수직중앙으로. &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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️&amp;nbsp;&amp;nbsp;&lt;/span&gt;오토레이아웃 프로그래밍 실습2&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이번엔 &amp;ldquo;Hello, autolayout&amp;rdquo; 텍스트의 레이블을 왼쪽여백 20, 오른쪽여백 20, 톱여백 100으로 주어 배치해보자.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉 화면상에서 왼쪽으로 20px, 오른쪽에서 20px, 상단에서 100px 떨어진 레이블이 화면에 출력될 것이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;하단 여백은 지정해주지 않았으니 이 레이블의 height는 텍스트 사이즈만큼만 차지한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1744899456411&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ConversionViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
...
view.addSubview(helloLabel)
helloLabel.translatesAutoresizingMaskIntoConstraints = false
helloLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor,
constant: 20).isActive = true
helloLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor,
constant: -20).isActive = true
helloLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant:
100).isActive = true
}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 코드를 보면 3개의 제약조건 방정식이 기술된 것을 확인해볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; helloLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;helloLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;helloLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 100)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. 헬로우레이블의 좌측시작좌표값을 (safeArea의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;좌측시작좌표값 + 20)의 값으로 &lt;/span&gt;설정하라.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. 헬로우레이블의 우측시작좌표값을 (&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;safeArea의&amp;nbsp;우&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;측시작좌표값 - 20)의 값으로&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;설정하라.&amp;nbsp;&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;3. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;헬로우레이블의 상단시작좌표값을 (&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;safeArea의&amp;nbsp;상단&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;시작좌표값 + 100)의 값으로&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;설정하라.&amp;nbsp;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;즉 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;헬로우레이블은 화면에서 왼쪽여백 20, 오른쪽여백 20, 상단여백 100 에 배치된다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IOS</category>
      <category>ios</category>
      <category>프로그래밍뷰</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/39</guid>
      <comments>https://basecoding.tistory.com/entry/iOS-Programming-5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9C%BC%EB%A1%9C-View-%EA%B5%AC%EC%84%B1%EB%B0%B0%EC%B9%98%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B7%B0#entry39comment</comments>
      <pubDate>Thu, 17 Apr 2025 23:23:13 +0900</pubDate>
    </item>
    <item>
      <title>[iOS Programming] 4-2. 오토레이아웃 보충</title>
      <link>https://basecoding.tistory.com/entry/iOS-Programming-4-2-%EC%98%A4%ED%86%A0%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EB%B3%B4%EC%B6%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이전에는 아이폰 기종이 하나의 사이즈였으나, 점점 발전하며 아이폰 SE, PRO 등 다양한 사이즈와 화면 비율로 출시가 되면서 사이즈에 구애받지않고 시각적으로 동일한 화면을 구현해야하기때문에 오토레이아웃을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우리가 오토레이아웃을 수행할때는 뷰의 제약사항이 있다. 뷰의 제약사항을 바탕으로 체계 내의 모든 뷰의 크기와 위치를 동적으로 계산하게 된다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;어플리케이션을 사용할때 발생하는 외부변경이 있고 내부변경이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이러한 외부변경과 내부변경에 동적으로 반응하는 사용자 인터페이스를 가능하게해주는 것이 오토레이아웃이다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;so, autoLayout이 요구되는 그러한 외부변경과 내부변경이 무엇인지 알아보자.&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;외부변경&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;외부변경이라는 것은 슈퍼뷰의 크기나 모양이 변경될때 발생하는 것을 외부변경이라고 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt; &lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;사용자가 아이패드의 분할 뷰(Split View)를 사용하거나 사용하지 않는 경우(iOS)&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;장치를 회전하는 경우(iOS)&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;활성화 콜(active call)과 오디오 녹음 바가 보여지거나 사라지는 경우(iOS)&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;다른 크기의 클래스(폰트)를 지원하기 원하는 경우&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;다른 크기의 스크린을 지원하기 원하는 경우&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위의 케이스들이 바로 외부변경의 예시들이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이러한 변경사항이라는게 대부분 실행시간에 발생하기에, 이러한 변경이 발생하면 어플리케이션으로 동적으로 응답이 되어야 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;내&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부변경&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;내부변경이라는 것은 사용자 인터페이스의 뷰의 크기 또는 설정이 변경되었을때 발생하는 변경을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;애플리케이션 변경에 의해 콘텐츠가 보여지는 경우&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;애플리케이션이 국제화를 지원하는 경우&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;애플리케이션이 동적 타입을 지원하는 경우&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;신문기사, 텍스트, 이미지 등등의 앱 내부의 앱 콘텐츠가 변경이 됐을때 새로운 콘텐츠가 예전과는 다른 레이아웃을 필요로 할텐데, 이것이 바로 내부변경(앱 콘텐츠)으로 인한 오토레이아웃의 필요성이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ 오토레이아웃의 필요성&lt;/span&gt;&lt;/b&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아래는 오토레이아웃이 필요한 케이스들이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;애플리케이션이 실행되는 iOS 기기의 스크린 화면의 크기가 다양한 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;애플리케이션이 실행되는 iOS 기기의 스크린이 회전할 수 있는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;상태표시줄(Status Bar)에 전화 중임을 나타내는 액티브 콜(active call)과 오디오 녹음 중임을 나타내는 오디오 바가 보여지거나 사라지는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;애플리케이션의 콘텐츠가 동적으로 보여지는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;애플리케이션이 지역화(Localization)를 지원하는 경우 (한국,미국, 일본 등 각 국가에 맞게)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;애플리케이션이 동적 타입을 지원하는 경우&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, 인터페이스의 절대적인 좌표가 아니라&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;동적으로 상대적인 좌표를 나타낼 필요가 있을때&lt;/u&gt;&lt;/span&gt;가 오토레이아웃이 필요하다.&lt;/b&gt;&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ 오토레이아웃의 속성&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오토레이아웃의 속성은 아래와같은 정렬 사각형을 기반으로한다.&lt;/span&gt;&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;blob&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;524&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/omhDz/btsNhKB1LwZ/heytlkwwe7Knzy3GCYUYv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/omhDz/btsNhKB1LwZ/heytlkwwe7Knzy3GCYUYv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/omhDz/btsNhKB1LwZ/heytlkwwe7Knzy3GCYUYv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FomhDz%2FbtsNhKB1LwZ%2Fheytlkwwe7Knzy3GCYUYv0%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;500&quot; height=&quot;420&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;524&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&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Width:&lt;/b&gt; 정렬 사각형의 너비&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Height:&lt;/b&gt; 정렬 사각형의 높이&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Top:&lt;/b&gt; 정렬 사각형의 상단(margin)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Bottom:&lt;/b&gt; 정렬 사각형의 하단&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;(margin)&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Baseline:&lt;/b&gt; 텍스트의 하단(ex. 텍스트가 주어지면 해당 텍스트의 하단. 밑부분)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Horizontal:&lt;/b&gt; 수평&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Vertical:&lt;/b&gt; 수직&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Leading:&lt;/b&gt; 리딩 (텍스트를 읽을때 시작 방향, LTR에서는 왼쪽, RTL에서는 오른쪽)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Trailing:&lt;/b&gt; 트레일링 (텍스트 끝 방향, LTR에서는 오른쪽, RTL에서는 왼쪽)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;CenterX:&lt;/b&gt; 수평 중심 (수평 즉 가로축의 중앙지점. so, 뷰들의 x축은 해당 중앙지점에 고정이면서 y축만 다르게 뷰들이 배치)&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;CenterY:&lt;/b&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;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ 안전 영역 (Safe area)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;안전 영역은, 콘텐츠가 상태바, 네비게이션바, 툴바, 탭바 등 화면의 주요 콘텐츠들을 가리지 않도록 방지하고자 존재하는 영역.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 이 안전 영역에서만 콘텐츠를 배치하도록 강제되어진다.&amp;nbsp;&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;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 안전 영역은 ios11 버전부터 사용가능하나, 이전 버전들은 상-하단 레이아웃 가이드를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ 제약 조건(Constraint)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이웃이 가지고있는 속성 대비 나의 속성은 얼마만큼 떨어져있느냐 - 어떻게 정의할 수 있느냐 =&amp;gt; 제약&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000; text-align: start;&quot;&gt;제약은 방정식이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어 A라는 뷰와 B라는 뷰가 있다면, 이 뷰 사이의 관계를 위에서 보았던 오토레이아웃의 속성들을 통해서 정의하게된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉, 그렇기에 제약은 아래와 같은 방정식 형태로 나타낼 수 있는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;435&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mHOH7/btsNhlbRh8K/10nkoAieInmg1KZqgpsHhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mHOH7/btsNhlbRh8K/10nkoAieInmg1KZqgpsHhk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mHOH7/btsNhlbRh8K/10nkoAieInmg1KZqgpsHhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmHOH7%2FbtsNhlbRh8K%2F10nkoAieInmg1KZqgpsHhk%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;435&quot; height=&quot;187&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;187&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIQ2KI/btsNhXabrY6/uDayLyaQOirsK0Xfk2Ksf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIQ2KI/btsNhXabrY6/uDayLyaQOirsK0Xfk2Ksf1/img.png&quot; data-alt=&quot;위 A-B 뷰 간의 제약 방정식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIQ2KI/btsNhXabrY6/uDayLyaQOirsK0Xfk2Ksf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIQ2KI%2FbtsNhXabrY6%2FuDayLyaQOirsK0Xfk2Ksf1%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;500&quot; height=&quot;88&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;149&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;위 A-B 뷰 간의 제약 방정식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&quot;B뷰의 왼쪽 끝은 A뷰 오른쪽 끝보다 8만큼 떨어져있다&quot; 라는 제약을 나타낸다.&lt;br /&gt;A뷰가 가지고있는 trailing이라는 속성과 B뷰가 가지고있는 Leading이라는 속성이 이런식으로 관계가 형성되어있다.&lt;br /&gt;-&amp;gt; 이것이 제약조건.&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;Item1:&lt;/b&gt; 방정식에 있는 첫 번째 아이템(B View)이다. 첫 번째 아이템은 반드시 뷰 또는 레이아웃 가이드이어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Attribute1:&lt;/b&gt; 첫 번째 아이템에 대한 속성이다. 이 경우, B View의 리딩(Leading)이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Multiplier:&lt;/b&gt; Attribute2에 곱해지는 가중치 값이다. 이 경우 1.0이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Item2:&lt;/b&gt; 방정식에 있는 두 번째 아이템(A View)이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Attribute2:&lt;/b&gt; 두 번째 아이템에 대한 속성이다. 이 경우, A View의 트레일링(Trailing)이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Constant:&lt;/b&gt; 두 번째 아이템의 속성에 더해지는 상수 값이다.&lt;/span&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 고유 콘텐츠 크기 (Intrinsic Content Size)&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;: 뷰의 고유 콘텐츠 크기는 뷰가 갖는 원래의 크기&lt;/b&gt;&lt;/blockquote&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: #000000;&quot;&gt;&lt;span&gt;&lt;b&gt;if UILabel이 하나 있다면, 이 라벨의 고유 콘텐츠 크기는?&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&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;b&gt;= &lt;u&gt;라벨의 텍스트 크기&lt;/u&gt;&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;b&gt;이미지의 고유 콘텐츠 크기는?&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&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;b&gt;= &lt;u&gt;이미지 자체의 크기&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⬛️ 제약 우선도(Constraint Priorities)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #404040; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;콘텐츠 허깅 우선도(Content Hugging Priority)&lt;/b&gt;&lt;/u&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰가 자신의 콘텐츠 고유 사이즈보다 커지지 않도록 제한한다.&lt;/li&gt;
&lt;li&gt;다른 제약사항보다 콘텐츠 허깅 우선도가 높으면 뷰가 콘텐츠 사이즈보다 커지지 않는다.&lt;/li&gt;
&lt;li&gt;즉 현재 상태를 유지하려고 딱 달라붙어있는 - 허깅&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;u&gt;&lt;b&gt;콘텐츠 축소 방지 우선도(Content Compression Resistance Priority)&lt;/b&gt;&lt;/u&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뷰가 자신의 콘텐츠 고유 사이즈보다 작아지지 않도록 제한한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #404040; text-align: left;&quot;&gt;다른 제약사항보다 &lt;span style=&quot;color: #404040; text-align: left;&quot;&gt;콘텐츠 축소 방지&lt;/span&gt;&lt;span style=&quot;color: #404040; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;우선도가&lt;/span&gt;&lt;/span&gt; 높으면 뷰가 콘텐츠 사이즈보다 축소되지 않는다.&lt;/li&gt;
&lt;li&gt;ex) Label의 고유 콘텐츠 사이즈는 이 라벨의 텍스트 크기만큼인데, 라벨의 크기가 더 줄어든다면 이 라벨에 쓰인 텍스트를 알아볼 수 없을 것이다. 이럴때 이 Label의 축소 방지 우선도 값을 적절히 높게 설정해주면 축소를 방지할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;</description>
      <category>IOS</category>
      <category>autolayout</category>
      <category>ios</category>
      <category>safe area</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/38</guid>
      <comments>https://basecoding.tistory.com/entry/iOS-Programming-4-2-%EC%98%A4%ED%86%A0%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EB%B3%B4%EC%B6%A9#entry38comment</comments>
      <pubDate>Fri, 11 Apr 2025 14:27:29 +0900</pubDate>
    </item>
    <item>
      <title>[iOS Programming] 4. 오토레이아웃(autoLayout)</title>
      <link>https://basecoding.tistory.com/entry/iOS-Programming-4-%EC%98%A4%ED%86%A0%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83autoLayout</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃은 여러 아이폰 및 아이패드 등 다양한 기기-다양한 화면 크기에서도 UI를 안정적으로 일관되게 구성할 수 있도록 해주는 핵심 기능이다. 특히 다양한 디바이스가 존재하고 사용자의 인터페이스 사용 방식이 복잡해진 현재의 모바일 환경에서는 오토레이아웃의 역할이 매우 중요하다.&lt;/span&gt;&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;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; font-size: 1.62em; letter-spacing: -1px;&quot;&gt;⬛️ 오토레이아웃의 필요성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하나의 iOS 앱은 iPhone SE처럼 작은 화면부터 iPad Pro와 같은 대형 화면까지 다양한 디바이스에서 실행된다. 또한, 모바일 환경은 가로/세로 회전과 분할 화면 등 다양한 환경 변화가 빈번히 일어나기에 이에 잘 대응해야한다. 각각의 화면에서 UI가 적절하게 보여지기 위해서는 레이아웃이 유연하게 대응할 수 있어야 하며, 이를 위해 등장한 것이 오토레이아웃이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;오토레이아웃 이전에는 오토리사이징이 존재했지만, iOS 6 이후 오토레이아웃을 사용하면서 오토리사이징은 잘 사용하지 않는다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 오토레이아웃과 오토리사이징을 동시에 적용할 수도 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  오토리사이징(autoResizing)&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예전 방식으로, 슈퍼뷰 크기에 따라 하위 뷰의 크기나 위치를 자동 조정하는 방식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;고정 여백 설정과 비례 크기 조절이 가능하지만, 복잡한 UI에는 적합하지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;iOS 6 이후 오토레이아웃이 도입되면서 점차 사용 빈도가 줄어들고 있음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  오토레이아웃(autoLayout)&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰 간의 상대적인 제약조건(Constraints)을 통해 동적으로 레이아웃을 구성하는 방식&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;다양한 화면 크기, 방향, 디바이스에 대응 가능한 반응형 UI를 만들 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Auto Layout은 인터페이스 빌더와 코드 양쪽에서 모두 적용 가능하며, 더욱 정밀한 UI 제어가 가능&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;⬛️ &amp;nbsp;&lt;/span&gt;오토레이아웃의 핵심 개념&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하나의 View에 대하여 어떠한 화면의 크기에 대해서도 좌측상단좌표(left, height)와 크기(width, height)를 계산할 수 있으면 Satisfiable layout이라고 하는데, 화면상의 모든 View가 Satisfiable layout이면 이 화면은 오토레이아웃을 만족하게된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, View의 크기(너비, 높이)와 이웃 View와 간격으로 Satisfiable Layout를 이루는 것을 오토레이아웃.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때의 이웃은 가장 가까운 이웃(Default)을 말하는데 가까운 이웃이 없는 경우는 부모 뷰를 이웃으로 본다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  주요 용어 및 속성&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;leading / trailing / left / right&lt;/b&gt;: 오토레이아웃의 정의에 필요한 속성이자 UI의 방향성과 관련된 개념이다.&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; 중동국가에서는 leading = right, trailing = left 이고 그 외 국가에서는 leading = left, trailing = right 이다.&amp;nbsp; 즉, 그 외 국가에 속하는 우리나라의 경우엔 &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;leading속성은 뷰의 왼쪽을 뜻하고 trailing은 뷰의 오른쪽을 뜻한다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Safe Area&lt;/b&gt;: iOS 11 이후 도입된 개념으로, 상태바, 네비게이션 바, 홈 인디케이터 등 시스템 UI 요소를 침범하지 않도록 제한된 뷰 영역을 말한다. Apple이 safe area 밖에 View를 배치하지 말 것 을 권고하면서 나온 영역으로, 앱의 가장 중요한 디폴트 영역인 상단 탑바나 하단바 등등 주요 영역에 사용자 지정 뷰들이 침범하지않도록 만들어둔 공간이다. 사용자 지정 뷰들은 이 Safe Area안에서만 존재하게된다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;179&quot; data-start=&quot;138&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  제약조건과 여백 계산 (Constraints &amp;amp; Spacing)&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃에서 레이아웃을 결정짓는 가장 중요한 구성요소는 &lt;b&gt;제약조건(Constraints)&lt;/b&gt;이다. 이 제약조건을 통해 뷰 간의 상대적 관계를 정의하게 되며, &lt;b&gt;여백(margin)&lt;/b&gt;이나 &lt;b&gt;크기(size)&lt;/b&gt;, &lt;b&gt;위치(position)&lt;/b&gt; 등을 세밀하게 제어할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;333&quot; data-start=&quot;181&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃에서 &lt;b&gt;Constraint(제약조건)&lt;/b&gt;은 단순히 뷰의 위치나 크기를 정하는 것 이상으로, &lt;b&gt;뷰 간의 관계를 수식 형태로 정확하게 표현&lt;/b&gt;하는 도구이다. 이 제약조건을 통해 &lt;b&gt;여백(margin), 상대적 위치, 크기 비율&lt;/b&gt;까지 모두 조정할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;378&quot; data-start=&quot;335&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃에서의 제약 조건은 다음과 같은 &lt;b&gt;수학적 표현&lt;/b&gt;으로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1744263883095&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;item1.attribute1 = multiplier &amp;times; item2.attribute2 + constant&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;477&quot; data-start=&quot;449&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;477&quot; data-start=&quot;449&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  제약조건 예시: 두 뷰 사이 여백 설정&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1744263904875&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;RedView.leading = 1.0 &amp;times; BlueView.trailing + 8.0&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;676&quot; data-start=&quot;541&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;676&quot; data-start=&quot;541&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 수식은 &lt;b&gt;RedView의 leading(왼쪽)&lt;/b&gt; 위치가 &lt;b&gt;BlueView의 trailing(오른쪽)&lt;/b&gt; 위치보다 8pt 만큼 오른쪽에 있다는 의미이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;676&quot; data-start=&quot;541&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, 두 뷰 사이의 &lt;b&gt;수평 여백이 8pt&lt;/b&gt;가 되도록 제약이 설정된 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;917&quot; data-start=&quot;678&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;917&quot; data-start=&quot;706&quot;&gt;
&lt;tr data-end=&quot;740&quot; data-start=&quot;706&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;718&quot; data-start=&quot;706&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;RedView&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;740&quot; data-start=&quot;718&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제약을 적용할 뷰 (Item 1)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;778&quot; data-start=&quot;741&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;754&quot; data-start=&quot;741&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;.leading&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;778&quot; data-start=&quot;754&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;적용할 속성 (Attribute 1)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;809&quot; data-start=&quot;779&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;787&quot; data-start=&quot;779&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1.0&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;809&quot; data-start=&quot;787&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;배수 계수 (Multiplier)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;844&quot; data-start=&quot;810&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;823&quot; data-start=&quot;810&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;BlueView&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;844&quot; data-start=&quot;823&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기준이 되는 뷰 (Item 2)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;885&quot; data-start=&quot;845&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;859&quot; data-start=&quot;845&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;.trailing&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;885&quot; data-start=&quot;859&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기준 뷰의 속성 (Attribute 2)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;917&quot; data-start=&quot;886&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;895&quot; data-start=&quot;886&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;+8.0&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;917&quot; data-start=&quot;895&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;고정 여백 값 (Constant)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-end=&quot;980&quot; data-start=&quot;919&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이런 방식으로 &lt;b&gt;뷰 사이 간격&lt;/b&gt;, &lt;b&gt;위치 정렬&lt;/b&gt;, &lt;b&gt;비율 설정&lt;/b&gt; 등을 세밀하게 지정할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;⬛️ &amp;nbsp;&lt;/span&gt;오토레이아웃 도구 소개 (Xcode Interface Builder 기준)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1) Align Tool&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여러 뷰를 수평 또는 수직 방향으로 정렬할 때 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;정렬 축과 기준 뷰를 설정하여 간단하게 레이아웃을 맞출 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;원하는 뷰들을 선택하고 Align Tool을 클릭&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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-origin-width=&quot;598&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/G9k79/btsNfQjgxEt/1bF8lSwWiH9Kb83PvxKlK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/G9k79/btsNfQjgxEt/1bF8lSwWiH9Kb83PvxKlK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/G9k79/btsNfQjgxEt/1bF8lSwWiH9Kb83PvxKlK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FG9k79%2FbtsNfQjgxEt%2F1bF8lSwWiH9Kb83PvxKlK0%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;300&quot; height=&quot;302&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;602&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2) Pin Tool (Add New Constraints)&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰의 여백, 고정된 너비/높이, 비율 제약 등을 설정할 수 있는 도구&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Pin tool은 뷰의 상대적 위치와 크기에 대한 제약 조건을 적용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;설정 후 빨간 점선으로 표시된 제약은 아직 완전히 적용되지 않은 상태이며, Update Frames나 Resolve Auto Layout Issues를 통해 반영해야 한다.&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-origin-width=&quot;540&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bR6rNb/btsNhnUdagx/wuEyie2o9kkiEpZeceTy80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bR6rNb/btsNhnUdagx/wuEyie2o9kkiEpZeceTy80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bR6rNb/btsNhnUdagx/wuEyie2o9kkiEpZeceTy80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbR6rNb%2FbtsNhnUdagx%2FwuEyie2o9kkiEpZeceTy80%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;300&quot; height=&quot;401&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3) Resolve Auto Layout Issues&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제약조건 충돌, 누락, 불완전 적용 등의 문제를 해결하는 데 사용&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;일반적인 자동 레이아웃 문제를 해결하기위한 여러 가지 옵션을 제공&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;상단은 현재 선택된 뷰, 아래쪽 옵션은 모든 뷰에 영향&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;주요 기능&lt;/b&gt;:&lt;/u&gt;&lt;/span&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Clear Constraints&lt;/b&gt;: &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;해당 제약조건을 모두 지움, &lt;/span&gt;모든 제약조건을 제거&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Add Missing Constraints&lt;/b&gt;: 필수 제약조건을 자동으로 추가, &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;추가적으로 제약 조건들을 자동으로 생성&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Reset to Suggested Constraints&lt;/b&gt;: &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;현재 적용된 제약 조건들을 지우고 필요한 제약 조건들을 자동으로 생성하는 옵션, &lt;/span&gt;Xcode가 제안하는 기본 제약조건으로 재설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Update Constraint Constants&lt;/b&gt;: &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;현재의 Constraint에서 UIView의 이동후 이 동값에 대한 상수를 적용하고자 하는 경우,&lt;/span&gt;뷰의 현재 위치와 크기에 맞춰 상수 값 업데이트&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;⬛️&amp;nbsp; 상대적&amp;nbsp;&lt;/span&gt;콘텐츠 크기 제어&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  콘텐츠(뷰 객체) 크기&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;: 뷰 객체의 너비와 높이&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;원칙적으로는 Constraint를 적용하여 크기를 설정하여야 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;일부 뷰 객체는 디폴트로 크기가 정해지는 것도 있음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  고유 콘텐츠 크기 (Intrinsic Content Size)&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;: 뷰 객체가 표시할 내용을 기반으로 뷰의 크기가 어느 정도될 지에 대한 정보&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;라벨의 고유 콘텐츠 크기는 표시할 텍스트 크기에 기반을 둔다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: left;&quot;&gt;이미지 뷰의 고유 콘텐츠 크기는 직접 선택한 이미지 크기이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UILabel, UIButton, UIImageView 등은 콘텐츠 자체의 크기를 기준으로 기본 크기를 결정한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예: UILabel은 텍스트 길이에 따라, UIImageView는 이미지의 원본 해상도에 따라 intrinsic size가 달라진다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  상대적 콘텐츠 크기&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여러 개의 뷰 객체가 동시에 크기가 변경되어야 하는 경우 콘텐츠의 크기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;⬛️&amp;nbsp; 콘텐츠 크기의 우선 순위&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  허깅 우선순위 (Hugging Priority)&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰가 &lt;b&gt;&quot;지금보다 더 커지지 않으려는 정도&quot;&lt;/b&gt;를 의미&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;늘어나기 싫어하는 우선순위 (낮으면 잘 늘어난다, 고무밴드와 같다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;크기에 대한 설정이 없는 뷰 객체는 가장 낮은 우선 순위를 갖는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우선순위 값이 높을수록 늘어나기 싫어하므로 뷰는 현재 크기를 유지하려고 하며, 다른 뷰가 확장되도록 유도&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  압축 저항 우선순위 (Compression Resistance Priority)&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰가 &lt;b&gt;&quot;지금보다 작아지지 않으려는 정도&quot;&lt;/b&gt;를 의미&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;줄어들기 싫어하는 우선순위 (낮으면 잘 줄어든다, 스프링과 같다)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;크기에 대한 설정이 없는 뷰 객체는 가장 낮은 우선 순위를 갖는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 값이 높을수록 크기압축에 더욱 저항하므로 뷰는 크기가 줄어드는 것을 거부하고, 대신 다른 뷰가 줄어들게 됨&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;⬛️&amp;nbsp; Stack View&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제약조건 없이도 간단한 레이아웃을 잡을 수 있는 방법이 있다. 바로 &lt;b&gt;UIStackView&lt;/b&gt;를 활용하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-end=&quot;1300&quot; data-start=&quot;1282&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  StackView란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1411&quot; data-start=&quot;1301&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;StackView는 여러 뷰들을 일렬로 정렬하고 자동으로 간격과 정렬을 조절해주는 컨테이너 뷰이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1411&quot; data-start=&quot;1301&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;복잡한 제약 없이도 기본적인 레이아웃을 빠르게 잡을 수 있어서 자주 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1411&quot; data-start=&quot;1301&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;스택 뷰는 복잡한 제약 조건을 도입하지 않고도 자동 레이아웃의 기능을 쉽게 활용할 수있는 방법을 제공해주는 유용한 도구인 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-end=&quot;1442&quot; data-start=&quot;1413&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1442&quot; data-start=&quot;1415&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;안드로이드의 LinearLayout과 유사하다&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-end=&quot;1466&quot; data-start=&quot;1444&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;1466&quot; data-start=&quot;1444&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅ StackView의 주요 속성&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1659&quot; data-start=&quot;1468&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1659&quot; data-start=&quot;1496&quot;&gt;
&lt;tr data-end=&quot;1541&quot; data-start=&quot;1496&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1507&quot; data-start=&quot;1496&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;axis &lt;/b&gt;(UIStackView only)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1541&quot; data-start=&quot;1507&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;오리엔테이션 지정:&lt;/b&gt; 정렬 방향 (horizontal 또는 vertical)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1576&quot; data-start=&quot;1542&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1558&quot; data-start=&quot;1542&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;alignment&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1576&quot; data-start=&quot;1558&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오리엔테이션의 수직 방향에서 자식 뷰들의 위치-정렬방식 지정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1630&quot; data-start=&quot;1577&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1596&quot; data-start=&quot;1577&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;distribution&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1630&quot; data-start=&quot;1596&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;자식 뷰들을 오리엔테이션 방향에 따라 분배 방법 지정, 공간 분배 방식 (fill, fillEqually 등)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1659&quot; data-start=&quot;1631&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1645&quot; data-start=&quot;1631&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;spacing&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-end=&quot;1659&quot; data-start=&quot;1645&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;distribution에서 자식 뷰들 사이의 간격, 자식 뷰 간의 간격&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;1696&quot; data-start=&quot;1666&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;⬛️&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;StackView 실습: 로그인 화면 만들기&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1652&quot; data-origin-height=&quot;906&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xTsv5/btsNgBTf9zT/1ROEiEFdUwkt5ZT5klr9tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xTsv5/btsNgBTf9zT/1ROEiEFdUwkt5ZT5klr9tk/img.png&quot; data-alt=&quot;로그인화면 구성도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xTsv5/btsNgBTf9zT/1ROEiEFdUwkt5ZT5klr9tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxTsv5%2FbtsNgBTf9zT%2F1ROEiEFdUwkt5ZT5klr9tk%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;700&quot; height=&quot;384&quot; data-origin-width=&quot;1652&quot; data-origin-height=&quot;906&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;/p&gt;
&lt;h3 data-end=&quot;1715&quot; data-start=&quot;1698&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✔︎ 1단계: 기본 구성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1882&quot; data-start=&quot;1716&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1778&quot; data-start=&quot;1716&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UILabel(Login ID), UITextField, UILabel(Password), UITextField, UIButton(OK)를 스토리보드 뷰컨트롤러의 적절한 위치에 놓기&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1847&quot; data-start=&quot;1779&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Login ID, UITextField 두 컴포넌트를 나란히 배치하고 동시에 선택하여 Editor &amp;gt; Embed In &amp;gt; StackView를 적용 -&amp;gt; 이러면 라벨과 텍스트필드가 하나의 스택뷰 컨테이너에 포함되어짐&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1882&quot; data-start=&quot;1848&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;StackView의 배경색을 노란색으로 설정&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1882&quot; data-start=&quot;1848&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 과정과 마찬가지로 Password, UITextField를 동시에 선택한 후 StackView를 적용 &amp;amp; StackView 배경색을 노란색으로 변경&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1882&quot; data-start=&quot;1848&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 1~4 과정을통해 만들어진 두 개의 StackView와 OK버턴을 동시에 선택한 후 이들에 대하여 또하나의 StackView를 적용 -&amp;gt; 이러면 2개의 스택뷰와 하나의 버튼 컴포넌트를 포함하고있는 하나의 스택뷰가 존재할 것이다. 이 최상위 스택뷰의 배경색을 파란색으로 설정해주어 색으로 구분해주자.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-end=&quot;1912&quot; data-start=&quot;1884&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;1912&quot; data-start=&quot;1884&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✔︎ 2단계: 바깥 최상위 StackView에 속성 적용&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2018&quot; data-start=&quot;1913&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1936&quot; data-start=&quot;1913&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Alignment&lt;/b&gt;: Fill&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1961&quot; data-start=&quot;1937&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Distribution&lt;/b&gt;: Fill&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1979&quot; data-start=&quot;1962&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Spacing&lt;/b&gt;: 10&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1979&quot; data-start=&quot;1962&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Constraint 설정&lt;/b&gt;: Add New Constraints(Pin Tool)에서 좌우 여백 20으로 설정, Align Tool에서 수직 &amp;amp; 수평 중앙 정렬(Horizontally&amp;amp;Vertically in Container값 0으로 설정)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-end=&quot;2059&quot; data-start=&quot;2020&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;2059&quot; data-start=&quot;2022&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이처럼 스택뷰를 통해 이전처럼 복잡한 제약 조건을 도입하지 않고도 자동 레이아웃의 기능을 쉽게 활용할 수 있어, 훨씬 간단하게 구조를 잡을 수 있다&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-end=&quot;2088&quot; data-start=&quot;2061&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;2088&quot; data-start=&quot;2061&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✔︎ 3단계: 내부 2개의 StackView에 각각 속성 적용&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;1913&quot; data-end=&quot;2018&quot;&gt;
&lt;li data-start=&quot;1913&quot; data-end=&quot;1936&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Alignment&lt;/b&gt;: Fill&lt;/span&gt;&lt;/li&gt;
&lt;li data-start=&quot;1937&quot; data-end=&quot;1961&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Distribution&lt;/b&gt;: Fill&lt;/span&gt;&lt;/li&gt;
&lt;li data-start=&quot;1962&quot; data-end=&quot;1979&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Spacing&lt;/b&gt;: 10&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2241&quot; data-start=&quot;2089&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot; data-end=&quot;2241&quot; data-start=&quot;2179&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-start=&quot;2061&quot; data-end=&quot;2088&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✔︎ 4단계: Login ID와 Password 라벨 너비를 동일한 크기로 정렬&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Login ID를 Ctrl+Drag -&amp;gt; Password에서 Drop&lt;/span&gt;&lt;/blockquote&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;h3 style=&quot;color: #000000; text-align: center;&quot; data-start=&quot;1444&quot; data-end=&quot;1466&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c1bef9; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 결과 화면&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;1936&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTTJD8/btsNf8qvvm9/Nw20kiNKN4Mjvv4vHTUgLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTTJD8/btsNf8qvvm9/Nw20kiNKN4Mjvv4vHTUgLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTTJD8/btsNf8qvvm9/Nw20kiNKN4Mjvv4vHTUgLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTTJD8%2FbtsNf8qvvm9%2FNw20kiNKN4Mjvv4vHTUgLk%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;500&quot; height=&quot;949&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;1936&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;오토레이아웃은 단순한 레이아웃 도구를 넘어서, 다양한 화면 환경에 최적화된 &lt;b&gt;유연하고 반응형&lt;/b&gt; UI를 구성할 수 있게 해주는 핵심 기술이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제약조건과 우선순위를 적절히 조합하고, 다양한 실습을 통해서 이 autoLayout을 어떻게 적용할 수 있는지 잘 익혀두는 것이 중요할 것 같다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>IOS</category>
      <category>autolayout</category>
      <category>ios</category>
      <category>stackview</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/37</guid>
      <comments>https://basecoding.tistory.com/entry/iOS-Programming-4-%EC%98%A4%ED%86%A0%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83autoLayout#entry37comment</comments>
      <pubDate>Fri, 11 Apr 2025 01:47:30 +0900</pubDate>
    </item>
    <item>
      <title>[iOS Programming] 3. 뷰와 뷰 계층 구조(View &amp;amp; View Hierarchy)</title>
      <link>https://basecoding.tistory.com/entry/iOS-Programming-3-%EB%B7%B0%EC%99%80-%EB%B7%B0-%EA%B3%84%EC%B8%B5-%EA%B5%AC%EC%A1%B0View-View-Hierarchy</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;iOS 에플리케이션에서 화면 UI를 구성하는 기본적인 단위, 화면에 보이는 UI요소들을 View 라고한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;이러한 View들은 뷰들 간에 계층적으로 구성되며, 이렇게 구성된 View 계층을 View Hierarchy라고 한다.&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이번에는 IOS 에플리케이션에서 화면 UI를 구성하는 뷰와 그 뷰들 간의 계층 구조에 대해서 알아보자.&lt;/b&gt;&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;▶️ 뷰(View)&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용자에게 보일 수 있는 객체&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰는 UIView의 인스턴스이거나 &lt;b&gt;UIView클래스 하위 클래스&lt;/b&gt;의 인스턴스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;통상적으로 클래스 계층에서 단말 뷰를 컨트롤 또는 위젯이라 부름&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;뷰는 자신을 어떻게 그리는지 알고있음&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;뷰는 터치 등등의 이벤트 처리 가능&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;뷰 인스턴스는 뷰 계층 구조상에 존재&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: start; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;뷰 계층 구조상의 루트 클래스는 바로 앱의 원도우(UIWindow)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;background-color: #ffffff; color: #353638; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;iOS 앱에서 모든 View들은 뷰 계층구조상 UIView 클래스를 상속한 클래스의 인스턴스이다. 즉 모든 UI요소들은 UIView의 서브 뷰.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, Label, Button 등등의 뷰, UI 요소는 모두 UIView를 상속받아 만들어진 UIView 클래스의 하위클래스인 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이러한 View는 서로간에 &lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;부모-자식 관계를 형성 - 즉&amp;nbsp;&lt;/span&gt;계층적으로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 부모 View는 자식 View를 포함하는 Container View로써의 역할을 하며, 자식 View는 해당 부모 View 위에 얹힌다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; 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;style6&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;▶️&amp;nbsp;UIView와 UIViewController&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;UIView&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;iOS에서 화면에 표시되는 모든 요소는 UIView를 기반으로 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UIView는 화면을 구성하는 기본 단위로, 버튼, 레이블, 이미지 뷰 등의 기본 UI 요소들은 이 UIView를 상속받아 구현된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UIView의 주요 역할:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;화면에 그래픽 요소를 그린다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용자 입력(터치 이벤트)을 처리한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;UIViewController&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UIViewController는 하나의 화면을 관리하는 컨트롤러 역할을 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;UIView&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;는 화면을 구성하는 기본 단위이며,&amp;nbsp;&lt;/span&gt;UIViewController는 이 UIView를 관리하는 컨트롤러&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 뷰 컨트롤러는 하나의 루트 UIView를 가지며, 그 내부에 여러 개의 서브뷰를 추가할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UIViewController의 주요 역할:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰의 생명주기 관리&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;화면 전환 및 데이터 전달&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용자 인터랙션 처리&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;UIWindow&lt;/b&gt;&lt;/span&gt;&lt;/h4&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;모든 앱은 하나의 UIWindow 인스턴스를 가진다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;앱의 여러 뷰들은 이 UIWindow 인스턴스 내 포함된다.&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;앱 내의 view 인스턴스 포함 관계&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;UIWindow 인스턴스가 아이폰 앱 화면 그 자체, 즉 최상위 뷰 인스턴스임을 확인해볼 수 있다.&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;1872&quot; data-origin-height=&quot;840&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QLCc9/btsMY39y9ea/0cDrjSUe2hsguKO0UPHxkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QLCc9/btsMY39y9ea/0cDrjSUe2hsguKO0UPHxkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QLCc9/btsMY39y9ea/0cDrjSUe2hsguKO0UPHxkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQLCc9%2FbtsMY39y9ea%2F0cDrjSUe2hsguKO0UPHxkk%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;1872&quot; height=&quot;840&quot; data-origin-width=&quot;1872&quot; data-origin-height=&quot;840&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;▶️ &amp;nbsp;View 계층 구조(View Hierarchy)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;View 계층 구조란?&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;iOS의 뷰 시스템은 계층적 구조를 가지고 있으며, 하나의 UIView 안에 여러 개의 Subview를 포함한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;최상위 뷰를 루트 뷰(root view)라고 하며, 그 아래에 여러 개의 서브 뷰(subview)를 배치할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 뷰는 &lt;b&gt;슈퍼 뷰(superview)&lt;/b&gt;와 &lt;b&gt;서브 뷰(subview)&lt;/b&gt; 관계를 가질 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래는 뷰 계층구조를 간단하게 보여주는 swift코드와 View 클래스 계층 구조도이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1743053228891&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let parentView = UIView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
        parentView.backgroundColor = .red
        
        let childView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
        childView.backgroundColor = .blue
        
        parentView.addSubview(childView) // childView를 parentView의 subview로 추가
        view.addSubview(parentView)      // parentView를 최상위 view의 subview로 추가
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-pm-slice=&quot;3 3 []&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;parentView(빨간색)는 childView(파란색)를 포함하는 &lt;b&gt;슈퍼 뷰&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;childView는 parentView의 &lt;b&gt;서브 뷰&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;parentView는 ViewController의 루트 뷰에 추가됨(즉, &lt;b&gt;ViewController의 루트 뷰-&amp;gt;parentView-&amp;gt;childView&lt;/b&gt; 구조의 계층)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9kFYR/btsMYs2UEAX/oAYYGYVwQolq6cnvqz1mf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9kFYR/btsMYs2UEAX/oAYYGYVwQolq6cnvqz1mf1/img.png&quot; data-alt=&quot;뷰 클래스 계층도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9kFYR/btsMYs2UEAX/oAYYGYVwQolq6cnvqz1mf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9kFYR%2FbtsMYs2UEAX%2FoAYYGYVwQolq6cnvqz1mf1%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;1278&quot; height=&quot;794&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;794&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;/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;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;▶️&amp;nbsp; 화면이 그려지는 과정&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 윈도우를 포함한 각 계층 구조의 뷰는 자신을 레이어(CALayer)에 그린다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그 후, 모든 뷰의 레이어들은 전체 화면에 합성되는 방식으로 ios앱의 화면이 그려진다.&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;1877&quot; data-origin-height=&quot;1082&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqtYSZ/btsMYqRNsaC/lKpcFkaj7LqLnlqFyVWUn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqtYSZ/btsMYqRNsaC/lKpcFkaj7LqLnlqFyVWUn0/img.png&quot; data-alt=&quot;계산기 앱이 핸드폰에 그려지는 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqtYSZ/btsMYqRNsaC/lKpcFkaj7LqLnlqFyVWUn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqtYSZ%2FbtsMYqRNsaC%2FlKpcFkaj7LqLnlqFyVWUn0%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;1877&quot; height=&quot;1082&quot; data-origin-width=&quot;1877&quot; data-origin-height=&quot;1082&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;/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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;▶️&amp;nbsp; UIViewController Lifecycle&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;1120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QZqsb/btsMXRCyWFv/iIvf7TlCezKhqSbcV47590/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QZqsb/btsMXRCyWFv/iIvf7TlCezKhqSbcV47590/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QZqsb/btsMXRCyWFv/iIvf7TlCezKhqSbcV47590/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQZqsb%2FbtsMXRCyWFv%2FiIvf7TlCezKhqSbcV47590%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;300&quot; height=&quot;669&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;1120&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&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;init&lt;/b&gt;: 생성자 역할&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;loadView&lt;/b&gt;: 스토리보드 등을 이용하여 View Hierarchy를 완성하는 부분, 대체로 코딩할 내용은 없다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;viewDidLoad&lt;/b&gt;&lt;/span&gt;: View가 화면에 나오기전에 초기화 등을 하는 부분, 여기서 많은 코딩이 일어난다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;viewWillAppear&lt;/b&gt;: 화면에 보이기 직전에 호출되는 함수로 여기서 UI layout등을 조정한다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;viewDidAppear&lt;/b&gt;: 화면이 보이는 상태, 여기서부터 사용자와 인터렉션이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;viewWillDisappear&lt;/b&gt;: 화면이 보이지 않게 되는 시점에서 호출, 특별한 코딩은 요구되지 않는다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;viewDidDisappear&lt;/b&gt;&lt;/span&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;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅&amp;nbsp; 화씨 -&amp;gt; 섭씨로 바꾸는 앱 만들기&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;아래와 같은 계층 구조의 화씨를 섭씨로 변환해주는 ios앱을 만들어보자.&lt;/b&gt;&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;1874&quot; data-origin-height=&quot;662&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duqzhQ/btsMX00lzWK/pcw26xH8KxhwqsLRSiDuvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duqzhQ/btsMX00lzWK/pcw26xH8KxhwqsLRSiDuvK/img.png&quot; data-alt=&quot;화씨 변환 앱 계층구조도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duqzhQ/btsMX00lzWK/pcw26xH8KxhwqsLRSiDuvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduqzhQ%2FbtsMX00lzWK%2Fpcw26xH8KxhwqsLRSiDuvK%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;1874&quot; height=&quot;662&quot; data-origin-width=&quot;1874&quot; data-origin-height=&quot;662&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;화씨 변환 앱 계층구조도&lt;/figcaption&gt;
&lt;/figure&gt;
&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;&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;Main스토리보드에서 뷰들의 레이아웃 등을 구성해주고, 해당 스토리보드를 ConversionViewController와 연결해준다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;현재 프로젝트 디렉터리안에 File-&amp;gt;New-&amp;gt;File-&amp;gt;Cocoa Touch Class &amp;ndash; ConversionViewController.swift 생성&lt;br /&gt;Class 이름은 ConversionViewController,&amp;nbsp; Subclass of는 UIViewController로 입력&lt;br /&gt;&lt;br /&gt;Main.storyboard에서 Identity Inspector클릭 후, Class에서 ConversionViewController 선택.&lt;br /&gt;이제 Main.storyboard와 ConversionViewController가 연결되었다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&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;스토리보드는 아래와 같이 구성되어야한다.&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;2026&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjAj6E/btsMZBSl5IC/ItNy0IoVT6UfC8uPA7CAe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjAj6E/btsMZBSl5IC/ItNy0IoVT6UfC8uPA7CAe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjAj6E/btsMZBSl5IC/ItNy0IoVT6UfC8uPA7CAe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjAj6E%2FbtsMZBSl5IC%2FItNy0IoVT6UfC8uPA7CAe1%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;2026&quot; height=&quot;1800&quot; data-origin-width=&quot;2026&quot; data-origin-height=&quot;1800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;위처럼 스토리보드를 구성해준 다음, 스토리보드에서 placeholder로 Value가 적힌 텍스트필드와&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;??? 라벨을 ConversionViewController.swift에 컨트롤 + 드레그하여 outlet으로 추가. 두 파일에서 View객체와 변수간 연결을 한다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기서 추가로, Value 텍스트필드는 action으로 하나더 드레그해준다. &lt;/span&gt;&lt;/span&gt;fahrenheitEditingChanged 메서드로 추가하여 텍스트필드에 텍스트 입력시 해당 값을 섭씨로 변환 후 ??? 라벨에 해당 섭씨 값을 출력시킬 목적이다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;nbsp;  전체 코드&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1743056888509&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import UIKit

class ConversionViewController: UIViewController {
    @IBOutlet weak var fahrenheitTextField: UITextField!
    @IBOutlet weak var celsiusLabel: UILabel!
}

extension ConversionViewController{
    override func viewDidLoad() {
        super.viewDidLoad()
        fahrenheitTextField.delegate = self
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dissmissKeyboard))
        view.addGestureRecognizer(tapGesture)
        
        // Do any additional setup after loading the view.
    }
}

extension ConversionViewController {
    @IBAction func fahrenheitEditingChanged(_ sender: UITextField) {
        if let text = sender.text {
            if let fahrenheitValue = Double(text) {
                let celsiusValue = 5.0/9.0*(fahrenheitValue-32.0)
                celsiusLabel.text = String.init(format: &quot;%.2f&quot;, celsiusValue)
                
            }else {
                celsiusLabel.text = &quot;???&quot;
            }
        }
    }
}

extension ConversionViewController{
    @objc func dissmissKeyboard(sender: UITapGestureRecognizer) {
        fahrenheitTextField.resignFirstResponder()
    }
}

extension ConversionViewController: UITextFieldDelegate{
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -&amp;gt; Bool {
        let existingTextHasDecimalSeperator = textField.text?.range(of: &quot;.&quot;)
        let replacementTextHasDecimalSeperator = string.range(of: &quot;.&quot;)
        if existingTextHasDecimalSeperator != nil &amp;amp;&amp;amp; replacementTextHasDecimalSeperator != nil {
            return false
        } else{
            return true
        }
    }
}&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;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;nbsp;  실행 화면&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;1936&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVEBbO/btsMZki3VtX/SRCyqK6Uee7eKmD9N5wPK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVEBbO/btsMZki3VtX/SRCyqK6Uee7eKmD9N5wPK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVEBbO/btsMZki3VtX/SRCyqK6Uee7eKmD9N5wPK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVEBbO%2FbtsMZki3VtX%2FSRCyqK6Uee7eKmD9N5wPK0%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;500&quot; height=&quot;949&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;1936&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;</description>
      <category>IOS</category>
      <category>ios</category>
      <category>UIView</category>
      <category>View Hierarchy</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/36</guid>
      <comments>https://basecoding.tistory.com/entry/iOS-Programming-3-%EB%B7%B0%EC%99%80-%EB%B7%B0-%EA%B3%84%EC%B8%B5-%EA%B5%AC%EC%A1%B0View-View-Hierarchy#entry36comment</comments>
      <pubDate>Thu, 27 Mar 2025 15:48:15 +0900</pubDate>
    </item>
    <item>
      <title>[iOS Programming] 2. Xcode Playground &amp;amp; Swift 문법 알아보기</title>
      <link>https://basecoding.tistory.com/entry/iOS-Programming-2-Xcode-Playground-Swift-%EB%AC%B8%EB%B2%95-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이번에는 IOS 개발을 위한 언어인 Swift와, 스위프트 언어를 학습할 수 있는 공간인 플레이그라운드에 대해서 알아보자.&lt;/b&gt;&lt;/span&gt;&lt;/p&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  Swift의 배경&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;스위프트는 애플의 iOS와 macOS를 위한 프로그래밍 언어로 2014년 6월 2일 애플 세계 개발자 회의(WWDC)에서 처음 소개된 언어이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기존의 애플 OS용 언어인 Objective-C와 함께 IOS &amp;amp; macOS 개발 언어로써 공존할 목적으로 만들어진 언어인 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Swift는 Objective-C &lt;/span&gt;에는 없었던 &lt;/span&gt;클로저, 다중 리턴 타입, 네임스페이스, 제네릭스, 타입 유추 등과 같은&amp;nbsp; 현대 프로그래밍 언어가 갖고 있는 다양한 기능들을 많이 포함있다. so, 기존 오브젝티브 C언어에 비해서&amp;nbsp; 진보되어진 언어이다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2014년 6월 2일 애플 세계개발자 회의(WWDC)에서 최초 소개되었던 Swift버전은 &amp;lsquo;Swift 1.0' 이었고, 현재 2025년도 기준 &amp;lsquo;Swift 5.0'을 넘어 &amp;lsquo;Swift 6.0' 버전까지 출시되었다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✨ Swift의 특징&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;스위프트는 오픈소스로 공개된 언어이며, 가장 큰 특징 3가지로는 Safe, Fast, Expressive 이다.&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;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; Safe: 안정성 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Swift는 프로그래밍을 하는 중에 프로그래머가 저지를 수 있는 문법적 로직적 실수를 엄격한 문법을 통하여 미연에 방지해주기에 안정성이 있다는 특징이있다.&amp;nbsp; 옵셔널(Optional), guard, 에러처리(Error Handling), 강력한 타입통제 등 다양한 안정성 보장 문법들을 제공해주기에 안정적이다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;  Fast: 신속성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Swift는 기존의 &lt;b&gt;C, C++, Objective-C&lt;/b&gt;보다 &lt;b&gt;개발 속도와 실행 속도가 더 빠른 언어이다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Swift는 &lt;b&gt;간결한 문법 + 빠른 실행 속도 + 자동 메모리 관리&lt;/b&gt;를 기반으로 더욱 빠른 개발과 실행 속도를 보장해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기존 Objective-C는 동적 타입 기반이라 런타임 성능이 Swift보다 떨어졌고, C/C++는 강력하지만, 컴파일 시간이 오래 걸렸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;so, 기존에 너무 느렸던 C, C++, Objective-C와 같은 프로그래밍 언어를 대체하려는 목적으로 출시된 언어라고도 볼 수 있다.&amp;nbsp;&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;  &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Expressive&lt;/span&gt;: &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;표현성&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Swift는 더 사용하기 편하고 보기 좋은 문법을 구사하도록 도와준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;매번 구문 뒤에 꼬박꼬박 붙여주어야했던 세미콜론 등 개발자 사용성에 있어서 불편한 문법들을 과감히 제거했다.&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;⛹ &amp;zwj;♂️ Xcode &lt;b&gt;Playground&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;자 이제 Swift언어를 체험해볼 시간이다. 아무리 언어를 눈으로 많이 익힌다해도 직접 Running 시켜봐야 동작을 파악할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;IOS개발에 돌입하기 전에 이 Swift언어를 Running 시켜보면서 언어를 훈련할 수 있도록도와주는 일종의 놀이터, 훈련장 같은 &lt;b&gt;Playground&lt;/b&gt;라는 프로그램이 있다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;플레이그라운드는 우리가 설치한 Xcode에 내장되어있는 프로그램이다. 설치가 안되어있다면 아래 게시물을 통해 설치하기를 바란다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.03.13 - [IOS] - [iOS Programming] 1. 개발환경 및 기본개념&amp;amp;앱 개발 실습&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1742448594528&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[iOS Programming] 1. 개발환경 및 기본개념&amp;amp;앱 개발 실습&quot; data-og-description=&quot; 개발환경ios 앱 개발을 하기위해선 macOS기반의 맥북, ios앱 개발도구인 xcode가 필요하다.이때 고려사항으로는 맥북의 macOS 버전&amp;amp;개발가능한 xcode 버전 &amp;amp; 실행가능한 ios버전을 고려해야한다.&amp;nbsp;안&quot; data-og-host=&quot;basecoding.tistory.com&quot; data-og-source-url=&quot;https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5&quot; data-og-url=&quot;https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/caV8hz/hyYrWk13uH/g86YxiQrKODnZhJAqQRiH1/img.png?width=800&amp;amp;height=1026&amp;amp;face=0_0_800_1026,https://scrap.kakaocdn.net/dn/Tshst/hyYrVzEq0e/4zgnqvyHYIdaHX2txEIIek/img.png?width=800&amp;amp;height=1026&amp;amp;face=0_0_800_1026,https://scrap.kakaocdn.net/dn/1ABz2/hyYrW6mzye/WQovp4RMbf817zaeETYQJK/img.png?width=2800&amp;amp;height=1746&amp;amp;face=0_0_2800_1746&quot;&gt;&lt;a href=&quot;https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/caV8hz/hyYrWk13uH/g86YxiQrKODnZhJAqQRiH1/img.png?width=800&amp;amp;height=1026&amp;amp;face=0_0_800_1026,https://scrap.kakaocdn.net/dn/Tshst/hyYrVzEq0e/4zgnqvyHYIdaHX2txEIIek/img.png?width=800&amp;amp;height=1026&amp;amp;face=0_0_800_1026,https://scrap.kakaocdn.net/dn/1ABz2/hyYrW6mzye/WQovp4RMbf817zaeETYQJK/img.png?width=2800&amp;amp;height=1746&amp;amp;face=0_0_2800_1746');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[iOS Programming] 1. 개발환경 및 기본개념&amp;amp;앱 개발 실습&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt; 개발환경ios 앱 개발을 하기위해선 macOS기반의 맥북, ios앱 개발도구인 xcode가 필요하다.이때 고려사항으로는 맥북의 macOS 버전&amp;amp;개발가능한 xcode 버전 &amp;amp; 실행가능한 ios버전을 고려해야한다.&amp;nbsp;안&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;basecoding.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;Playground&lt;/b&gt;는 우리가 작성한 Swift 언어를 컴퓨터 언어로 해석해주는 해석기 역할의 sw인데, 이는 마치 Interpreter 처럼 동작하나 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;실제로 Swift는 컴파일 언어임을 기억하자.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;단순히 스위프트 언어를 학습하기 위해서 매번 Xcode를 키고 플레이그라운드를 실행시키는 과정이 번거롭다면 아래 온라인 사이트를 통해서 간단하게 스위트프 언어를 실행해볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;&lt;a title=&quot;online.swiftplayground.run&quot; href=&quot;http://online.swiftplayground.run&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://online.swiftplayground.run&lt;/a&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;⛹ &amp;zwj;♂️ Playground 실행하기&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;먼저 Xcode를 실행하고, 상단 탭의 File - &amp;gt; New -&amp;gt; Playground를 클릭해준다.&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;1604&quot; data-origin-height=&quot;1468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DVKUr/btsMQ7Lc28F/fXc1K5y4bvmdklAG84QK71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DVKUr/btsMQ7Lc28F/fXc1K5y4bvmdklAG84QK71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DVKUr/btsMQ7Lc28F/fXc1K5y4bvmdklAG84QK71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDVKUr%2FbtsMQ7Lc28F%2FfXc1K5y4bvmdklAG84QK71%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;700&quot; height=&quot;641&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;1468&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그 다음 iOS, macOS의 선택지 중에서 macOS를 선택 &amp;amp; Black를 선택해주고 Next버튼을 눌러준다.&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;2104&quot; data-origin-height=&quot;1776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ow6wp/btsMQz9b3BN/ZnHnA1XCmTw0jE7fzsvmGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ow6wp/btsMQz9b3BN/ZnHnA1XCmTw0jE7fzsvmGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ow6wp/btsMQz9b3BN/ZnHnA1XCmTw0jE7fzsvmGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fow6wp%2FbtsMQz9b3BN%2FZnHnA1XCmTw0jE7fzsvmGk%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;700&quot; height=&quot;591&quot; data-origin-width=&quot;2104&quot; data-origin-height=&quot;1776&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그리고, 원하는 파일명과 파일이 저장될 경로를 입력해준 후 Create 버튼을눌러 Playground파일을 생성해준다.&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;2104&quot; data-origin-height=&quot;1776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csh3ZS/btsMQDQ6KwM/ZJLGKKOawTBEXwKXOJHEnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csh3ZS/btsMQDQ6KwM/ZJLGKKOawTBEXwKXOJHEnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csh3ZS/btsMQDQ6KwM/ZJLGKKOawTBEXwKXOJHEnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcsh3ZS%2FbtsMQDQ6KwM%2FZJLGKKOawTBEXwKXOJHEnk%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;700&quot; height=&quot;591&quot; data-origin-width=&quot;2104&quot; data-origin-height=&quot;1776&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 style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  Playground의 첫화면&lt;/b&gt;&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;2104&quot; data-origin-height=&quot;1776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uhmpP/btsMQcftjC3/RPqv37QuA2uj7Re6JD2L1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uhmpP/btsMQcftjC3/RPqv37QuA2uj7Re6JD2L1K/img.png&quot; data-alt=&quot;Playground 생성 후 첫화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uhmpP/btsMQcftjC3/RPqv37QuA2uj7Re6JD2L1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuhmpP%2FbtsMQcftjC3%2FRPqv37QuA2uj7Re6JD2L1K%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;700&quot; height=&quot;591&quot; data-origin-width=&quot;2104&quot; data-origin-height=&quot;1776&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Playground 생성 후 첫화면&lt;/figcaption&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;플레이그라운드를 생성후 자동으로 입력된 코드 템플릿을 보면 Cocoa라이브러리와 간단한 인사말 문자열 변수가 생성된 것을 확인할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Cocoa 라이브러리&lt;/b&gt;는 macOS 앱 개발을 위한 라이브러리로, iOS에서는 Cocoa의 모바일 버전인 Cocoa Touch를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Swift의 &lt;b&gt;Playground 환경&lt;/b&gt;에서 Cocoa 라이브러리를 불러오는 이유는, 기본적으로 macOS 환경에서 GUI 요소 및 기본 시스템 기능을 사용할 수 있도록 하기 위해서이다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, Swift 플레이그라운드에서 자동 생성되는 코드 템플릿에서 import Cocoa가 보인다면, &lt;b&gt;macOS용 코드&lt;/b&gt;가 기본으로 설정되었다는 뜻이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우리는 ios를 개발할건데, 왜 macOS로 Playground파일을 생성한걸까?&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그 이유는&amp;nbsp;&lt;b&gt;Swift 언어 자체를 익히는 데 집중하기 위해서&lt;/b&gt;이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;iOS에서는 UIKit을 써야 하지만, UIKit은 화면 관리(View Controller) 같은 추가 개념이 필요해서 초반에 배우기엔 복잡할 수 있으며, macOS의 Cocoa는 기본적인 Swift 연습을 하는 데&amp;nbsp;&lt;b&gt;불필요한 UI 개념이 적어서&amp;nbsp;배우기 더 간단&lt;/b&gt;하기 때문에, 초기 Swift언어를 배우기위해서 플레이그라운드를 이용할때는 macOS용으로 플레이그라운드를 생성해서 학습하는 것을 추천한다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉,&amp;nbsp;iOS-specific한 개념(UI 관련 요소, ViewController 등)을 배제하고 Swift 문법 자체에 집중할 수 있도록!&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&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;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;⛹ &amp;zwj;♂️ 콘솔창에 출력해보기&lt;/b&gt;&lt;/span&gt;&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;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;내가 작성한 코드를 확인해보기 위한 간단한 방법은 print() 메서드를 활용하는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기본 템플릿에서 제공해준 인사말 문자열을 콘솔창에 출력시켜보자.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742450711723&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Cocoa

var greeting = &quot;Hello, World!&quot;
print(greeting)&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 플레이그라운드를 실행시켜보면 아래와 같이 콘솔창에 인사말이 출력된다.&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;1856&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wutc0/btsMQDKwInS/VsFsvsLbLdHjD6XKH9mEJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wutc0/btsMQDKwInS/VsFsvsLbLdHjD6XKH9mEJ0/img.png&quot; data-alt=&quot;콘솔창에 출력된 인사말&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wutc0/btsMQDKwInS/VsFsvsLbLdHjD6XKH9mEJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWutc0%2FbtsMQDKwInS%2FVsFsvsLbLdHjD6XKH9mEJ0%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;1856&quot; height=&quot;468&quot; data-origin-width=&quot;1856&quot; data-origin-height=&quot;468&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 처럼 플레이그라운드에 작성된 코드를 실행하기 위해선 2가지 방법이 존재한다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. 아래의 이미지에 밑줄친 조그만 플레이 버튼을 클릭하면 해당 코드 구문까지의 모든 코드 구문들을 실행시켜준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. 하단 콘솔창 상단에 보이는 조금 더 큰 플레이 버튼을 클릭하면 현 플레이그라운드의 모든 구문들을 실행시켜준다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 2번 방법이 가장 편한데, &lt;b&gt;더욱 편하게 사용하기위한 실행 단축키는 command(또는 option) + shift + Enter 키 동시입력&lt;/b&gt;이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;또는, 매번 실행버튼 클릭 또는 단축키를 눌러주는게 번거롭게 느껴질 경우, 내가 코드를 입력할때마다 자동으로 컴파일 &amp;amp; Run 해주는 기능이있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;바로 하단 이미지에 보이는 콘솔창 상단의 플레이버튼을 2초 정도 눌러주면 Automatically Run &amp;amp; Manually Run 옵션 다이얼로그창이 뜨는걸 확인할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;nbsp;Manually Run 옵션은 이전처럼 수동으로 프로그램을 Run하는 방식이고,&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Automatically Run 옵션이 바로 내가 코드를 입력할때마다 자동으로 컴파일 &amp;amp; Run 해주는 옵션이다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 Automatically Run 옵션을 클릭하여 플레이그라운드를 이용하는 것을 추천한다. 매우 편하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;2880&quot; data-origin-height=&quot;1800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x78CJ/btsMQS8AJnJ/c3GkvCyuqhmw7ETLt5zmy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x78CJ/btsMQS8AJnJ/c3GkvCyuqhmw7ETLt5zmy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x78CJ/btsMQS8AJnJ/c3GkvCyuqhmw7ETLt5zmy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx78CJ%2FbtsMQS8AJnJ%2Fc3GkvCyuqhmw7ETLt5zmy0%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;2880&quot; height=&quot;1800&quot; data-origin-width=&quot;2880&quot; data-origin-height=&quot;1800&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;상단 이미지의 우측 사이드바를 보면, 현 플레이그라운드의 파일명과 스위프트 언어의 버전 선택 &amp;amp; 개발 플렛폼을 변경해줄 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;⭐️자동정렬 단축키&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;매우 유용한 단축키이다. 전체적인 코드 가독성을 높여주기에, 코딩시&amp;nbsp; command + a 키로 전체코드 선택 후,&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;control + shift + Enter키&lt;/b&gt;&lt;/span&gt;를 동시에 눌러주면 전체코드가 자동정렬되어진다. 원하는 부분만 선택해서 control + shift + Enter키 눌러주면 해당 부분만 정렬도 가능하다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본격적으로 Swift문법에 대해서 알아보자.&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;이번 게시물은 스위프트의 문법에 대한 핵심 요약 기술이기에, 이제부터 기술할 스위프트 문법 및 예제에 대한 실행 결과 및 이미지는 디테일하게 첨부하지 않고 간단하게 코드와 주석문으로 나타낼 예정이다. 직접 Playground에서 실행해보며 문법을 익혀보기를 바란다.&amp;nbsp;&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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  변수&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 값을 다루고 저장하는 역할을하는 변수이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Swift에서의 변수는 var 이나 let으로 선언한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 마치 JavaScript와 같아보이지만, 매우 큰 차이점이 있다.&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;Swift에서 var를 사용하면 일반 변수로 생성된다는 점은 같으나, let을 사용하면 상수를 만들어진다.&amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 일반 언어들에서는 const 및 final로 상수를 선언하지만 스위프트는 let이다.&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;아래의 예제를 보면 let으로 선언된 변수는 상수이기에 초기화 이후 값 변경시 컴파일 애러가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Swift는 정적 타입 언어&lt;/b&gt;라서, 이 코드에서 yourName을 변경하려고 하면 &lt;b&gt;코드를 실행하기도 전에(컴파일 시점에서) 스위프트 컴파일러가 오류를 감지&lt;/b&gt;하고 에러를 발생시킨다.&lt;/p&gt;
&lt;pre id=&quot;code_1742451933321&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var myName = 42 // 변수
myName += 42
let yourName = 42 // 상수
//yourName += 42 // error&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  변수의 타입지정&lt;/span&gt;&lt;/h2&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;p data-ke-size=&quot;size16&quot;&gt;참고로 스위프트 변수의 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;기본&lt;/span&gt;&amp;nbsp;타입종류는 Int, Unit, Float, Double, String, Bool 이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수의 타입을 명시적으로 지정할 수도 있고, 암시적으로 지정 수도 있는데, 지정하지 않으면(암시적 지정) rvalue의 타입으로 자동추론하여 지정되고, 명시적으로 타입을 지정하려면 해당 변수의 우측에 : 콜론과 지정할 타입을 기입해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742452337410&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let explicitInt: Int = 70 // 변수 explicitInt의 타입을 명시적으로 Int로 지정
let inplicitInteger = 70 // 변수 inplicitInteger의 타입은 지정되지 않았으나 rvalue인 70을 보고 Int로 지정
let implicitDouble = 70.5
let explicitDouble: Double = 70&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  변수의 형변환&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수는 기본적으로 대입연산자 = 기준 좌항 우항 모두 동일한 타입이어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 타입의 변수를 다른 타입으로 형변환 시켜주기 위해서는, 변경하고자 하는 타입의 클래스의 생성자에 변경대상 변수를 인자로 넘겨주면서 호출하여 형변환 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ex) Int 타입 변수인 width를 String 타입으로 형변환하고자 한다면 String(width)&lt;/blockquote&gt;
&lt;pre id=&quot;code_1742452509005&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let label = &quot;The width is &quot;
let width = 94
let widthLabel = label + String(width) // String() =&amp;gt; String의 생성자를 호출
let height = Int(&amp;rdquo;10&amp;rdquo;)
let sheight = Int(&amp;ldquo;10.5&amp;rdquo;)
let dheight = Int(10.5)&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  문자열 내에서 간단하게 문자열로 형변환&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;마치 JS의 템플릿 문자열처럼, 문자열 내에서 변수 및 표현식들을 간편하게 문자열로 포함시켜 사용하고자 하는 경우&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;\()&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위의 &quot;\()&quot; 구문안에 변수를 넣어주면 문자열안에 변수 값은 문자열로 변환하여 적용된다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742452858486&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let apples = 3
let oranges = 5
let appleSummary = &quot;I have \(apples) apples.&quot;
let fruitSummary = &quot;I have \(apples + oranges) pieces of fruit.&amp;rdquo;&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  배열(array)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;동일한 자료형의 변수들을 순차적으로 저장해두는 자료구조인 &lt;b&gt;배열은 [](대괄호)를 이용하여 생성가능&lt;/b&gt;하다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;스위프트는 엄격한 문법 검사를 한다고 했었다. 물론 자동 타입 추론기능이 있지만, 안정성을 위해 : 콜론 뒤에 타입을 명시적으로 기술해주는 것이 좋은데, 만약 해당 배열을 정수형 자료형들을 모아두는 배열이라면 &lt;b&gt;: [Int] &lt;/b&gt;처럼 대괄호 안에 자료형을 써준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742452980355&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 배열 선언
var list1: [Int] = [] // Int를 저장하는 빈 배열, 명시적
var list2 =[Int]() // Int를 저장하는 빈 배열, 암시적
var shoppingList = [&quot;catfish&quot;, &quot;water&quot;, &quot;tulips&quot;, &quot;blue paint&quot;] // 배열초기화, 암시적
shoppingList[1] = &quot;bottle of water&quot; // 배열 요소 액세스
let first = shoppingList.first // shoppingList[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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;딕셔너리(Dictionary)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;마치 언어사전의 인덱스를 보고 편하게 해당 단어가 있는 페이지를 찾아보듯, 딕셔너리는 &amp;lt;key:value&amp;gt;로 값을 저장하는 자료구조.&lt;/span&gt;&lt;/p&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;배열과 마찬가지로 딕셔너리도 [] 대괄호안에 변수 데이터들을 관리한다.&lt;/p&gt;
&lt;pre id=&quot;code_1742453304618&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 딕셔너리 선언
var dict1: [String: Int] = [:] // &amp;lt;문자열, 값&amp;gt;으로 저장하는 딕셔너리, 명시적
var dict2 = [String: Int]() // &amp;lt;문자열, 값&amp;gt;으로 저장하는 딕셔너리, 암시적
var occupations = [ &quot;Malcolm&quot;:&quot;Captian&quot;, &quot;Kaylee&quot;:&quot;Mechanic&quot;, ] //딕셔너리 초기화
occupations[&quot;Jayne&quot;] = &quot;Public Relations&amp;rdquo;
let myjob = occupations[&amp;ldquo;kjhan&amp;rdquo;] // 에러, &amp;ldquo;kjhan&amp;rdquo;가 저장되어 있지 않기 때문&lt;/code&gt;&lt;/pre&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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;/span&gt;&lt;span&gt; 제어문: if, switch, for, while&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  흐름제어(if문)&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;코드 로직의 흐름을 제어하는 가장 대표적인 문법인 if이다. &lt;/span&gt;&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;if문 안의 조건은 꼭 불리언(Boolean) 표현이어야 한다. 즉, C나 Java처럼 정수값을 이용한 암시적 비교(implicit comparison)를 허용하지 않는다!  &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;C나 Java에서는 if (score) {...}라고 하면,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;264&quot; data-start=&quot;200&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;228&quot; data-start=&quot;200&quot;&gt;score가 &lt;b&gt;0이 아니면 true&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;264&quot; data-start=&quot;229&quot;&gt;score가 &lt;b&gt;0이면 false&lt;/b&gt;&lt;br /&gt;로 해석되었지만, 스위프트 언어에서는 정수를 Boolean 값처럼 사용할 수 없다. 오직 불리언 값만 조건문의 조건식에 올수있다.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if 문 조건에 Boolean이 아닌 값을 넣을 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;so,if score {...}라고 표현하면 0과의 비교를 암시하지 않기 때문에 에러가 발생하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 불리언 값이 참이면 if문 안의 로직 수행, 거짓이면 else if문으로 이동하여 해당 else if문의 조건 확인 후 이전과같이 참이면 else if 문 안의 로직 수행, 거짓이면 또 다른 else if문 으로, 모든 else if 문이 다 거짓이라면 else문을 실행하게된다.&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;if(&amp;hellip;)에서 괄호를 없애고 간단하게 if &amp;hellip; 해도 된다. 조건식에 소괄호를 없애고 그냥 if 조건식 {} 처럼 사용하는 걸 추천한다.&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;또한,&amp;nbsp; if(condition1 &amp;amp;&amp;amp; condition){ &amp;hellip; } 인 경우 If condition1, condition{ &amp;hellip; } 처럼 간단하게 사용해도된다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742453467181&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Cocoa

var teamScore = 0
let score = 30
if score &amp;gt; 50 {
    teamScore = 3
} else {
    teamScore = 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;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;흐름제어(switch문)&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;if문과 마찬가지로 코드의 흐름을 제어하는 문법으로 switch문이 있다.&lt;/span&gt;&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;스위프트의 switch문에는 정수 타입 값이나 동등 비교 연산 뿐만 아니라 어떤 종류의 데이터든 사용할 수 있다는 특징이있다.&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;또한, 다른 언어들의 switch문과 마찬가지로 &lt;b&gt;case문의 조건과 일치할 때 case문 아래에 속한 코드를 실행하는데,&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;break문을 써주지않아도 해당 case구문 수행후 switch문을 빠져나온다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 나오는 case문은 자동적으로 빠져 나오기 때문에 코드 끝에 break 키워드를 명시하지 않아도 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 일일히 break를 케이스 구문 마지막에 써줄 필요가 없다. 매우 편리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742454237014&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Cocoa

let vegetable = &quot;red pepper&quot;
switch vegetable {
case &quot;celery&quot;:
    let vegetableComment = &quot;Add some raisins and make ants on a log.&quot;
case &quot;cucumber&quot;, &quot;watercress&quot;:
    let vegetableComment = &quot;That would make a good tea sandwich.&quot;
case let x where x.hasSuffix(&quot;pepper&quot;):
    let vegetableComment = &quot;Is it a spicy \(x)?&quot;
default:
    let vegetableComment = &quot;Everything tastes good in soup.&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>IOS</category>
      <category>ios</category>
      <category>playground</category>
      <category>SWIFT</category>
      <category>Xcode</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/35</guid>
      <comments>https://basecoding.tistory.com/entry/iOS-Programming-2-Xcode-Playground-Swift-%EB%AC%B8%EB%B2%95-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry35comment</comments>
      <pubDate>Thu, 20 Mar 2025 16:11:39 +0900</pubDate>
    </item>
    <item>
      <title>[iOS Programming] 1. 개발환경 및 기본개념&amp;amp;앱 개발 실습</title>
      <link>https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 개발환경&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ios 앱 개발을 하기위해선 macOS기반의 맥북, ios앱 개발도구인 xcode가 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때 고려사항으로는 맥북의 macOS 버전&amp;amp;개발가능한 xcode 버전 &amp;amp; 실행가능한 ios버전을 고려해야한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;안드로이드 스튜디오와 마찬가지로 개발도구(xcode)의 버전에 따라 요구되는 최소OS버전이 있기때문에 맥북의 OS를 잘 확인하여 해당 OS와 호환되는 xcode를 설치해야한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅ xcode 설치&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;본격적인 ios 개발을 위해서 xcode를 설치해야하는데, 보통 xcode를 설치하는 방법은 2가지가 있다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1️⃣ App Store에서 xcode 설치&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2️⃣ Apple Developer에서 xcode 설치&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1번의 경우 가장 간편하나, App Store에서는 가장 최신 버전을 업로드해주기에 이전 버전의 xcode를 선택하고자 하는경우 선택권이 없어진다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2번의 경우 1번에 비해 과정은 추가되나, 베타버전을 포함한 전체 버전들을 선택해서 다운로드가 가능하기에 추천하는 방법이다.&amp;nbsp;&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;&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; MVC 패턴&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ios 앱을 개발하기에 앞서, MVC패턴에 대해서 숙지하여야한다. 이는 iOS 개발에 사용되는 핵심 디자인 패턴이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;MVC패턴은 Model-View-Controller로, MVC패턴을 적용한 앱이라면 앱 상의 모든 인스턴스들은 모델,뷰,컨트롤러 중 하나이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&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;1280&quot; data-origin-height=&quot;631&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b72kHG/btsMES8VnvS/dkn1bHHs91yMK9LDISWqCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b72kHG/btsMES8VnvS/dkn1bHHs91yMK9LDISWqCk/img.png&quot; data-alt=&quot;MVC패턴 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b72kHG/btsMES8VnvS/dkn1bHHs91yMK9LDISWqCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb72kHG%2FbtsMES8VnvS%2Fdkn1bHHs91yMK9LDISWqCk%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;800&quot; height=&quot;394&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;631&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MVC패턴 구조&lt;/figcaption&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 모델 Layer&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;모델 계층은 &lt;b&gt;데이터를 저장하지만 사용자 인터페이스에 대하여 알지 못하는 객체&lt;/b&gt;를 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;보통, 모델 레이어는 현실 세계의 사물을 대상으로 한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ex) 전화번호부 앱이 있다면, 해당 전화번호부의 전화번호 정보들을 담은 전화번호 리스트가 바로 Model.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 뷰 Layer&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;뷰 계층은&lt;b&gt; 사용자에게 시각적으로 보이는 모든 객체&lt;/b&gt;를 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;so, View는 앱의 UI를 구성하는 역할을 하며 대부분 이미 만들어져 있는 것들을 그대로 사용하여 앱 구성한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ex) 전화번호부 앱이 있다면, 해당 전화번호부의 전화번호를 보여주는 텍스트 필드나, 전화번호 추가버튼 등등&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 컨트롤러 Layer&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;컨트롤러 계층은 앱을 관리하는 앱의 관리자 역할을 하는 객체를 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;컨트롤러는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;사용자에게 보이는 뷰들을 구성하고 &amp;amp; 뷰와 모델을 연결하고 동기화되는 것을 보장해주는 역할을한다.&amp;nbsp;&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;뷰 객체를 통해 입력된 사용자의 입력을 처리하고, 모델의 데이터를 가져다가 조작&amp;amp;처리하여 다시 뷰에 전달한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, View 와 Model 사이의 중계자 역할을한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;뷰로부터 트리거되어&amp;nbsp; - 내부에 정의된 로직에따라 모델의 데이터를 갖다가 가공 후 결과를 뷰에 전달 -&amp;nbsp; &lt;span style=&quot;background-color: #ffffff; color: #383838; text-align: start;&quot;&gt;&amp;nbsp;뷰는 컨트롤러로 부터 받은 이 데이터를 사용하여 사용자에게 보여지는 앱의 UI를 렌더링하는 형태.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;ex) &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. 사용자가 텍스트필드(view)에 전화번호 입력후 추가하기버튼(view) 클릭시, 해당 전화번호가 컨트롤러 객체로 전송.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. TelController컨트롤러는 해당 전화번호 문자열을 전화번호 리스트(Model)에 update.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3. 전화번호 리스트가 업데이트되었으니, 컨트롤러는 해당 리스트를 뷰에게 전달&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;4. 뷰는 전달받은 전화번호 리스트(Model)데이터를 전화번호부의 전화번호 목록 컴포넌트(View)에 렌더링&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;5. so, 사용자가 추가한 전화번호가 전화번호 목록에 추가된 효과 by MVC패턴&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;847&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b72Zqo/btsME5mEvNO/yLUlW0wFZGcAVpnRRwjF30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b72Zqo/btsME5mEvNO/yLUlW0wFZGcAVpnRRwjF30/img.png&quot; data-alt=&quot;MVC패턴 흐름도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b72Zqo/btsME5mEvNO/yLUlW0wFZGcAVpnRRwjF30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb72Zqo%2FbtsME5mEvNO%2FyLUlW0wFZGcAVpnRRwjF30%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;847&quot; height=&quot;588&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MVC패턴 흐름도&lt;/figcaption&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  Xcode 실행&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BfTrl/btsMJAmBfY5/BjYDZkRSfejiGc32RfGYR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BfTrl/btsMJAmBfY5/BjYDZkRSfejiGc32RfGYR0/img.png&quot; data-alt=&quot;최신 안정화 버전인 16.2 버전&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BfTrl/btsMJAmBfY5/BjYDZkRSfejiGc32RfGYR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBfTrl%2FbtsMJAmBfY5%2FBjYDZkRSfejiGc32RfGYR0%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;700&quot; height=&quot;284&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;1049&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;최신 안정화 버전인 16.2 버전&lt;/figcaption&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 본격적인 개발을 위해 Xcode를 실행시켜준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 설치된 Xcode의 버전은 16.2 이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;&lt;/span&gt;&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;style8&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  프로젝트 생성&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1572&quot; data-origin-height=&quot;1012&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/esiZpH/btsMJdMboB1/GQ0GkIfDQoQFFCXq36bFy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/esiZpH/btsMJdMboB1/GQ0GkIfDQoQFFCXq36bFy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/esiZpH/btsMJdMboB1/GQ0GkIfDQoQFFCXq36bFy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FesiZpH%2FbtsMJdMboB1%2FGQ0GkIfDQoQFFCXq36bFy0%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;700&quot; height=&quot;451&quot; data-origin-width=&quot;1572&quot; data-origin-height=&quot;1012&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하나의 앱 개발을 위한 개발공간인 프로젝트를 생성해주자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;ldquo;Create a new Xcode project&amp;rdquo;클릭&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qn3oT/btsMKxWVIpN/VaRzOxhM6NwkDdE74YLO71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qn3oT/btsMKxWVIpN/VaRzOxhM6NwkDdE74YLO71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qn3oT/btsMKxWVIpN/VaRzOxhM6NwkDdE74YLO71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqn3oT%2FbtsMKxWVIpN%2FVaRzOxhM6NwkDdE74YLO71%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;700&quot; height=&quot;525&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우리는 아이폰에서 실행 가능한 아이폰 앱 개발을 목표로하고있기에, IOS 플렛폼 앱 프로젝트를 선택해주어야한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;상단의 이미지처럼 IOS - App을 선택해주자.&lt;/span&gt;&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;style8&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XPISb/btsMKs9a5vx/9s1W1jIIJORrJfJMDmp451/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XPISb/btsMKs9a5vx/9s1W1jIIJORrJfJMDmp451/img.png&quot; data-alt=&quot;프로젝트 옵션 지정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XPISb/btsMKs9a5vx/9s1W1jIIJORrJfJMDmp451/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXPISb%2FbtsMKs9a5vx%2F9s1W1jIIJORrJfJMDmp451%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;700&quot; height=&quot;525&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;1264&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. Product Name: 프로젝트의 이름&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. Organization identifier: 소속 단체에 대한 식별자(해당 기업의 주소 도메인 등등)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3. Interface: 프로젝트UI 선택(우리는 스토리보드 형태로 간단하게 ui를 구성할 예정)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;4. Language: IOS앱 개발을 위한 스위프트 언어&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;5. Testing System &amp;amp; Storage: 별도로 지정해주지 않도록하자(none)&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;&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;style8&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;1120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dconcD/btsMKdRZHYv/eC0X5XLZsaks3crkkH3iyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dconcD/btsMKdRZHYv/eC0X5XLZsaks3crkkH3iyK/img.png&quot; data-alt=&quot;프로젝트 경로 지정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dconcD/btsMKdRZHYv/eC0X5XLZsaks3crkkH3iyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdconcD%2FbtsMKdRZHYv%2FeC0X5XLZsaks3crkkH3iyK%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;700&quot; height=&quot;430&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;1120&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 프로젝트 디렉터리가 생성될 경로를 지정해주어야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;본 프로젝트는 간단하게 데스크탑 바탕화면에 프로젝트 디렉터리를 설치해주겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그리고 하단의 Source Control같은 경우는 해당 프로젝트에 git 레포지토리로 버전 관리를 할 것인지 여부인데, 하지않도록 하겠다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1974&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9Nx2F/btsMJHMNYXi/OFAqPdhocNQiKTShQt2eC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9Nx2F/btsMJHMNYXi/OFAqPdhocNQiKTShQt2eC0/img.png&quot; data-alt=&quot;프로젝트 생성 후 첫화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9Nx2F/btsMJHMNYXi/OFAqPdhocNQiKTShQt2eC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9Nx2F%2FbtsMJHMNYXi%2FOFAqPdhocNQiKTShQt2eC0%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;3024&quot; height=&quot;1974&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1974&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;앞의 프로젝트 설정을 모두 마치면 위와같이 프로젝트의 첫화면이 나온다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;필자는 별도로 메뉴바 상단에 체크해둔 화면분할 버튼을 클릭하여 화면을 좌우로 구분하였고,&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;좌측화면에는 Main.storyboard ui화면을 띄워두었고&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;우측화면에는 ViewController.swift 코드화면을 띄워두워 작업하기 수월한 환경으로 세팅해주었다.&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;2800&quot; data-origin-height=&quot;1746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMVNhy/btsMKOc66uU/ZipNW7wiKtGZJmRwgGNwP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMVNhy/btsMKOc66uU/ZipNW7wiKtGZJmRwgGNwP0/img.png&quot; data-alt=&quot;스토리보드의 디바이스 모형에 View컴포넌트 끌어놓기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMVNhy/btsMKOc66uU/ZipNW7wiKtGZJmRwgGNwP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMVNhy%2FbtsMKOc66uU%2FZipNW7wiKtGZJmRwgGNwP0%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;2800&quot; height=&quot;1746&quot; data-origin-width=&quot;2800&quot; data-origin-height=&quot;1746&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스토리보드의 디바이스 모형에 View컴포넌트 끌어놓기&lt;/figcaption&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 스토리보드로 간편하게 ios앱의 UI를 만들어보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;앞서 언급했듯이 스토리보드 방식은 UI구성이 매우 간편하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;디바이스 모형의 좌측에 보이는 리스트 영역을 Document Outline 이라고 하는데, ViewController 에 대응하는 View의 모든 요소들을 계층적으로 표시해주는 역할을 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉 현재 앱을 구성하는 뷰들을 계층적으로 쉽게 확인시켜주는 리스트이다.&lt;/span&gt;&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;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  &amp;lt;실습&amp;gt;: 간단한 퀴즈 앱 만들기&lt;/b&gt;&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 앱의 흐름은, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;상단에는 퀴즈 문제를 보여주는 uiLabel 하나와 그 아래에는 다음 문제로 넘겨주는 이벤트를 발생시키는 uiButton 하나를두고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하단에는 현재 문제의 정답 텍스트를 표시해주는 역할을하는&amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;uiLabel 하나와 그 아래에는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;현재 퀴즈 문제의 정답을 보여주는 &lt;/span&gt;이벤트를 발생시키는 uiButton 하나를두고자 한다.&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이를 위해선 View와 UIViewController의 연결이 필요하다.&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✏️&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;View와 UIViewController의 연결&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&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;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;View와 UIViewController의 연결이란 무엇일까?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;뷰는 레이블, 버튼, 토글 등 ios 및 andriod os에서 화면 구성에 쓰이는 직접적인 ui들이다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이 뷰들은 해당 os가 모바일 기기에다가&amp;nbsp;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;os레벨에서 화면에 렌더링해주기 때문에, 코드로 이 뷰들에 접근-엑세스하기 위해서 필요한 것이 바로&amp;nbsp; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;UIViewController.swift파일이다. 우리는 스위프트 언어로 ios ui들을 배치하고 컨트롤해야하는 것이다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉 UIViewController에서 Label 뷰에 데이터를 write하려고하면 이 Label에 뷰에 액세스할 수 있어야 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;안드로이드에서 label = findViewById(&amp;hellip;)와 동일&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;또한, 사용자가 버튼View를 클릭하면 그 클릭 이벤트발생에 대한 정보는 UIViewController에 알려진다음 이 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;UIViewController에 작성해둔 코드에 맞게 적절한 이벤트 처리가 이루어져야 할 것이다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;안드로이드에서는 button.setOnClickListener(&amp;hellip;)와 동일&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이 View 들을 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;UIViewController와&amp;nbsp;&lt;/span&gt;연결하는 가장 쉬운 방법이 있다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;복잡하게 해당 뷰에 대한 참조 코드들을 작성할 필요없이, StoryBoard에서 원하는 뷰를 &amp;ldquo;Control+드래그&amp;rdquo;하여 UIViewController의 메인 퍼블릭 클래스내에 드롭한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;3024&quot; data-origin-height=&quot;1974&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYxWzJ/btsMKvES0Bh/xzygjF0t92rWO9yeuY2uQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYxWzJ/btsMKvES0Bh/xzygjF0t92rWO9yeuY2uQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYxWzJ/btsMKvES0Bh/xzygjF0t92rWO9yeuY2uQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYxWzJ%2FbtsMKvES0Bh%2FxzygjF0t92rWO9yeuY2uQK%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;3024&quot; height=&quot;1974&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;1974&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 Outlet/Action을 선택하고, 해당 컴포넌트의 적절한 이름을 정해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;텍스트를 보여주기 용도인 Label의 경우, 해당 레이블 컴포넌트의 주소, 즉 레퍼런스만을 참조하면되므로 Outlet 연결이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &amp;ndash; Outlet: 객체의 레퍼런스를 의미.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;무언가 이벤트를 listening하고 있다가 발생시 해당 이벤트를 처리하는 용도인 Button의 경우, 해당 버튼에 발생하는 클릭이벤트를 대기하고있다가 발생시 처리하는 메서드가 필요하므로 Action 연결이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &amp;ndash; Action: 객체의 listener를 의미.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;먼저 퀴즈의 정답을 출력해주는 용도인 qLabel을 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;UIViewController에 연결해보자.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;573&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bByzdt/btsMKy9uNEW/4LXHigmeJ4a5dqakHaB2D1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bByzdt/btsMKy9uNEW/4LXHigmeJ4a5dqakHaB2D1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bByzdt/btsMKy9uNEW/4LXHigmeJ4a5dqakHaB2D1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbByzdt%2FbtsMKy9uNEW%2F4LXHigmeJ4a5dqakHaB2D1%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;794&quot; height=&quot;573&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;573&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그러면&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;UIViewController 코드부분에 해당 뷰가 코드로 기술되어진 것을 확인해볼 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;자 이제 2개의 레이블과 2개의 버튼을 전부 뷰 컨트롤러 코드에 연결시켜보자. &lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때, 레이블 컴포넌트의 경우 outlet 연결이므로 클래스의 맴버변수(필드)로, 버튼 컴포넌트의 경우 action연결이므로 클래스의 메서드 포지션으로 연결해준다 생각하자.&lt;/span&gt;&lt;/blockquote&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;1184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmCwUz/btsMJrKcgMD/20JK5nUtnPT1J896Ba6eWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmCwUz/btsMJrKcgMD/20JK5nUtnPT1J896Ba6eWK/img.png&quot; data-alt=&quot;2개의 레이블과 2개의 버튼을 뷰컨트롤러 코드와 연결해준 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmCwUz/btsMJrKcgMD/20JK5nUtnPT1J896Ba6eWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmCwUz%2FbtsMJrKcgMD%2F20JK5nUtnPT1J896Ba6eWK%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;1704&quot; height=&quot;1184&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;1184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2개의 레이블과 2개의 버튼을 뷰컨트롤러 코드와 연결해준 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;여기서 주의해야할 점은, 초기 레이블 컴포넌트는 해당 텍스트 길이만큼 width height를 차지하기에 퀴즈의 문제와 정답 문자열이 길다는 점을 고려해서 화면의 전체 width만큼 늘려주고, 구분을 위해 background도 초록색 노란색으로 지정해주었다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&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;style8&quot; /&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✏️퀴즈 문제와 정답을 담아둘 배열 생성&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 퀴즈의 문제와 정답 데이터를 생성해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;일련의 문자열 데이터들을 보관하기위해 가장 보편적인 자료구조인 배열을 생성해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1741850542935&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
import UIKit


class ViewController: UIViewController {

    @IBOutlet weak var qLabel: UILabel!
    @IBOutlet weak var aLabel: UILabel!
    
    var questions = [
    &quot;대한민국의 수도는 무엇인가요?&quot;,
    &quot;아이폰의 운영체제는 무엇인가요?&quot;,
    &quot;7+21은 얼마인가요?&quot;
    ]
    var answers = [
    &quot;서울&quot;,
    &quot;IOS&quot;,
    &quot;28&quot;
    ]
    var currentIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    @IBAction func qBtn(_ sender: UIButton) {
    }
    
    @IBAction func aBtn(_ sender: UIButton) {
    }
    
}&lt;/code&gt;&lt;/pre&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;style8&quot; /&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✏️ 로직 작성&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 퀴즈 데이터들과 view 컴포넌트들을 이용하여 퀴즈 앱 로직을 작성해보자.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;주의 깊게 다뤄야하는 부분은 세 부분이다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. count 변수&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. viewDidLoad() 함수&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3.. 버튼 이벤트헨들러&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;✏️&amp;nbsp;&lt;/b&gt;viewDidLoad() 함수&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;ndash; 이 함수는 앱 프로그램이 완전히 실행된 직후 가장 처음 호출되는 Callback 함수이다. (js의 DOMContentLoaded 같은느낌)&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;ndash; 즉, 이 함수는 이 View에 대한 초기화 역할 - 뷰컨트롤러 클래스의 생성자와 비슷한 느낌이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;주의: 생성자는 아님 &lt;/span&gt;&lt;/blockquote&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;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  최종 코드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1741851146486&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import UIKit


class ViewController: UIViewController {

    @IBOutlet weak var qLabel: UILabel!
    @IBOutlet weak var aLabel: UILabel!
    
    var questions = [
    &quot;대한민국의 수도는 무엇인가요?&quot;,
    &quot;아이폰의 운영체제는 무엇인가요?&quot;,
    &quot;7+21은 얼마인가요?&quot;
    ]
    var answers = [
    &quot;서울&quot;,
    &quot;IOS&quot;,
    &quot;28&quot;
    ]
    var currentIndex = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        qLabel.text = questions[currentIndex]
    }

    @IBAction func qBtn(_ sender: UIButton) {
        currentIndex = (currentIndex+1)%questions.count
        qLabel.text = questions[currentIndex]
    }
    
    @IBAction func aBtn(_ sender: UIButton) {
        aLabel.text = answers[currentIndex]
    }
    
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  프로그램 실행하여 가상 디바이스에&amp;nbsp; 앱 빌드하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 퀴즈 프로그램을 실행하여 가상 아이폰 디바이스에 앱으로 빌드시켜보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;navigator 사이드바의 상단의 Play버튼을 클릭하면 가상 디바이스에 현재 프로그램이 자동으로 빌드&amp;amp;실행되어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1301&quot; data-origin-height=&quot;1669&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvLfI8/btsMKfWE03V/nmgfLCPCPAfLoWj7gKOqjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvLfI8/btsMKfWE03V/nmgfLCPCPAfLoWj7gKOqjk/img.png&quot; data-alt=&quot;아이폰 16 프로 모델 가상 디바이스에 앱 빌드 &amp;amp;amp; 실행화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvLfI8/btsMKfWE03V/nmgfLCPCPAfLoWj7gKOqjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvLfI8%2FbtsMKfWE03V%2FnmgfLCPCPAfLoWj7gKOqjk%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;700&quot; height=&quot;898&quot; data-origin-width=&quot;1301&quot; data-origin-height=&quot;1669&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아이폰 16 프로 모델 가상 디바이스에 앱 빌드 &amp;amp; 실행화면&lt;/figcaption&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;qButton을 클릭하면 다음 퀴즈문제로 넘어가고, aButton을 클릭하면 현재 퀴즈문제의 정답을 aLabel에 출력시켜준다.&lt;/b&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>IOS</category>
      <category>ios</category>
      <category>SWIFT</category>
      <category>Xcode</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/34</guid>
      <comments>https://basecoding.tistory.com/entry/iOS-Programming-1-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EB%B0%8F-%EA%B8%B0%EB%B3%B8%EA%B0%9C%EB%85%90%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%8B%A4%EC%8A%B5#entry34comment</comments>
      <pubDate>Thu, 13 Mar 2025 16:40:03 +0900</pubDate>
    </item>
    <item>
      <title>게임예제를 통해 JAVA 프로그램 전체 실행과정 분석: 클래스 로딩 &amp;amp; static 멤버 로딩</title>
      <link>https://basecoding.tistory.com/entry/JAVA-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%A0%84%EC%B2%B4-%EC%8B%A4%ED%96%89%EA%B3%BC%EC%A0%95-%EB%B6%84%EC%84%9D-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%A1%9C%EB%94%A9-static-%EB%A9%A4%EB%B2%84-%EB%A1%9C%EB%94%A9</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg8v4g/btsL8V0aJI8/Quwda7n0Fm8wa558xb6TnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg8v4g/btsL8V0aJI8/Quwda7n0Fm8wa558xb6TnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg8v4g/btsL8V0aJI8/Quwda7n0Fm8wa558xb6TnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg8v4g%2FbtsL8V0aJI8%2FQuwda7n0Fm8wa558xb6TnK%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;300&quot; height=&quot;188&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;자바 프로그램이 실행될 때, &lt;b&gt;클래스 로딩(Class Loading)&lt;/b&gt; 과정과 함께 &lt;b&gt;static 멤버(필드 및 메서드) 로딩&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;본 글에서는 JVM(Java Virtual Machine)이 프로그램을 실행하는 과정과, static 멤버가 언제, 어떻게 메모리에 적재되는지를 정리해 보겠습니다.&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1️⃣ 클래스 로딩이란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;클래스 로딩(Class Loading)은 &lt;b&gt;디스크(하드디스크 or SSD)에 저장된 .class 바이트코드 파일을 JVM이 읽어서 메모리에 적재하는 과정&lt;/b&gt;을 의미합니다. 즉, 실행을 위해 필요한 클래스의 정보(메타데이터, 메서드 코드, 정적 변수 등)가 적절한 메모리 영역에 배치됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  클래스 로딩의 주요 특징&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅ &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;모든 클래스가 한 번에 로드되지 않음! (해당 클래스가 처음 참조될 때, 언급될때 로드됨 - Lazy Loading) &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;✅&lt;/span&gt; &amp;nbsp;최초로 참조되는 순간(new, static 접근 등)에 JVM이 해당 클래스를 디스크에서 찾아서 메모리에 로드 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;✅&lt;/span&gt; &amp;nbsp;static 변수는 클래스가 로드될 때 한 번만 초기화됨. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;✅&lt;/span&gt; &amp;nbsp;new 키워드로 생성된 객체는 &lt;b&gt;힙(Heap) 영역&lt;/b&gt;에 저장됨.&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2️⃣ JVM 메모리 구조 (클래스 로딩 관련 부분)&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;JVM은 자바 프로그램 실행을 위해 여러 개의 메모리 영역을 사용합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;클래스 로딩과 관련된 주요 영역은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 메소드 영역 (Method Area, 또는 Metaspace)&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;.class 파일이 로드되면, 해당 클래스의 &lt;b&gt;메타데이터(클래스 정보), static 변수, 메서드 코드, 상수&lt;/b&gt; 등이 저장됨.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;모든 스레드가 공유하는 영역.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Java 8 이전: PermGen 영역 사용 &amp;rarr; Java 8 이후: &lt;b&gt;Metaspace&lt;/b&gt;로 변경되었음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 힙 영역 (Heap Area)&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;new 키워드로 생성한 &lt;b&gt;객체(instance)&lt;/b&gt; 가 저장되는 공간.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;GC(Garbage Collector)의 관리 대상.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 스택 영역 (Stack Area)&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;메서드 호출 시 &lt;b&gt;지역 변수, 매개변수, 리턴 주소&lt;/b&gt; 등을 저장하는 공간.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 스레드마다 개별적으로 존재.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3️⃣ JAVA 프로그램 실행 시 클래스 로딩 과정&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  1) 디스크에 저장된 바이트코드 파일 (.class)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;A 게임 프로그램이 있다고 가정하면, 디스크에는 다음과 같은 .class 파일들이 존재합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;A_Game/  
 ├── Main.class  
 ├── Player.class  
 ├── Enemy.class  
 ├── Item.class  
 ├── World.class  
&lt;/code&gt;&lt;/pre&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Main.class: 게임 프로그램(프로세스)의 시작점 (엔트리 포인트, public static void main(String[] args))&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Player.class: 플레이어 캐릭터 관련 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Enemy.class: 적 캐릭터 관련 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Item.class: 아이템 관련 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;World.class: 맵, 환경 관련 클래스&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  2) OS가 JVM을 실행하고, Main 클래스를 로드&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용자가 A_Game을 실행하면, OS가 &lt;b&gt;JVM(Java Virtual Machine)을 실행&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;JVM은 &lt;b&gt;Main.class를 디스크에서 읽어와 메모리에 로드&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Main.class의 바이트코드가 &lt;b&gt;메소드 영역(Method Area)에 적재됨&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;static 변수들이 먼저 &lt;b&gt;메소드 영역에 초기화됨&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;public static void main(String[] args) 메서드 실행이 시작됨.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  3) main()에서 다른 클래스 참조 시 로드 발생&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Player player = new Player();  // Player 클래스 로드됨
    }
}
&lt;/code&gt;&lt;/pre&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;new Player(); 실행 시, JVM이 &lt;b&gt;Player.class&lt;/b&gt;를 디스크에서 찾아 로드.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Player.class의 바이트코드가 &lt;b&gt;메소드 영역에 로드됨&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;static 필드 초기화 후, new Player(); 실행 &amp;rarr; &lt;b&gt;힙(Heap) 영역에 Player 객체 생성&lt;/b&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  4) 필요할 때만 추가 클래스 로드 (Lazy Loading)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;public class Player {
    Item sword = new Item(&quot;Sword&quot;);  // Item 클래스가 아직 로드되지 않았다면, 여기서 로드됨.
}
&lt;/code&gt;&lt;/pre&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;new Item(&quot;Sword&quot;) 실행 시, Item.class가 메모리에 로드됨.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이후 Item 관련 코드 실행 가능.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, &lt;b&gt;모든 클래스를 한 번에 로드하는 것이 아니라, 필요한 순간(최초 참조 시)에 로드됨.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;rarr; 이를 &lt;b&gt;Lazy Class Loading (지연 로딩)&lt;/b&gt; 또는 &lt;b&gt;On-Demand Loading&lt;/b&gt; 이라고 함.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;4️⃣ static 멤버 로딩 과정&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  static 변수, static 블록 로딩 순서&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class Example {
    static int staticVar = 10;

    static {
        System.out.println(&quot;Static block executed!&quot;);
        staticVar = 20;
    }
}
&lt;/code&gt;&lt;/pre&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Example 클래스가 처음 로드될 때:&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;static int staticVar가 &lt;b&gt;메소드 영역(Method Area)&lt;/b&gt; 에 기본값(0)으로 초기화됨.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;static 블록 실행 &amp;rarr; staticVar 값이 20으로 변경됨.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이후 Example 클래스를 사용할 수 있음.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  static 멤버는 클래스 로딩 시 한 번만 실행됨&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Example ex1 = new Example();  // 클래스 로딩 &amp;amp; static 블록 실행
        Example ex2 = new Example();  // static 블록 실행 X (이미 클래스 로드됨)
    }
}
&lt;/code&gt;&lt;/pre&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Example 클래스가 처음 로드될 때만 static 블록 실행됨.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이후 객체를 여러 개 생성해도 &lt;b&gt;static 블록과 static 변수 초기화는 재실행되지 않음!&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 결론: JVM의 클래스 로딩 &amp;amp; static 멤버 로딩 순서&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1️⃣ OS가 java 실행 &amp;rarr; JVM 실행됨&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2️⃣ Main.class 디스크에서 읽어서 메모리에 로드 (메소드 영역)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3️⃣ static 변수 및 static 블록 실행&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;4️⃣ main() 실행 &amp;rarr; 다른 클래스(Player, Enemy 등) 참조하면, 필요한 순간에 클래스 로딩 발생&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;5️⃣ new 키워드로 객체 생성 시, &lt;b&gt;힙(Heap)에 저장됨&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;6️⃣ 프로그램이 실행되는 동안 필요한 클래스가 점진적으로 로드됨&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #f6e199;&quot;&gt;즉, 자바 프로그램은 처음엔 Main.class만 로드되고, 실행 도중 필요한 순간(참조되는 순간)에만 다른 클래스들이 메모리에 적재된다는 것이 핵심!&lt;/span&gt;&lt;/h3&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  게임 예제코드를 통해 클래스&amp;amp;static 맴버 로드 과정 마무리 이해하기&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1738886640027&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 게임 아이템 클래스
 * - 이 클래스는 GameItem 객체가 처음 참조될 때 로딩
 * - static 멤버는 클래스 로딩 시 한 번만 초기화
 */
class GameItem {
    // static 변수는 클래스 로딩 시 메소드 영역(Method Area)에 생성
    private static int totalItems = 0;  // 처음에는 0으로 초기화
    private String name;  // 인스턴스 변수는 힙(Heap) 영역에 생성
    
    // static 초기화 블록
    // - 클래스가 처음 로딩될 때 한 번만 실행
    // - static 변수 초기화 후에 실행
    static {
        System.out.println(&quot;[GameItem] Static 블록 실행 - 클래스 로딩 시점&quot;);
        System.out.println(&quot;[GameItem] totalItems 초기화: &quot; + totalItems);
    }
    
    // 생성자는 new 키워드로 객체 생성 시마다 실행
    public GameItem(String name) {
        this.name = name;  // 인스턴스 변수 초기화
        totalItems++;      // static 변수 증가
        System.out.println(&quot;[GameItem] 새로운 아이템 생성: &quot; + name + &quot; (총 &quot; + totalItems + &quot;개)&quot;);
    }
}

/**
 * 플레이어 클래스
 * - Player 객체가 처음 참조될 때 로딩
 * - GameItem 클래스는 equipWeapon() 메서드가 처음 호출될 때 로딩(지연 로딩)
 */
class Player {
    // static 변수는 클래스 로딩 시점에 메소드 영역에 생성
    private static int playerCount = 0;
    // 인스턴스 변수들은 객체 생성 시 힙 영역에 생성
    private String name;
    private GameItem weapon;  // 참조형 변수 - null로 초기화
    
    // static 초기화 블록
    static {
        System.out.println(&quot;[Player] Static 블록 실행 - 클래스 로딩 시점&quot;);
        System.out.println(&quot;[Player] playerCount 초기화: &quot; + playerCount);
    }
    
    // 생성자 - 객체 생성시마다 실행
    public Player(String name) {
        this.name = name;
        playerCount++;  // static 변수 증가
        System.out.println(&quot;[Player] 새로운 플레이어 생성: &quot; + name + &quot; (총 &quot; + playerCount + &quot;명)&quot;);
    }
    
    // 이 메서드가 처음 호출될 때 GameItem 클래스가 로딩(지연 로딩)
    public void equipWeapon(String weaponName) {
        this.weapon = new GameItem(weaponName);  // GameItem 클래스 참조 발생
        System.out.println(&quot;[Player] &quot; + name + &quot;가 &quot; + weaponName + &quot;을(를) 장착함&quot;);
    }
}

/**
 * 메인 클래스
 * - JVM이 가장 먼저 로딩하는 클래스
 * - 다른 클래스들은 이 클래스에서 처음 참조될 때 로딩
 */
public class GameDemo {
    public static void main(String[] args) {
        System.out.println(&quot;==== 게임 시작 - GameDemo 클래스 로딩 완료 ====&quot;);
        
        // 1. Player 클래스 최초 참조 -&amp;gt; 클래스 로딩 발생
        System.out.println(&quot;\n1. 첫 번째 플레이어 생성 - Player 클래스 로딩됨&quot;);
        Player p1 = new Player(&quot;Alice&quot;);  // Player 클래스 로딩 &amp;amp; static 초기화
        
        // 2. GameItem 클래스 최초 참조 -&amp;gt; 클래스 로딩 발생
        System.out.println(&quot;\n2. 첫 번째 플레이어 무기 장착 - GameItem 클래스 로딩됨&quot;);
        p1.equipWeapon(&quot;검&quot;);  // GameItem 클래스 로딩 &amp;amp; static 초기화
        
        // 3. Player 클래스는 이미 로딩되어 있음 -&amp;gt; static 초기화 없이 인스턴스만 생성
        System.out.println(&quot;\n3. 두 번째 플레이어 생성 - Player 클래스는 이미 로딩됨&quot;);
        Player p2 = new Player(&quot;Bob&quot;);  // static 블록 실행 없음
        
        // 4. GameItem 클래스도 이미 로딩되어 있음 -&amp;gt; static 초기화 없이 인스턴스만 생성
        System.out.println(&quot;\n4. 두 번째 플레이어 무기 장착 - GameItem 클래스는 이미 로딩됨&quot;);
        p2.equipWeapon(&quot;활&quot;);  // static 블록 실행 없음
        
        System.out.println(&quot;\n==== 게임 종료 ====&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS 지식</category>
      <category>java 실행과정</category>
      <category>java 클래스 로딩</category>
      <category>static 맴버 로딩</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/33</guid>
      <comments>https://basecoding.tistory.com/entry/JAVA-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%A0%84%EC%B2%B4-%EC%8B%A4%ED%96%89%EA%B3%BC%EC%A0%95-%EB%B6%84%EC%84%9D-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%A1%9C%EB%94%A9-static-%EB%A9%A4%EB%B2%84-%EB%A1%9C%EB%94%A9#entry33comment</comments>
      <pubDate>Fri, 7 Feb 2025 09:08:54 +0900</pubDate>
    </item>
    <item>
      <title>[정보처리기사] 2025 정보처리기사 필기 &amp;lt;1과목 소프트웨어 설계&amp;gt; 정리2</title>
      <link>https://basecoding.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-2025-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%ED%95%84%EA%B8%B0-1%EA%B3%BC%EB%AA%A9-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84-%EC%A0%95%EB%A6%AC2</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  현행 시스템 분석 &amp;amp; 파악 절차 3단계&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;내가 무턱대고 최신 기술을 사용해서 sw프로그램을 만들어서 회사에 넘겨준다고해도, 해당 회사의 시스템이 구형이라면 큰일.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;sw를 개발할때, 이 회사가 어떻게 굴러가는지 - 하는일이 뭔지 - 여기에 어떤 컴퓨터가 설치되어있는지 - 어떤 인터넷 쓰는지 데이터베이스는 뭐쓰는지 등 분석을 해야함.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, 새로 개발하려는 시스템의 개발 범위를 명확히 설정하기 위해 현행 시스템의 구성과 제공 기능, 시스템 간의 전달 정보, 사용되는 기술 요소, 소프트웨어, 하드웨어, 그리고 네트워크 구성 등을 파악하는 것 = &amp;gt; 현행 시스템 파악&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1단계&lt;/span&gt;&lt;/h4&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;시스템 &lt;b&gt;구&lt;/b&gt;성 파악 (회사에 가서 시스템 파악: 수출하는 업체인지, 무슨 업무하는 업체인지)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;시스템 &lt;b&gt;기&lt;/b&gt;능 파악 (주요기능, 하부기능,세부기능으로 구분)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;시스템 &lt;b&gt;인&lt;/b&gt;터페이스 파악 (회사의 각 부서별로 어떻게 데이터를 주고받는지)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2단계&amp;nbsp;&lt;/span&gt;&lt;/h4&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;아&lt;/b&gt;키텍처 구성 파악 (각 시스템이 어떤 원리로 작동하는지 최상위 수준에서 계층별로 표현한 아키텍쳐 구성도 작성)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;소&lt;/b&gt;프트웨어 구성 파악 (sw들의 제품명, 라이센스 갯수 등 window10, Apache Tomcat, MySQL...)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;3단계&amp;nbsp;&lt;/span&gt;&lt;/h4&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;하&lt;/b&gt;드웨어 구성 파악 (서버의 수량 주요 스펙, 이중화의 적용 등)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;네&lt;/b&gt;트워크 구성 파악 (회사의 인터넷 네트워크 연결 상황 등)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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 style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Q. 현행 시스템 분석에서 고려하지 않아도 되는 항목은?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;DBMS 분석&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;네트워크 분석&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;운영체제 분석&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;인적 자원 분석&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;정답: 4번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;현행 시스템 파악 절차 2단계의 소프트웨어 구성 파악 단계에서 sw인 운영체제&amp;amp;DBMS 분석이 이루어지고,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;3단계의 네트워크 구성 파악 단계에서 네트워크 분석이 이루어지는 반면,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;인적 자원 분석은 현행 시스템 분석에서 고려하지 않는다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  요구사항 개발&lt;/b&gt;&lt;/span&gt;&lt;/h3&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; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;요구공학의 목적: &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;고객과 개발자, 디자이너와 개발자 간에 원활한 의사소통 수단을 제공해줌. 요구사항 이력관리로 개발비용 절약.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;SWEBOK에 따른 요구사항 개발 프로세스:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;요구사항 &lt;span style=&quot;color: #ee2323;&quot;&gt;도출&lt;/span&gt; -&amp;gt; 요구사항 &lt;span style=&quot;color: #ee2323;&quot;&gt;분석&lt;/span&gt; -&amp;gt; 요구사항 &lt;span style=&quot;color: #ee2323;&quot;&gt;명세&lt;/span&gt;(문서화) -&amp;gt; 요구사항 &lt;span style=&quot;color: #ee2323;&quot;&gt;검증&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 요구사항 도출:&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;sw가 해결해야 할 문제를 이해하는 첫번째 단계. 현재의 상태를 파악하고 문제를 정의한 후 문제 해결과 목표를 명확히 도출하는 단계&lt;/b&gt;&lt;/span&gt;&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: #ee2323; background-color: #ffc1c8; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;+ 요구사항 도출 기법들  &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;고객의 발표, 문서 조사, 설문, 업무 절차 및 양식 조사, 브레인스토밍, 워크숍, 인터뷰, 관찰 및 모델의 프로토타이핑, Use Case, 벤치마킹, BPR(업무 재설계), RFP(제안요청서)&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/u&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;&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 2&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;. 요구사항 분석:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1단계에서 도출된 요구사항들은 구조화와 열거가 어려워, 명확하지 못하거나 모호한 부분들이 많음.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;so, 도출된 사용자의 요구사항들 중에서, 사용자의 실제&amp;nbsp; 요구사항이 무엇인지에 대해서 걸러 내는 단계.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;요구사항 정의를 문서화하는 과정.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;+ 요구사항 분석을 위한 기법들  &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;사용자 의견 청취, 사용자 인터뷰, 현재 사용 중인 각종 문서 분석과 중재, 관찰 및 모델 작성 기술, 설문 조사를 통한 의견 수렴&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt;+ 요구사항 분석 수행 단계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 문제 인식 (인터뷰, 설문 조사 등을 활용하여 요구사항을 파악)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 전개 (파악한 문제를 자세히 조사)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 평가와 종합 (요구들을 다이어그램이나 자동화 도구를 이용하여 종합)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. 검토 (요구분석 작업의 내용을 검토, 재정리하는 과정)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5. 문서화 (요구사항 분석 내용을 문서로 만드는 단계)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #ffc9af; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 기능적 요구사항 vs 비기능적 요구사항&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;기능적 요구사항: 시스템이 실제로 어떻게 동작하는지에 관점을 둔 요구사항&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;비기능적 요구사항: 시스템 구축에 대한 성능,보안,품질,안정성 등으로 실제 수행에 보조적인 요구사항&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 3&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;. 요구사항 명세:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;체계적으로 검토, 평가, 승인될 수 있도록 문서로 만드는 것을 의미한다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;기능 요구사항은 빠지는 부분없이 명확하게 기술한다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;요구사항 명세 기법 (정형 명세, 비정형 명세)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;+ &lt;span style=&quot;color: #ee2323;&quot;&gt;정형 명세&lt;/span&gt;: 수학적 기반&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- Z, VDM, Petri-Net, LOTUS, CSP, CCS&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 장점: 정확하고 명세가 간결&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 단점: 낮은 이해도, 이해관계자의 부담 가중&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;+ &lt;span style=&quot;color: #ee2323;&quot;&gt;비정형 명세&lt;/span&gt;: 상태/기능/객체 중심 명세 기법 (자연어 기반)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- State Chart (SADT)&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- UseCase&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- FSM&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- Decision Table&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- ER 모델링&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 장점: 의사전달 방법 다양&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 단점: 불충분한 명세 &amp;amp; 모호성&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;요구사항 명세 속성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;- 정확성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;- 명확성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;- 완전성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;- 일관성&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;- 수정 용이성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;- 추적성&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 4&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;. 요구사항 확인:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;요구사항 분석 단계를 거쳐 - &amp;gt; 요구사항 명세 단계를 거쳐 -&amp;gt; 문서로 만들어진 요구사항 내용을 확인하고 검증하는 단계&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;요구사항 관리 도구를 이용하여 -&amp;nbsp; &amp;nbsp;이해관계자들이 문서를 검토하고 요구사항 정의 문서들에 대해 형상 관리를 한다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;요구사항 관리 도구의 필요성:  &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅ 요구사항 변경으로 인한 비용 편익 분석&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/b&gt; 요구사항 변경의 추적&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;✅&lt;/span&gt;&lt;/b&gt; 요구사항 변경에 따른 영향 평가&lt;/span&gt;&lt;/b&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;&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  UML&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;객체지향 소프트웨어 개발 과정에서 시스템 분석, 설계, 구현 등의 산출물을 명세화, 시각화, 문서화 할 때 사용하는 모델링 기술과 방법론을 통합하여 만든 범용 모델링 언어.&lt;/b&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt; &lt;b&gt;+ 럼바우(Rumbaugh) 객체지향 분석 기법 및 절차 &lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;객체 모델링(OMT)&lt;/span&gt;&lt;/b&gt;: 현실 세계에 있는, 시스템에서 요구되는 객체를 찾아내어 속성&amp;amp;연산(메서드) 식별 및 객체들 간의 관계를 규정하여 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;객체를 다이어그램으로 표시&lt;/b&gt;&lt;/span&gt;한다. &lt;b&gt;&amp;lt;&lt;span style=&quot;color: #ee2323;&quot;&gt;객체 다이어그램&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;동적 모델링&lt;/span&gt;: &lt;/b&gt;객체 간의 상호작용 표현 (사람&amp;amp;사람간의 ~~), 제어 흐름 - 상호작용 - 동작 순서 등의 상태를 시간 흐름에 따라 &lt;b&gt;&amp;lt;&lt;span style=&quot;color: #ee2323;&quot;&gt;상태 다이어그램&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;으로 표시한다. 동적이니깐 상태 &amp;amp; 다이어그램.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;기능 모델링&lt;/span&gt;: &lt;/b&gt;여러 프로세스 간의 &lt;b&gt;자료 흐름을 표시&lt;/b&gt;한다. 어떤 데이터를 입력하여 어떤 결과를 가져올 수 있을지를 표현. &lt;b&gt;&amp;lt;&lt;span style=&quot;color: #ee2323;&quot;&gt;데이터 흐름도&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  UML 소프트웨어에 대한 관점&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 기능적 관점:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용자 측면에서 본 sw의 기능을 나타낸다. 사용 사례 모델링이라고도 한다. 요구분석 단계에서 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;- Use Case Diagram&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt;2. 정적 관점:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;sw내부의 구성 요소 사이의 구조적 관계를 나타낸다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;객체, 속성, 연관 관계, 오퍼레이션의 시스템 구조를 나타낸다. (ex. 클래스 사이의 관계, 클래스 구성과 패키지 사이의 관계)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;- Class Diagram&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 동적 관점:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;시스템 내부 동작을 말한다. 상호작용으로 인한 상태 변화. state&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;- Sequance Diagram, State Diagram, Activity Diagram (움직이는 상태 관련 다이어그램들)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  UML 다이어그램의 분류:&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;UML 다이어그램은 크게 &lt;span style=&quot;color: #ee2323;&quot;&gt;구조 다이어그램&lt;/span&gt;, &lt;span style=&quot;color: #ee2323;&quot;&gt;행위 다이어그램&lt;/span&gt;으로 나뉜다.&amp;nbsp;&lt;/b&gt;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;  구조적 다이어그램들 (Structure Diagram)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;정적이고, 구조 표현을 위한 다이어그램이다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;클래스 다이어그램&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;객체 다이어그램&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;복합체 구조 다이어그램 (Composite Structure Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;배치 다이어그램 (Deployment Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;컴포넌트 다이어그램(Component Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;패키지 다이어그램&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  행위 다이어그램들 (Behavior Diagram)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;동적이고, 순차적인 표현을 위한 다이어그램이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;유스케이스 다이어그램 ( 사용자 관점에서 시스템 행위를 표현 )&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;활동 다이어그램 (Avtivity Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;상태 머신 구조 다이어그램 (State Machine Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Collaboration Diagram&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;순차 다이어그램(Sequence Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;상호작용 개요 다이어그램&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;통신 다이어그램 (Communication Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;타이밍 다이어그램(Timing Diagram)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  UML 관계 표현&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;-&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 단방향 연관관계&lt;/span&gt; (실선+화살표 &lt;span style=&quot;color: #ee2323;&quot;&gt;ㅡㅡㅡㅡㅡㅡㅡㅡ&amp;gt;&lt;/span&gt;)&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;- &lt;span style=&quot;color: #000000;&quot;&gt;양방향 연관관계&lt;/span&gt; &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;(실선+화살표x&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt; ㅡㅡㅡㅡㅡㅡㅡㅡ&lt;/span&gt;)&lt;/span&gt;&lt;/b&gt; &lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;- &lt;span style=&quot;color: #000000;&quot;&gt;의존 관계&lt;/span&gt; &lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;(점선+화살표&amp;nbsp; &lt;span style=&quot;color: #ee2323;&quot;&gt;-----------------------&lt;/span&gt; )&lt;/span&gt;&lt;/b&gt;&lt;/b&gt; &lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;- &lt;span style=&quot;color: #000000;&quot;&gt;일반화 관계&lt;/span&gt; (실선 + 빈 화살표 &lt;span style=&quot;color: #ee2323;&quot;&gt;ㅡㅡㅡㅡㅡㅡㅡㅡ▷&lt;/span&gt;)&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;- &lt;span style=&quot;color: #000000;&quot;&gt;집합(집약)관계&lt;/span&gt; (실선 + 빈 마름모&lt;span style=&quot;color: #ee2323;&quot;&gt; &lt;b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ㅡㅡㅡㅡㅡ&lt;b&gt;◇&lt;/b&gt; &lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt; ) : A객체가 B객체를 포함하는 관계. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;부분 객체를 다른 객체와 공유할 수 있다. 전체&amp;amp;부분 라이프사이클 독립적&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;- &lt;span style=&quot;color: #000000;&quot;&gt;포함(합성)관계&lt;/span&gt; (실선 + 꽉찬 마름모&lt;span style=&quot;color: #ee2323;&quot;&gt; &lt;b&gt;&lt;b&gt;------------&lt;/b&gt;&lt;/b&gt;◆&lt;/span&gt;) : 부분 객체가 전체 객체에 속하는 강한 결합 관계.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;전체 객체가 사라지면 부분 객체도 사라진다. 전체&amp;amp;부분 라이프사이클 종속적&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- &lt;span style=&quot;color: #000000;&quot;&gt;실체화 관계&lt;/span&gt; &lt;b&gt;&lt;span&gt;&amp;nbsp;(점&lt;/span&gt;선 + 빈 화살표 &lt;span style=&quot;color: #ee2323;&quot;&gt;-------------------&lt;b&gt;▷&lt;/b&gt;&lt;/span&gt;)&lt;/b&gt; &lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  Use Case Diagram&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;객체지향 초반기 분석 작업에 작성되는 사용자의 요구를 기능적 측면에서 기술할 때 사용하는 도구&lt;/b&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;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;Use Case Diagram 작성 단계 &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 액터식별&lt;/span&gt; (모든 사용자 역할과 상호작용하는 타 시스템을 식별, 정보를 주고받는 hw 및 지능형 장치를 식별)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Use Case 식별&lt;/span&gt; (액터가 요구하는 서비스와 정보를 식별, 액터가 시스템과 상호작용하는 행위를 식별)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 관계 정의&lt;/span&gt;(액터와 액터, 그리고 액터와 유스케이스의 관계분석을 정의)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Use Case 구조화&lt;/span&gt;(두 개의 상위 Use Case에 존재하는 공통 서비스를 추출)&lt;/b&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;&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  소프트웨어 아키텍처&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;개발 대상 시스템의 전반적인 구조를 체계적으로 설계하는 것&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;소프트웨어를 구성하는 컴포넌트들의 상호작용 및 관계, 각각의 특성을 기반으로 컴포넌트들이 상호 유기적으로 결합하는 소프트웨어의 여러 가지 원칙들의 집합&lt;/b&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt; &lt;b&gt;+ ISO/IEC 9126 모델  &lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;소프트웨어 품질 특성과 평가를 위한 국제 표준&lt;/b&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;u&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;lt;내외부 품질 &amp;amp; 사용 품질 특징 구분문제&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;내외부 품질: 기능성, 신뢰성, 사용성, 효율성, 유지보수성, 이식성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;사용 품질: 효과성, 생산성, 안정성, 만족도&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;외부지표: 사용자, 평가자, 시험자 및 개발자 이런 대상들을 기준으로 지표를 만들어내는 것&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;내부지표: 설계, 코딩 이런쪽에서의 표준 품질을 테스트&lt;/b&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;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Q. ISO/IEC 9126에 근거한 소프트웨어 품질목표 중 명시된 조건 하에서 소프트웨어 제품의 일정한 성능과 자원 소요량의 관계에 관한 속성, 즉 요구되는 기능을 수행하기 위해 필요한 자원의 소요 정도를 의미하는 것은?&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. Usability&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. Reliability&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. Functionality&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. Efficiency&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;정답: 4번&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;성능 및 자원 소요 -&amp;gt; 이는 효율성을 말하고있으므로 효율성 Efficiency.&lt;/b&gt;&lt;/span&gt;&lt;/p&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>정보처리기사</category>
      <category>2025 정보처리기사 필기</category>
      <category>정보처리기사</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/32</guid>
      <comments>https://basecoding.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-2025-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%ED%95%84%EA%B8%B0-1%EA%B3%BC%EB%AA%A9-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84-%EC%A0%95%EB%A6%AC2#entry32comment</comments>
      <pubDate>Thu, 6 Feb 2025 10:58:58 +0900</pubDate>
    </item>
    <item>
      <title>[정보처리기사] 2025 정보처리기사 필기 &amp;lt;1과목 소프트웨어 설계&amp;gt; 정리1</title>
      <link>https://basecoding.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-2025-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%ED%95%84%EA%B8%B0-1%EA%B3%BC%EB%AA%A9-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84-%EC%A0%95%EB%A6%AC1</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  sw의 특징&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 상품성&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 복잡성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 변경 가능성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 복제성&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt; 시스템의 개요와 기본 요소&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시스템?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시스템 기본 요소&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 입력, 처리, 출력, 제어, 피드백&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&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;313&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KSgZQ/btsL6AaaUwS/2cUO9pW5qKxXd0LuKRhrE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KSgZQ/btsL6AaaUwS/2cUO9pW5qKxXd0LuKRhrE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KSgZQ/btsL6AaaUwS/2cUO9pW5qKxXd0LuKRhrE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKSgZQ%2FbtsL6AaaUwS%2F2cUO9pW5qKxXd0LuKRhrE1%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;313&quot; height=&quot;200&quot; data-origin-width=&quot;313&quot; data-origin-height=&quot;200&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  소프트웨어 생명 주기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;소프트웨어 개발 방법론(sw 개발&amp;amp;유지보수 등 작업들을 수행하는 방법들을 체계적으로 정리해서 표준화 해놓은 일종의 방법론)의 바탕이 된다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;sw 개발을 하는 개발자에게 의뢰자가 ~~sw를 만들어주세요 의뢰를하면서 ~~이런이런 기능들이 있었으면 좋겠다라고 요구사항들을 말해줄텐데, 이 요구사항들을 분석하고 설계 후 -&amp;gt; 그 설계에 맞는 sw를 개발.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;개발하고나서 끝이 아니라, 개발된 그 sw가 항상 최신의 상태를 유지할 수 있게끔 운용,유지보수 등 관리(버그fix, update 등)를 해줘야할텐데 이러한 전체과정을 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;각 단계별로 나눈 것&lt;/span&gt;이 바로 소프트웨어 생명 주기.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 소프트웨어 생명 주기를 표현하는 형태를 보고 -&amp;gt; 소프트웨어 생명 주기 모형이라고도 하는데,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  소프트웨어 공학&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;소프트웨어의 위기(인건비, hw-sw간의 격차로 인한 요구사항 불만족, 유지보수 어려움)&lt;/b&gt;를 극복하기 위한 방안으로 연구된 학문. 경제적으로 신뢰도 높은 소프트웨어를 만들기 위한 방법, 도구와 절차들의 체계.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여러가지 방법론과 도구, 관리 기법들을 통하여 &lt;b&gt;소프트웨어의 품질과 생산성을 향상시킬 목적&lt;/b&gt;으로 함.&lt;/span&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;소프트웨어 공학의 기본 원칙&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 현대적인 프로그래밍 기술을 계속적으로 적용해야함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 신뢰성이 높아야함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 사용의 편리성, 유지보수성 높아야함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 지속적인 검증 시행 필요&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  폭포수 모형 (Waterfall Model)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;폭포에서 한번 떨어진 물은 거슬러 올라갈 수 없듯, sw개발도 이전 단계로 돌아갈 수 없다는 전제하에, 각 단계를 확실히 매듭짓고 그 결과를 철저히 검토하여 승인과정을 거친 후에 다음 단계로 진행하는 개발 방법론&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;애초에 되돌아갈 일 없게끔, 계획을 정확히해서 순서대로 쭉&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- sw공학에서 가장 오래되고 폭 넓게 사용된 전통적인 sw생명주기 모형. Boehm이 제시한 고전적 생명주기 모형&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- sw개발 과정의 한 단계가 끝나야 다음 단계로 넘어갈 수 있는 &lt;b&gt;선형 순차적 모형&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 중간에 변경된 요구사항을 중간에 적용 불가.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;한번 단계 넘어가면 이전 단계로 되돌아갈 수 없다&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;- 소규모 sw개발에 적합&lt;/span&gt;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;폭포수 모형 개발 순서&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfuH4S/btsL6LCLjHl/nfGzgGZkKw5l6voATEDcBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfuH4S/btsL6LCLjHl/nfGzgGZkKw5l6voATEDcBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfuH4S/btsL6LCLjHl/nfGzgGZkKw5l6voATEDcBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfuH4S%2FbtsL6LCLjHl%2FnfGzgGZkKw5l6voATEDcBk%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;905&quot; height=&quot;110&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;110&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 타당성 검토(이 sw를 개발할 필요가 있는지 없는지 검토)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 계획&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 요구 분석 (고객들의 요구 싹 분석)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. 설계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5. 구현(설계한 내용들을 기반으로 컴퓨터 코딩)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;6. 시험(구현한 코드가 잘 되나 안되나 검사)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;7. 유지보수(sw 개발 완료 후 버그fix, update 등)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  프로토타입 모형 (Prototype Model, 원형 모형)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;건물 짓기 전의 모델하우스. (건물 완공 전, 고객들에게 미리 보여줌. 고객 평가 후, 프로토타입 조정하여 개선)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;프로토타입 모형은, 사용자의 요구사항을 정확히 파악하기 위해, 실제 개발될 sw에 대한 견본품-시제품(prototype)을 만들어 최종 결과물을 예측하는 모형.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;sw의 개발완료 시점에 오류가 발견&amp;amp;한번 지나간 단계로 되돌아 가기 불가 -&amp;gt; 폭포수 모델의 단점&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이를 보완한게 프로토타입 모델. 이전 단계로 되돌아 갈 수 있음.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;프로토타입 모형 개발 순서&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;286&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFUzxn/btsL6cOupgR/mREBiWzALcKV7zSxTpg261/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFUzxn/btsL6cOupgR/mREBiWzALcKV7zSxTpg261/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFUzxn/btsL6cOupgR/mREBiWzALcKV7zSxTpg261/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFUzxn%2FbtsL6cOupgR%2FmREBiWzALcKV7zSxTpg261%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;286&quot; height=&quot;277&quot; data-origin-width=&quot;286&quot; data-origin-height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  나선형 모형 (Spiral Model, 점진적 모형)&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  &lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;위험 관리 == 나선형 모델&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&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: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Boehm이 제시하였으며, 반복적인 작업을 수행하는 점진적 생명주기 모형이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;폭포수 모형&amp;amp;프로토타입 모형의 장점 + 위험분석 기능을 추가한 모형.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 나선을 따라 돌듯이 여러 번의 sw개발 과정을 거쳐 점진적으로 완벽한 최종 sw를 개발하는 것으로 점진적 모형이라고도 함.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 점진적으로, 반복적으로 개발 과정이 나선으로 돌면서 반복되기에 - 누락되거나 추가된 요구사항을 첨가할 수 있고, 정밀하며, 유지보수 과정이 필요없음&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;소프트웨어를 개발하면서 발생할 수 있는 위험을 관리하고 최소화하는 것이 목적&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;나선형 모형 개발 순서&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;491&quot; data-origin-height=&quot;162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yB9cX/btsL7CSw8e4/oIRyv2KdBEbkQym2FK9WY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yB9cX/btsL7CSw8e4/oIRyv2KdBEbkQym2FK9WY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yB9cX/btsL7CSw8e4/oIRyv2KdBEbkQym2FK9WY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyB9cX%2FbtsL7CSw8e4%2FoIRyv2KdBEbkQym2FK9WY0%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;491&quot; height=&quot;162&quot; data-origin-width=&quot;491&quot; data-origin-height=&quot;162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 phase 를 거칠때마다 sw의 완성도 up. 각 phase 마다 누락된 부분이나 추가요구사항 추가되니.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 계획 수립&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 위험 분석 (이 계획의 위험요소들 분석해서 -&amp;gt; 추진할지말지 결정)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 개발 및 검증 (위험 분석이 끝난거를 가지고 프로토타입 개발)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. 고객 평가 ( 개발된 프로토타입을 고객이 평가)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1-2. 계획 수립 (고객이 맘에 안들거나 요구사항 추가시 -&amp;gt; 또 계획 수립)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2-2. 위험 분석&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  HIPO (Hierarchy Input Process Output)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;입력, 처리, 출력으로 구성되는 시스템 분석 및 설계와 시스템 문서화용 기법.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;가시적 도표&lt;/span&gt;, 총체적 다이어그램, 세부적 다이어그램으로 구성됨&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 가시적 도표로 되어있어, 보기쉽고 이해하기 쉬우며 유지보수가 쉽다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 폭포수 모형과 비슷하여, 하향식 sw개발을 위한 문서화 도구임. (폭포가 위에서 아래로 흐르니 하향식)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  V - 모델  &lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;폭포수 모형에 + &lt;span style=&quot;color: #ee2323;&quot;&gt;시스템 검증&lt;/span&gt;과 &lt;span style=&quot;color: #ee2323;&quot;&gt;테스트 작업&lt;/span&gt;을 강조한 모델. &lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;V모델은&amp;nbsp;&lt;/span&gt;각 개발 단계를 검증&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;하는데 초점을 둔다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉 폭포수 모델의 변형이다.&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 개발 단계의 작업을 확인하기 위해 각 단계별로 테스트 작업을 수행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 코드뿐만 아니라 요구사항과 설계 단계에서도 테스트할 수 있어야한다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 테스트 작업을 단계별로 구분하므로 책임이 명확&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;color: #ee2323; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;V - 모델과 테스트 단계 &lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4rpgV/btsL6W47Hrn/EM56CVXq3R3nE73iPqkM6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4rpgV/btsL6W47Hrn/EM56CVXq3R3nE73iPqkM6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4rpgV/btsL6W47Hrn/EM56CVXq3R3nE73iPqkM6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4rpgV%2FbtsL6W47Hrn%2FEM56CVXq3R3nE73iPqkM6k%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;518&quot; height=&quot;278&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  애자일 모형 (Agile Model) &lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;최신 sw개발 방법론인 애자일 개발 방법론.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;고객과의 소통에 초점을 맞춘 방법론을 통칭해서 애자일 모형이라고 부른다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;날렵한, 민첩한, 재빠른이란 사전적 의미에 맞게 , 정확하게 목표만 딱 표적해서 빠르게.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&quot;계획이고 뭐고간에 일단 제대로 된 sw만 만들어내면 돼&quot;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- sw를 빠르고 낭비없이 제작하기 이해 &lt;span style=&quot;color: #ee2323;&quot;&gt;고객과의 협업-소통에 초점&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- sw 개발 중 설계 변경에 신속히 대응하여 요구사항을 수용 가능. &lt;span style=&quot;color: #ee2323;&quot;&gt;변화에 빠른반응&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 절차와 도구보다 개인과 소통을 중요시하고 고객과의 피드백을 중요하게 생각&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 계획을 따르는 것보다 변경에 대한 응답이 더 중요&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 내가 목표하는대로 만들어졌느냐, 잘 실행되느냐에 가치를 둠. sw배포 시차를 최소화.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;- 스프린트(Sprint), 이터레이션(Iteration)이라고 불리는 짧은 개발주기를 반복하며, 반복되는 주기마다 만들어지는 결과물에 대한 고객의 평가와 요구를 적극 수용함&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;애자일 방법론의 종류&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 익스트림프로그래밍 (XP)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 스크럼 (SCRUM)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 칸반(Kanban)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 린 (Lean)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- DSDM (Dynamic System Development Method)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- FDD (기능중심개발)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  애자일 선언문&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;애자일 개발 철학이 담겨있는 4가지 핵심 가치 &amp;amp; 애자일 개발을 실무에 적용할 때 기준이 되는 12가지 실행 지침&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;애자일 개발 4가지 핵심 가치&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 프로세스와 도구보다는 개인과 상호작용에 더 가치를 둔다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 방대한 문서보다는 실행되는 SW에 더 가치를 둔다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 계약 협상보다는 고객과 협업에 더 가치를 둔다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. 계획을 따르기 보다는 변화에 반응하는 것에 더 가치를 둔다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt;애자일 개발 12가지 실행 지침&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p id=&quot;1-유용한-소프트웨어를-빠르고-지속적으로-제공하여-고객을-만족시킨다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 유용한 소프트웨어를 빠르고, 지속적으로 제공하여 고객을 만족시킨다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;2-개발-막바지라도-요구사항-변경을-적극-수용한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 개발 막바지라도 요구사항 변경을 적극 수용한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;3-몇-개월이-아닌-몇-주-단위로-실행되는-소프트웨어를-제공한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 몇 개월이 아닌 &lt;span style=&quot;color: #ee2323;&quot;&gt;몇 주 단위로&lt;/span&gt; 실행되는 소프트웨어를 제공한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;4-고객과-개발자가-프로젝트-기간에-함께-일한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. 고객과 개발자가 프로젝트 기간에 함께 일한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;5-개발에-대한-참여-의지가-확실한-사람들로-팀을-구성하고-필요한-개발환경과-지원을-제공하며-일을-잘-끝낼-수-있도록-신뢰한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5. 개발에 대한 참여 의지가 확실한 사람들로 팀을 구성하고, 필요한 개발환경과 지원을 제공하며, 일을 잘 끝낼 수 있도록 신뢰한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;6-같은-사무실에서-얼굴을-맞대고-의견을-나눈다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;6. 같은 사무실에서 얼굴을 맞대고 의견을 나눈다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;7-개발의-진척도를-확인하는-1차기준은-작동하는-소프트웨어이다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;7. 개발의 진척도를 확인하는 1차기준은 작동하는 소프트웨어이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;8-지속-가능한-개발을-장려하고-일정한-속도로-개발을-진행한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;8. 지속 가능한 개발을 장려하고 일정한 속도로 개발을 진행한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;9-기술적-우수성과-좋은-설계에-지속적인-관심을-기울이면-민첩성이-향상된다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;9. 기술적 우수성과 좋은 설계에 지속적인 관심을 기울이면 민첩성이 향상된다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;10-단순화를-추구한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;10. 단순화를 추구한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;11-최상의-아키텍처-명확한-요구사항-최상의-설계는-자기-스스로-일을-주도하는-조직적인-팀으로부터-나온다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;11. 최상의 아키텍처, 명확한 요구사항, 최상의 설계는 자기 스스로 일을 주도하는 조직적인 팀으로부터 나온다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;12-더-효과적인-팀이-될수-있는-방항을-정기적으로-깊이-고민하고-그에-따라-팀의-행동을-조정한다&quot; style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;12. 더 효과적인 팀이 될수 있는 방항을 정기적으로 깊이 고민하고 그에 따라 팀의 행동을 조정한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  폭포수 모형과 애자일의 비교&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 120px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구분&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;폭포수 모형&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애자일&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;새로운 요구사항 반영&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;어려움&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;지속적으로 반영&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;고객과의 의사소통&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;적음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;지속적임&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 40px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 40px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;마지막에 모든 기능을 테스트&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 40px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;반복되는 일정 주기가 끝날 때마다 테스트&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;개발 중심&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;계획, 문서(메뉴얼)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;고객&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 폭포수 모델은 선형 순차적이기에 한번 요구사항 변경되면 처음부터 다시 시작해야하기에 반영이 어렵다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  스크럼&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;앞서서 애자일 모형, 즉 애자일 방법론에 대해서 알아보았는데 여러 애자일 방법론 중의 하나인 스크럼을 알아보자.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;스크럼은, 요구사항 변경에 신속하게 대처할 수 있는 반복적이고 점진적인 소규모 팀원 간 활발한 소통과 협동심이 필요한 &lt;span style=&quot;color: #ee2323;&quot;&gt;팀 중심의 소프트웨어 개발 방법론&lt;/span&gt;이다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;애자일 모델 타입답게 소통을 중요시한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 팀원 스스로 팀을 구성해야한다. ( Self Organizing )&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 개발 작업에 관한 모든 것을 팀원 스스로 해결해야한다. ( Cross Functional )&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;SCRUM 팀 ( 제품 책임자 )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 개발 목표에 이해도가 높은 개발 의뢰자, 즉 사용자가 담당한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 제품 요구사항을 파악하여 기능 목록(Product Backlog)을 작성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- Backlog의 우선순위를 결정한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;SCRUM 팀 (&amp;nbsp;스크럼 마스터 )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 스크럼 팀의 마스터. 통제하지 않음. 스크럼 팀이 스크럼 잘 수행하도록 객관적인 시각에서 조언해주는 가이드역할.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 업무를 배분만하고 일은 강요하지 않으며 팀을 스스로 조직하고 관리하도록 지원.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 개발과정에서 발생된 장애 요소를 공론화하여 처리함.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;SCRUM 팀 (&amp;nbsp;스크럼 팀 )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 제품 책임자, 스크럼 마스터를 제외한 팀원이 해당. 팀원은 5~9명&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- 스프린트 결과물을 제품 책임자에게 시연&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;제품 백로그&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 제품개발에 필요한 모든 요구사항들을 우선순위에 따라 나열한 목록(제품 책임자가 관리)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 개발 과정에서 새롭게 도출되는 요구사항으로 인해 지속적으로 업데이트됨&lt;/b&gt;&lt;/span&gt;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;스프린트&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 실제 개발 작업을 진행하는 과정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 2~4주 정도의 기간내에서 진행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  XP (eXtreme Programming)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1999년 Kent Beck이 제안, 개발 단계 중 요구사항이 시시각각 변동이 심한 경우 적합한 방법론이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;수시로 발생하는 고객의 요구사항에 유연하게 대응하기 위해 고객의 참여와 개발 과정의 반복을 극대화하여 개발 생산성을 향상시키는 방법.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;짧고 반복적인 개발주기, 단순한설계, 고객의 적극적인 참여를 통해 소프트웨어를 빠르게 개발하는 것을 목적으로 함.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;- 요구에 맞는 양질의 sw를 신속하게 제공하는 것을 목표로한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- &lt;span style=&quot;color: #ee2323;&quot;&gt;애자일 방법론 타입답게, 고객의 참여와 개발 과정의 반복을 극대화하여 생산성을 향상하는 방법이다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;- 릴리즈 기간이 짧아서 - &amp;gt; 고객의 요구사항 반영에 대한 가시성을 높임. 릴리즈 테스트마다 고객이 직접 참여하여 잘되는지 확인&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- XP의 5가지 핵심 가치: &lt;u&gt;의사소통(Communication), 단순성(Simplicity), 용기(Courage), 존중, 피드백&lt;/u&gt;&lt;/span&gt;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;사용자 스토리&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 고객의 요구사항을 간단한 시나리오로 표현한 것&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;릴리즈 계획 수립&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 몇 개의 스토리가 적용되어, 부분적으로 기능이 완료된 제품을 제공하는 것&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;스파이크&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 요구사항의 신뢰성을 높이고 기술 문제에 대한 위험을 감소시키기위해 별도로 만드는 간단한 프로그램&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 처리할 문제 외의 다른 조건들은 모두 무시하고 작성&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이터레이션&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 하나의 릴리즈를 더 세분화한 단위&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 일반적으로 1~3주 정도의 기간으로 진행&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 이 기간 중에 새로운 유저 스토리가 작성되어, 진행중인 이터레이션 혹은 다음 이터레이션에 포함가능&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;승인 검사( 인수 테스트 )&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 릴리즈 단위의 개발이 구현되었을때 진행하는 테스트로, 사용자 스토리에 작성된 요구사항을 확인하여 고객이 직접 테스트한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 하나의 이터레이션 안에서 계획된 릴리즈 단위의 부분 완료 제품이 구현되면 구행하는 테스트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 테스트가 완료되면 다음 이터레이션 진행.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;소규모 릴리즈&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 릴리즈를 소규모로하여, 고객의 반응을 기능별로 확인 &amp;amp; 고객의 요구사항에 좀 더 유연한 대응&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  XP의 주요 실천 방법들&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. Pair Programming (짝 프로그래밍)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 다른 사람과 함께 프로그래밍 수행. 한명은 코딩, 한명은 검사&lt;/b&gt;&lt;/span&gt;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. Planning Game&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 게임처럼 선수와 규칙, 목표를 두고 기획에 임한다&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. Test Driven Develop-ment ( 테스트 주도 개발 )&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 실제 코드를 작성하기 전에 단위 테스트부터 작성 및 수행하며, 이를 기반으로 코드를 작성한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. Whole Team&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 개발 효율을 위해 고객을 프로젝트 팀원으로 상주시킨다. 고객도 전체 팀의 일원으로&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5. Continuous Integration ( 지속적인 통합 )&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 상시 빌드 및 배포를 할 수 있는 상태를 유지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt;6. Design improvement&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 기능 변경 없이 중복성/복잡성 제거, 커뮤니케이션 향상, 단순화, 유연성 등을 위한 재구성을 수행한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;7. Small Releases ( 소규모 릴리즈 )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 짧은 주기로 잦은 릴리즈를 함으로써 고객이 변경사항을 볼 수 있게 한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;8. Coding Standards&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 소스 코드 작성 포맷과 규칙즐을 표준화된 관례에 따라 작성하도록 한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;9. Collective Code Ownership ( 공동 코드 소유 )&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 시스템에 있는 소스 코드는 팀의 모든 프로그래머가 누구든지 언제라도 수정할 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;10. Simple Design&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 가능한 가장 간결한 디자인 상태 유지&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;11. &lt;/b&gt;&lt;b&gt;System Metaphor&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;- 최종적으로 개발되어야할 시스템의 구조를 기술한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;12. Sustainable Pace&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;- 일주일에 40시간 이상 작업 금지 , 2주 연속 오버타임을 금지한다.&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;익스트림 프로그래밍(XP)에 대한 설명으로 틀린 것은? &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;빠른 개발을 위해 테스트를 수행하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용자의 요구사항은 언제든지 변할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;고객과 직접 대면하며 요구사항을 이야기하기 위해 사용자 스토리를 활용가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기존의 방법론에 비해 실용성을 강조한 것이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;정답 = 1번.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;XR에서는, 릴리스마다 고객이 직접 인수테스트에 참여하여 요구사항이 잘 지켜졌는지 테스트한다.&amp;nbsp;&lt;/span&gt;&lt;/p&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 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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/B-F4JZtPx_Y?si=aZMtj-WePPTc_U4c&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/B-F4JZtPx_Y?si=aZMtj-WePPTc_U4c&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/JhKOsZuMDWs?si=0Gjg1VIn3xzSIpjo&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/JhKOsZuMDWs?si=0Gjg1VIn3xzSIpjo&lt;/a&gt;&lt;/p&gt;</description>
      <category>정보처리기사</category>
      <category>2025 정보처리기사</category>
      <category>정보처리기사 필기</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/31</guid>
      <comments>https://basecoding.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-2025-%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%ED%95%84%EA%B8%B0-1%EA%B3%BC%EB%AA%A9-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EC%84%A4%EA%B3%84-%EC%A0%95%EB%A6%AC1#entry31comment</comments>
      <pubDate>Wed, 5 Feb 2025 21:56:33 +0900</pubDate>
    </item>
    <item>
      <title>[라즈베리파이 setting] 2. 개발환경 setting (vim, VSCode, 가상환경)</title>
      <link>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-setting-2-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-setting-vim-VSCode-%EA%B0%80%EC%83%81%ED%99%98%EA%B2%BD</link>
      <description>&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;라즈베리파이 실습 및 개발과정에서 putty 및 리눅스 터미널을 통해 시스템을 조작하고, vi editor로 코딩을 하다보면 굉장히 번거롭고 가시성이 떨어진다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이를 위해 putty를 통해 원격 터미널로 작업하는 경우 &amp;amp; 리눅스 터미널로 작업하는 경우에는 vim 에디터로 업그레이드 하는 것을 권장한다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;물론 이보다 가장 편한 방법은, VSCode를 통한 원격 개발환경이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;vim 설치:&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;빔(vim)은 vi 편집기의 향상된 버전으로(vi improved), 기존 vi보다 향상된 기능을 가지고있다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;vim 설치는 아래 명령어를 통해 설치할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;sudo apt-get install vim&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;vim을 설치한 후, 일련의 설정을 해주어야 부가 기능들을 활성화 시킬 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래 명령어를 통해 홈 디렉터리에 vimrc 파일을 열어주고&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;vi ~/.vimrc&lt;/span&gt;&lt;/blockquote&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래와 같은 세팅 문구들을 추가해줌으로써 라인 번호 표시, 탭 간격 설정 등등 추가 기능들을 활성화 시킬 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set number &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set ai&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set si&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set cindent&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set shiftwidth=4&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set tabstop=4&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set ignorecase&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set hlsearch&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set expandtab&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set background=dark&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set nocompatible&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set fileencodings=utf-8,euc-kr&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set bs=indent,eol,start &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set history=1000&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; set ruler &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set nobackup &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set title &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set showmatch &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set nowrap &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;set wmnu&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;syntax on &lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 과정이 번거롭다면, 깃허브에 올라와있는 오픈소스 설정을 가져와서 간편하게 쓸 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래 명령어를 입력해주면 자동으로 vim 설정이 적용된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;git clone --depth=1 https://github.com/amix/vimrc.git ~/.vim_runtime &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;sh ~/.vim_runtime/install_awesome_vimrc.sh&lt;/span&gt;&lt;/blockquote&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;VSCode 로 원격 개발:&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;480&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn6yqv/btsL45ajAMr/m0GRBcCSUm56cjJxt491Nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn6yqv/btsL45ajAMr/m0GRBcCSUm56cjJxt491Nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn6yqv/btsL45ajAMr/m0GRBcCSUm56cjJxt491Nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn6yqv%2FbtsL45ajAMr%2Fm0GRBcCSUm56cjJxt491Nk%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;480&quot; height=&quot;240&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;240&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;어렵지 않은 방법으로 원격 호스트의 VSCode를 통해서 라즈베리파이에 원격 접속&amp;amp;개발이 가능하다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우선 원격 호스트를 windows 데스크톱이라면, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;데스크톱에 설치된 VSCode를 열고 좌측 사이드바의 Extension(확장) 패널을 열어준다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;마켓플레이스에서&amp;nbsp; Remote - SSH 확장 프로그램을 설치해준다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;F1 클릭후, ssh 검색 - SSH: Connect to Host 를 선택해준다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;그다음 + Add New SSH Host... 를 선택해준다음 라즈베리파이 user id(ex. pi)와 라즈베리파이의 사설ip주소를 pi@127.0.0.1 과 같은 형태로 입력해준다. (userid@IP주소)&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;그 다음 user\ssh\config를 선택해준다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;아까와같이 F1 - connect to host 를 들어가보면 방금 만들어둔 라즈베리파이 ssh 원격접속 즐겨찾기가 라즈베리파이의 ip주소형태로 추가된 것을 확인가능하다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;해당 즐겨찾기를 선택해주면&amp;nbsp; VSCode 새로운 창으로 라즈베리파이 원격접속창이 열리면서 선택창이 나타는데, 이때 Linux로 선택해주고 os 설치시 설정해두었던 패스워드를 입력해주면 정상적으로 ssh 원격접속이 성공한다. (ssh 프로토콜은 보안을 중시하기에, 매번 비밀번호를 입력해주어야함은 putty와 동일하다)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 VSCode로 라즈베리파이에 원격접속 + 개발환경 구축이 완료되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;VSCode의 터미널창(Ctrl + `) 에서도 putty처럼 리눅스 터미널로 라즈베리파이 조작이 가능하며, 좌측의 사이드바를 통해 간편하게 라즈베리파이 파일시스템을 설정할 수도 있다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;물론 VSCode의 확장 프로그램도 로컬과 동일하게 원격에 설치가능하나, 이 경우 백그라운드에서 node 프로세스로 VSCode 확장프로그램들이 상시 구동되므로 무거운 확장이나 많은 확장프로그램은 메모리 부하를 일으키니 free -h 또는 top 명령어로 메모리 상태에 따라 적절히 추가 - 미사용 설정해주어야한다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &amp;nbsp;&lt;/span&gt;&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;파이썬 가상환경: 서로 다른 버전의 파이썬 패키지 관리&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우리가 여러 프로젝트를 진행하거나 이 프로그램 저 프로그램 작성하다보면 각 프로젝트 및 프로그램마다 요구되는 파이썬 패키지 의존성들이 각기 다른 경우가 있을 것이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이를 위해 파이썬에서는 가상환경 기법을 지원해준다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가상환경이란, 파이썬을 실행할 수 있는 완벽히 독립된 실행 환경을 의미하며, 시스템에는 여러 개의 가상환경을 만들어두어서 개발자는 이중에서 하나의 가상환경을 선택하여 해당 환경기반에서 프로그램을 작성&amp;amp;실행이 가능해진다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 라즈베리파이 시스템 내에서 가상환경A,B 2개의 가상환경을 만들어두었다고 가정하자.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가상환경 A는 파이썬 3.4버전 + numpy 패키지 1.10.12버전이 설치되어있고,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가상환경 B에는 파이썬 3.9.2버전 + numpy 패키지 1.25.2버전이 설치되어있다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;만약 내가 현재 파이썬 3.9.2 버전 기반의 프로그램 제작이 필요하다면, 가상환경B를 활성화시키고 이 가상환경에서 프로그램을 개발하면 될 것이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이렇듯 가상환경 설치 &amp;amp; 활성화 &amp;amp; 비활성화 &amp;amp; 제거 방법만 알고있으면 원하는 파이썬 환경에서 개발을 선택적으로 독립적으로 해나갈 수 있다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;가상환경 설치:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;python -m venv 가상환경이름&lt;/span&gt;&lt;/blockquote&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;u&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;가상환경은 홈 디렉터리에 디렉터리로 생성된다&lt;/span&gt;&lt;/u&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;&lt;b&gt;가상환경 활성화:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가상환경을 사용하기 위해서는 설치된 여러 가상환경 중에서 하나를 활성화해야한다. 특정 가상환경을 활성화하면 그때부터 python 명령들은 활성화된 가상환경 디렉터리의 lib 디렉터리에 설치된 패키지들만 사용하게된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가상환경을 활성화시키려면 아래 명령어로 가상환경의 bin 디렉터리 내부의 activate 쉘 스크립트 프로그램을 실행시켜주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;source ~/가상환경이름/bin/activate&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가상환경이 활성화되면 가상환경 이름이 쉘 프롬프트 앞에 출력되어, 사용자가 현재 어떤 가상환경을 사용하고있는지, 어떤 가상환경속에서 개발중인지를 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;가상환경 비활성화:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;deactivate&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;&lt;b&gt;가상환경 삭제:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;rm -r -f ~/가상환경이름&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;해당 가상환경이 활성화된 상태에서 (myenv) pip 명령을 실행하면, 활성화된 해당 가상환경에서 패키지를 관리하게된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 아무 가상환경도 활성화되지않은 상태에서의 pip명령 실행은, 라즈베리파이 운영체제가 설치될때 user/bin 경로에 같이 설치된 python3 시스템 파이썬 영역에서 패키지를 관리한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, pip install 명령어를 사용하여 필요한 패키지를 설치하곤할때, 해당 가상환경 내에서만 파이썬 패키지가 설치되기때문에 이는 시스템 전체에 영향을 주지않는 독립적인 관리체계가 구축된 것이다.&amp;nbsp;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이로써, 파이썬 가상환경을 통해 우리는&amp;nbsp;각 프로젝트마다 필요한 패키지와 의존성을 독립적으로 관리하여, 프로젝트별 독립적인 개발환경을 구성할 수 있게된다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;라즈베리파이 메모리 관리:&lt;/span&gt;&lt;/h2&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 라즈베리파이의 메인메모리 상태를 확인하려면 아래 free -h 명령어로 터미널에서 간략하게 확인가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;free -h&amp;nbsp;&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;다음은 free -h 명령어의 출력 예시이다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #181d28; color: #ffffff; text-align: start;&quot;&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;               총계         사용        여분      공유    버퍼/캐시    가용
메모리:        1.8Gi       882Mi       743Mi        28Mi       318Mi       964Mi
스  왑:        511Mi          0B       511Mi&lt;/code&gt;&lt;/pre&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 data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 필자가 사용중인 라즈베리파이는 4b 모델 2GB 램 용량이기에 기본적인 os 및 시스템 파일을 제외한 전체 메모리 총량은 1.8GB이고&lt;b&gt;&amp;lt;총계&amp;gt;&lt;/b&gt;,&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 882MB 가량 프로세스가 구동중이며&amp;lt;사용&amp;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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 사용되고있지않은 여유 메모리 공간은 743MB&lt;b&gt;&amp;lt;여분&amp;gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;여러 프로세스 간에 공유되는 메모리 공간인 공유메모리(일반적으로 작음. 28MB)&lt;/span&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;b&gt;공유&amp;gt;&lt;/b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt; ,&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: left;&quot;&gt;약 318MB 크기의 메모리 공간이 &lt;/span&gt;&lt;span style=&quot;color: #404040; text-align: left;&quot;&gt;파일 시스템 캐시, 디스크 I/O 작업 등을 위해 할당중이며&lt;b&gt;&amp;lt;버퍼/캐시&amp;gt;&lt;/b&gt;, &lt;/span&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;span style=&quot;color: #404040; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;&lt;b&gt;여유 메모리(743MB)&lt;/b&gt;와&amp;nbsp;&lt;/span&gt;&lt;b&gt;버퍼/캐시 메모리(318MB)&lt;/b&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;&amp;nbsp;중에서 시스템이 즉시 사용할 수 있는 메모리를 합산한 크기인 가용메모리는 약 964MB임을 확인할 수 있다&lt;b&gt;&amp;lt;가용&amp;gt;&lt;/b&gt;.&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #404040; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;즉, 가용메모리가 현재 라즈베리파이의 메모리에서 사용가능한 메모리 크기를 일컫는다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;available (가용):&lt;/b&gt; 새로운 애플리케이션을 실행하는 데 사용할 수 있는 메모리 크기의 추정치.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;여분메모리 전체 + buff/cache 중 즉시 회수 가능한 부분 &lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #404040; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;&amp;nbsp;free -h 외에도 top 명령어를 통해 현재 라즈베리파이의 시스템 정보들을 확인하여 부하를 측정할 수 있는데, 이때 현재 라즈베리파이 메모리의 가용메모리 크기가 부족하다면 기기부하는 물론 성능 저하까지 발생하기에 적절한 메모리 관리가 필요하다.&amp;nbsp;&lt;/span&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;span style=&quot;color: #404040; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;특히, 입출력 속도 향상을 위해 가용되는 버퍼/캐시 메모리 공간이 &lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;페이지 hit rate가 낮은경우에도&lt;/span&gt; 많은 메모리공간을 사용하고 있어서 가용메모리가 부족한 상황이 종종발생한다.&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #404040; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;페이지 히트율 30% 미만&lt;/b&gt;&amp;nbsp;&amp;rarr; 캐시 효율 극히 낮음.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;가용 메모리 100MiB 미만&lt;/b&gt;&amp;nbsp;&amp;rarr; 시스템 지연 발생.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;버퍼/캐시 1GiB 이상&lt;/b&gt;&amp;nbsp;&amp;rarr; 메모리 낭비.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;만약 위의 조건과 같은 상황이라면&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #404040; text-align: left; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #404040; text-align: start;&quot;&gt;이때는 버퍼/캐시를 사용자가 수동으로 비워주어서 메모리공간을 쾌적하게 만들어줄 필요가 있다.&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;sudo sync; sudo sysctl -w vm.drop_caches=3&lt;/span&gt;&lt;/blockquote&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 명령어는 &lt;b&gt;페이지 캐시, 디렉토리 및 inode 캐시 모두 비우기&lt;/b&gt;를 수행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IOT/Raspberry Pi</category>
      <category>라즈베리파이 vscode</category>
      <category>라즈베리파이 개발환경</category>
      <category>라즈베리파이 메모리</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/30</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-setting-2-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-setting-vim-VSCode-%EA%B0%80%EC%83%81%ED%99%98%EA%B2%BD#entry30comment</comments>
      <pubDate>Tue, 4 Feb 2025 05:01:51 +0900</pubDate>
    </item>
    <item>
      <title>[라즈베리파이 setting] 1. OS setting</title>
      <link>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-setting-1-OS-setting</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;라즈베리파이 os 구축부터 전체적인 개발환경 setting까지 정리해보고자 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Raspberry Pi Imager 다운로드 &amp;amp; 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 노트북이나 데스크톱에, 라즈베리파이 운영체제 설치 프로그램인 Imager를 다운로드받고 실행해준다.&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;실행시 아래와 같은 프로그램이 나타나는데, 이때 디바이스 섹션에서는 현재 보유한 라즈베리파이 기종( 본 프로젝트에서는 라즈베리파이4B 2gb 모델이다)을 선택해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;677&quot; data-origin-height=&quot;482&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oZLZN/btsL6USDnvl/RbUNFJevRC4NxHJfP1YVlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oZLZN/btsL6USDnvl/RbUNFJevRC4NxHJfP1YVlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oZLZN/btsL6USDnvl/RbUNFJevRC4NxHJfP1YVlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoZLZN%2FbtsL6USDnvl%2FRbUNFJevRC4NxHJfP1YVlK%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;677&quot; height=&quot;482&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;482&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;br /&gt;그 다음 섹션인 운영체제의 섹션의 경우, 선택한 기종에 맞는 추천된 os들이 리스트로 나타나는데, 그 중에서 최 상단에 위치한 Bookworm 64-bit os 를 선택해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하단 이미지에 보이듯이 Recommended로 자동 추천해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;680&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCF36i/btsL40mFmFx/CTiTsb1wkDX6htuujffdjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCF36i/btsL40mFmFx/CTiTsb1wkDX6htuujffdjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCF36i/btsL40mFmFx/CTiTsb1wkDX6htuujffdjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCF36i%2FbtsL40mFmFx%2FCTiTsb1wkDX6htuujffdjK%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;680&quot; height=&quot;480&quot; data-origin-width=&quot;680&quot; data-origin-height=&quot;480&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;blockquote data-ke-style=&quot;style2&quot;&gt;이때 os를 선택하는 부분에 있어서 중요한 것은, 라즈베리파이 최신 os인 bookworm의 경우 라즈베리파이가 자동으로 잡아주는 무선 네트워크가 1개로 한정되어진다. 물론, 한정된 환경에서 개발을 하거나 GUI를 직접 컨트롤 가능한 환경이라면 최신os를 설치해주면된다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;하지만, 집-학교 등등 여러 환경에서 유동적으로 원격 실습 및 개발을 해야하는 경우에는 이러한 제약은 큰 불편을 주기에&amp;nbsp; other 섹션에서 Legacy 64-bit OS를 설치해주면 된다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Legacy 64-bit OS의 경우엔 이전 구버젼들과 동일하게 sd카드의 root 위치에 wpa_supplicant_conf 파일을 만들어두고, 접속할 여러 무선 네트워크들을 작성해주면된다. 이러면 라즈베리파이가 부팅시 해당 파일 내에 작성해둔 무선 네트워크 중 우선순위에 따라 자동으로 접속한다.&lt;br /&gt;&lt;br /&gt;본 게시물에서는 bookworm 64-bit 설치를 기준으로 작성하기에, 별도의&amp;nbsp;wpa_supplicant_conf 파일을 작성하지 않는다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후, 저장소 섹션에서 데스크톱에 꽂아둔 sd카드를 저장소로 선택한다음 다음을 눌러주면 os 커스터마이징 단계로 넘어가는데, 1. 일반 섹션 2. 서비스 섹션 3. 옵션 섹션으로 나뉜다.&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;1. 일반 섹션&lt;/b&gt;에서는 hostname 설정의 경우 본인이 원하는 hostname (ex. pi, raspberry, jun, kim ....) 으로 입력해주면 된다. 이때 설정해둔 hostname은, 라즈베리파이와 같은 로컬 네트워크에 연결된 다른 컴퓨터 호스트에서 ping 명령으로 라즈베리파이의 ip주소를 알아내는데 사용된다.&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;는 라즈베리파이에 로그인시 입력한 정보이므로 외워둬야하며,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무선 LAN 설정&lt;/b&gt;의 경우 라즈베리파이가 부팅시 자동으로 연결할 무선 네트워크의 SSID와 비밀번호를 입력해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 라즈베라파이&amp;amp;집 공유기 조합의 경우 집 공유기의 ssid 를, 라즈베리파이&amp;amp;노트북 핫스팟 조합의 경우 노트북 핫스팟의 ssid를 입력해주면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무선 LAN 국가는 영국(GB)로 선택해준다.&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;의 경우, 시간대는 Asia/Seoul, 키보드 레이아웃은 us로 설정해둔다. 이후 GUI를 통해 변경 가능하다.&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. 서비스 섹션&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;에서는 SSH사용을 허용해준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH는 ssh 프로토콜로, 동일 네트워크 내에서 타 호스트에 원격 접속시 사용하며, 추후 putty와 같은 원격 접속 sw를 이용하여 라즈베리파이와 동일한 로컬 네트워크에 속한 기기를 이용하여 라즈베리파이를 헤드리스 환경에서 원격으로 제어하기위해 꼭 필요한 옵션이니 꼭 체크해준다.&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 라즈베리파이에 SD카드 삽입 &amp;amp; 부팅&lt;/h3&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번 과정을통해 sd카드에 os를 설치한 후, 라즈베라피이의 sd카드 슬롯에 꽂아준다음 어뎁터를 연결하여 부팅해주면 sd카드 메모리가 라즈베리파이 메모리에 로드되면서 os 부팅이 일어난다.&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 네트워크 구성 &amp;amp; 라즈베리파이에 원격 접속&lt;/h3&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;amp; 원격 접속 파트인데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 이 라즈베리파이를 컨트롤 하는 방법으로는 &lt;b&gt;1. 직접 데스크톱처럼 사용&lt;/b&gt;(라즈베리파이에 모니터,마우스 등등 연결하여 일반 pc처럼 사용) 하는 방법과, &lt;b&gt;2. 원격 헤드리스로 사용&lt;/b&gt;(주변 hw연결없이 원격에서 네트워크로 접속하여 컨트롤)하는 방법으로 나뉜다.&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;이 게시물에서는 무선 네트워크망을 이용한 원격 헤드리스 방법으로 라즈베리파이 개발 환경을 구축하고자 한다.&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;헤드리스 라즈베리파이 구축에 있어서도 여러가지 방법이 존재하는데, 결국 공통된 점은 로컬 네트워크에 대한 이해 및 구축이다. 어떻게 라즈베리파이와 이 라즈베리파이를 원격으로 컨트롤하기 위한 호스트 간에 로컬 네트워크를 구축하면 좋을까?&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;1. 가장 간단한 방법으로는 노트북 핫스팟을 이용하는 방법이다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노트북을 어떠한 무선 공유기에 연결한다음 =&amp;gt; 모바일 핫스팟을 on 해주고 =&amp;gt; 라즈베리파이가 이 핫스팟에 연결한다면 라즈베리파이와 노트북은 하나의 로컬 네트워크를 형성하게된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 노트북 핫스팟의 장점은, 노트북의 모바일 핫스팟창에 이 핫스팟에 연결된 모든 호스트들의 사설ip주소들을 보여준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중에서는 노트북 핫스팟으로부터 사설IP를 할당받은 라즈베라파이의 사설IP도 있을테니 이 IP주소를 putty에 입력하여 라즈베리파이에 원격으로 접속할 수 있게된다.&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;이제 노트북 핫스팟이 구축한 로컬 네트워크 내의 호스트가 ssh프로토콜을 통해 원격으로 라즈베리파이에 접속할 수 있게된다.&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;450&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQxrGO/btsL4HVhUvW/WJkhVPmZXRfOcmD3tcTlcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQxrGO/btsL4HVhUvW/WJkhVPmZXRfOcmD3tcTlcK/img.png&quot; data-alt=&quot;라즈베리파이의 IP주소를 입력하고 ssh프로토콜로 원격 컨트롤&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQxrGO/btsL4HVhUvW/WJkhVPmZXRfOcmD3tcTlcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQxrGO%2FbtsL4HVhUvW%2FWJkhVPmZXRfOcmD3tcTlcK%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;450&quot; height=&quot;434&quot; data-origin-width=&quot;450&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;라즈베리파이의 IP주소를 입력하고 ssh프로토콜로 원격 컨트롤&lt;/figcaption&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 시스템 업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라즈베리파이에 putty를 통해 원격 접속한 후, 이제 라즈베리파이를 원격에서 컨트롤 할 수 있게되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 먼저 해야할 부분은 이제 막 os를 설치했으니 시스템 업데이트를 해줘야한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;sudo apt-get update&amp;nbsp; // 버전 업그레이드 가능한 패키지 목록 최신화.&lt;br /&gt;&lt;br /&gt;sudo apt-get upgrade // 패키지 목록에 있는대로 패키지 업그레이드&lt;/blockquote&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. 한글 설치&amp;nbsp;&lt;/h3&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;blockquote data-ke-style=&quot;style3&quot;&gt;sudo apt-get install ibus ibus-hangul fonts-unfonts-core&lt;/blockquote&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;p data-ke-size=&quot;size16&quot;&gt;아래 명령어를 통해 os 시스템 설정 화면으로 이동한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;sudo raspi-config&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이동 후, Localosation Options - &amp;gt; Locale -&amp;gt; &quot;ko_KR.UTF-8 UTF-8&quot; 칸을 스페이스바를 통해 선택해준다음 Tab 키를 눌러 &amp;lt;ok&amp;gt;로 이동후 엔터키를 눌러 확정해준다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 설치할 로케일 목록들이 뜰텐데, 이 중에서 아까 선택해준 한글 로케일을 선택하고 &amp;lt;ok&amp;gt;버튼을 선택하여 finish 해준다음 라즈베리파이를 재부팅해주어 적용시켜주면 끝이다.&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. 라즈베리파이 종료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라즈베리파이 실습 종료 후 라즈베리파이를 끄고싶을때는, 어댑터 파워선을 바로 뽑으면 편하겠지만 이 작업이 반복되다보면 어댑터 슬롯 고장 및 납땜 풀림, 설치된 응용프로그램 훼손, os 훼손 등 부작용들이 발생할 위험이있다.&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;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;sudo halt&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어가 입력되면 putty 터미널 연결이 끊어지고 + os는 SD카드에 저장되어야할 정보를 저장하는 등 마무리 작업 진행 후 CPU활동을 중지시킨다.&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;</description>
      <category>IOT/Raspberry Pi</category>
      <category>라즈베리파이</category>
      <category>라즈베리파이 os</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/29</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-setting-1-OS-setting#entry29comment</comments>
      <pubDate>Tue, 4 Feb 2025 00:35:25 +0900</pubDate>
    </item>
    <item>
      <title>NumPy 라이브러리: Chapter3 (useful Functions &amp;amp; matplotlib)</title>
      <link>https://basecoding.tistory.com/entry/NumPy-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Chapter3-useful-Functions-matplotlib</link>
      <description>&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt;  행렬 병합/연결&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;concatenate&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&amp;nbsp;&lt;/span&gt;: 행렬에 행 또는 열 추가하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;NumPy에서 행렬에 행 또는 열을 추가하고싶다면 numpy.concatenate(A,B) 와 같이&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;concatenate 메서드&lt;/b&gt;&lt;/span&gt;를 사용하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;기존행렬에 재료행렬을 병합함으로써 기존 행렬에 행이나 열을 추가하는 효과를 얻을 수 있는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;C = numpy.concatenate( (A,&amp;nbsp; B), axis = n )&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이때 concatenate의 첫번째 매개변수는 (병합 대상 행렬, 병합시킬 행렬)로 이루어진 튜플이고.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;두번째 매개변수는 axis로, 병합의 축을 설정하는 매개변수이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 병합의 경우 axis값은 0 or 1로, &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;axis=0&lt;/span&gt; 인 경우 &lt;span style=&quot;color: #ee2323;&quot;&gt;병합의 축이 행으로 설정&lt;/span&gt;되어 - &amp;gt; 행 방향으로 연결, 즉 행렬의 하단에 행렬이 연결되어진다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;axis=1&lt;/span&gt; 인 경우 &lt;span style=&quot;color: #ee2323;&quot;&gt;병합의 축이 열로 설정&lt;/span&gt;되어 - &amp;gt; 열 방향으로 연결, 즉 행렬의 우측에 행렬이 연결되어진다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래는 행렬 연결을 통한 행 추가를 보여주는 예시이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;824&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxZpRl/btsL10s6xN1/hyQzue3ewa4MweZHMVt8k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxZpRl/btsL10s6xN1/hyQzue3ewa4MweZHMVt8k0/img.png&quot; data-alt=&quot;concatenate 메서드를 이용한 행렬 연결 -&amp;amp;gt; 행 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxZpRl/btsL10s6xN1/hyQzue3ewa4MweZHMVt8k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxZpRl%2FbtsL10s6xN1%2FhyQzue3ewa4MweZHMVt8k0%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;824&quot; height=&quot;456&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;concatenate 메서드를 이용한 행렬 연결 -&amp;gt; 행 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;concatenate 예제 코드는 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738048395148&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np
# concatenate메서드로 행렬에 열과 행 추가하기

A = np.array([[10, 20, 30], [40, 50, 60]])
print(A.shape) # (2, 3)

# A matrix에 행(row)으로 추가될 row_add 행렬 정의.
# (3,) 벡터를 -&amp;gt; (1,3) matrix 로 형변환. 가로 벡터
# 벡터는 1차원이기때문에 2차원인 (1,3) matrix로 형변환하여야 함. 
row_add = np.array([70, 80, 90]).reshape(1, 3)

# A matrix에 열(column)으로 추가될 coloumn_add 행렬 정의.
# (2,) 벡터를 -&amp;gt; (2,1) matrix 로 형변환. 세로 벡터
column_add = np.array([1000, 2000]).reshape(2, 1)


#axis는 축을 뜻하는 매개변수로, 
#axis 값에따라서 행렬을 추가하는 방향 축이 달라짐.
# axis=0 : 행을 축으로 연결. 즉, 행이 추가되는 방향인 하단에 추가됨.
# axis=1 : 열을 축으로 연결. 즉, 열이 추가되는 방향인 우측에 추가됨.

# A matrix에 row_add 행렬을 추가한 matrix B 생성. axis값은 0이므로 행을 축으로하여 추가하였으니. 행으로 추가됨.
B = np.concatenate((A, row_add), axis=0)
print(B)

# A matrix에 column_add 행렬을 추가한 matrix C 생성. axis값은 1이므로 열을 축으로하여 추가하였으니. 열로 추가됨.
C = np.concatenate((A, column_add), axis=1)
print(C)
print(C.shape) # (2, 4) 형상으로 변경되었음을 확인할 수 있음. 열이 추가된 것!&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;concatenate는 머신러닝 개발에서 자주쓰이는 기법 중 하나이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;머신러닝의 회귀(regression)코드 구현시, 가중치(weight)와 바이어스(bias)를 별도의 행렬로 구분하지않고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;하나의 행렬로 취급하기위해서 =&amp;gt; &lt;b&gt;행과 열을 추가해주는 기능을 가진 바로 이 행렬 연결, concatenate 메서드를 사용한다.&amp;nbsp;&lt;/b&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;&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;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;&lt;b&gt;NumPy&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;loadtxt&lt;/span&gt;:&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #000000;&quot;&gt;&lt;b&gt;, 와 같은 분리자로 구분된 파일에서 데이터를 읽어들이기 위한 메서드이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; 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: #000000;&quot;&gt;&lt;b&gt;아래의 예시는 , 로 구분되어있는 파일의 데이터들을 읽어들이는 구문이다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;numpy.loadtxt(&quot;파일이름&quot; , separator=',')&lt;/blockquote&gt;
&lt;p style=&quot;text-align: start;&quot; 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: #000000;&quot;&gt;&lt;b&gt;이때, loadtxt 메서드는 행렬을 return 하기때문에 리턴값을 인덱싱 또는 슬라이싱을 이용하여 데이터를 분리해볼 수 있다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; 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: #000000;&quot;&gt;&lt;b&gt;이는 머신러닝 코드에서 입력데이터와 정답데이터를 분리하는데 유용하게 사용된다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738234571835&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np

# loadtxt function
# seperator로 구분된 파일에서 데이터를 읽어오는 함수
loaded_data = np.loadtxt('./data-01.csv', delimiter=',', dtype=np.float32)
 
x_data = loaded_data[ : , 0:-1]
t_data = loaded_data[:, [-1]]

# 데이터 차원 및 shape 확인
print(&quot;x_data.ndim = &quot;, x_data.ndim, &quot;, x_data.shape = &quot;, x_data.shape)
print(&quot;t_data.ndim = &quot;, t_data.ndim, &quot;, t_data.shape = &quot;, t_data.shape)&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 난수생성&lt;/b&gt;&lt;b&gt; (&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;random.rand() &lt;/span&gt;):&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #000000;&quot;&gt;rand 메서드는 0 과 1 사이의 임의의 랜덤 실수값을 반환해주는 함수이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #000000;&quot;&gt;(3) 처럼 매개변수값을 하나만 입력시 원소 3개짜리 벡터로 반환해주고, (1,3)처럼 매개변수값을 2개 입력하면 1행 3열짜리 행렬을 반환해준다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각 벡터와 행렬의 원소값들은 랜덤 실수값이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #000000;&quot;&gt;rand 메서드는 가중치나 바이어스 등을 임의의 값으로 설정할때 주로 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738234869914&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np

# 0~1 사이의 난수 생성.

random_number1 = np.random.rand(3)
random_number2 = np.random.rand(1,3)
random_number3 = np.random.rand(3,1)


print(&quot;random_number1 ==&quot;, random_number1, &quot;, random_number1.shape ==&quot;, random_number1.shape)
print(&quot;random_number2 ==&quot;, random_number2, &quot;, random_number2.shape ==&quot;, random_number2.shape)
print(&quot;random_number3 ==&quot;, random_number3, &quot;, random_number3.shape ==&quot;, random_number3.shape)&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;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-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt; max/min &amp;amp; argmax/argmin&lt;/span&gt;&amp;nbsp;: &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;배열 내의 최소-최대 값 구하기 &amp;amp; 해당 인덱스&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span&gt;벡터 및 행렬과 같은 다중 원소들을 포함하는 컨테이너 자료구조 내에서 최대-최소값 &amp;amp; 해당 값의 인덱스를 쉽게 구해주는 numpy 메서드들이다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;벡터의 경우, 해당 벡터의 요소들 중에서 최대최소값을 도출해주지만, 행렬의 경우엔 추가로 axis 매개변수를 통해서 열 기준으로 최대-최소값을 얻어낼 것인지 행 기준으로 얻어낼 것인지를 명시해주어야한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;벡터에서의 최대/최소값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738047291016&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import numpy as np

# 벡터의 최대값, 최소값, 최대값의 인덱스, 최소값의 인덱스
X = np.array([2,4,6,8])

print(f&quot;np.max(X) == {np.max(X)}&quot;)
print(&quot;np.min(X) == {}&quot;.format(np.min(X)))
print(&quot;np.argmax(X) ==&quot;, np.argmax(X))
print(&quot;np.argmin(X) ==&quot;, np.argmin(X))&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;행렬&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에서의 최대/최소값&lt;/span&gt;&lt;/b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;행렬에서는 반환값이 벡터이다. 행 기준 - 열 기준으로 최대최소값을 벡터구조로 나열하여 반환해주기 때문이다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738047291017&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;# 행렬의 최대값, 최소값, 최대값의 인덱스, 최소값의 인덱스
# 행렬의 경우, axis를 지정하여 행 또는 열 단위로 계산한다. 
# axis=0: 열을 축으로 계산, axis=1: 행을 축으로 계산
X = np.array([[2,4,6], [1,2,3], [0,5,8]])

print(&quot;np.max(X) ==&quot;, np.max(X, axis=0)) # 각 열의 최대값을 모아서 벡터로 반환
print(&quot;np.min(X) ==&quot;, np.min(X, axis=0)) # 각 열의 최소값을 모아서 벡터로 반환
print(&quot;np.max(X) ==&quot;, np.max(X, axis=1)) # 각 행의 최대값을 모아서 벡터로 반환
print(&quot;np.min(X) ==&quot;, np.min(X, axis=1)) # 각 행의 최소값을 모아서 벡터로 반환

print(&quot;np.argmax(X) ==&quot;, np.argmax(X, axis=0)) # 각 열의 최대값의 인덱스를 모아서 벡터로 반환
print(&quot;np.argmin(X) ==&quot;, np.argmin(X, axis=0)) # 각 열의 최소값의 인덱스를 모아서 벡터로 반환
print(&quot;np.argmax(X) ==&quot;, np.argmax(X, axis=1)) # 각 행의 최대값의 인덱스를 모아서 벡터로 반환
print(&quot;np.argmin(X) ==&quot;, np.argmin(X, axis=1)) # 각 행의 최소값의 인덱스를 모아서 벡터로 반환&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&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;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;ones &amp;amp; zeros &lt;/span&gt;:&lt;/b&gt;&lt;b&gt; 배열 생성 &amp;amp; 모든 요소 0 or 1로 초기화&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #000000;&quot;&gt;&lt;b&gt;주어진 형상의 배열(벡터 및 행렬)을 생성하고 해당 배열을 모든 요소들을 0 또는 1의 값으로 초기화해주는 간편한 메서드이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;b&gt;ones &amp;amp; zeros 는 앞서 기술한 concatenate 메서드와 함께 자주 사용되곤한다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738047291020&quot; class=&quot;python&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import numpy as np
# numpy.ones()와 numpy.zeros() 함수는 각각 모든 원소가 1 또는 0인 배열을 생성한다.
# 메서드에 작성한 형상의 배열을 생성하고, ones 인지 zeros인지에 따라 모든 원소를 1 또는 0으로 초기화한다.
A = np.ones([3,3])
print(&quot;A.shape ==&quot;, A.shape, &quot;, A ==&quot;, A)

B = np.zeros([3,2])
print(&quot;B.shape ==&quot;, B.shape, &quot;, B ==&quot;, B)&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;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style5&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;matplotlib &lt;span style=&quot;color: #000000;&quot;&gt;라이브러리&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;:&lt;/b&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp; 데이터 시각화 (그래프)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;머신러닝 코드를 구현하는 실무에서는 실제 코드를 구현하기 전에, 입력 데이터의 분포와 모양을 먼저 그래프로 그려보고, 데이터의 특성과 분포를 파악 한 후에, 해당 데이터에 어떤 알고리즘이 가장 적합한지를 결정하는 추세이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이렇듯, 데이터의 분포와 데이터의 시각화를 위해서 가장 많이 사용되는 라이브러리가 바로 이 matplotlib 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&amp;nbsp;matplotlib 라이브러리의 많은 그래프 유형중에서 일반적으로 line plot 과 scatter plot 을 많이 사용한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; &lt;b&gt;✅ scatter plot (산점도 그래프)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738245534887&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import matplotlib.pyplot as plt
import numpy as np

x_data = np.random.rand(100)
y_data = np.random.rand(100)

plt.title(&quot;Scatter plot&quot;) # 그래프 제목
plt.grid() # xy축 격자무늬.그리드 표시

# 그래프의 종류, 색상, 마커를 설정하여 출력
# 그래프의 종류: scatter(산점도). 다른 종류로는 plot(선그래프), bar(막대그래프) 등이 있다.
# x축, y축 데이터: x_data, y_data
# 색상: color='b'는 파란색, color='r'은 빨간색, color='g'는 초록색
# 데이터 마커: marker='o'는 원형, marker='x'는 x표시, marker='*'는 별표시
plt.scatter(x_data, y_data, color='b', marker='o')
plt.show() # 그래프 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&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;578&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpi55i/btsL31kjXZS/cnviTYroCHv5Q3PvUUtNH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpi55i/btsL31kjXZS/cnviTYroCHv5Q3PvUUtNH1/img.png&quot; data-alt=&quot;산점도 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpi55i/btsL31kjXZS/cnviTYroCHv5Q3PvUUtNH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdpi55i%2FbtsL31kjXZS%2FcnviTYroCHv5Q3PvUUtNH1%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;578&quot; height=&quot;452&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;452&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;/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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;✅ line plot (선형 그래프)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738248095157&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import matplotlib.pyplot as plt
import numpy as np

# list comprehension을 사용하여 x_data, y_data를 생성
# list comprehension은 for문 + 표현식을 이용하여 리스트를 생성하는 방법
x_data = [ x for x in range(-5,5)]
y_data = [ y*y for y in range(-5,5)]

plt.title(&quot;line plot&quot;)
plt.grid()
# 선형 그래프의 경우 plot()메서드를 사용하면 된다.
plt.plot(x_data, y_data, color='b', marker='o')
plt.show()&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;439&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kVYfP/btsL3OSTtEI/KMMVwc6E0OZBoZtRVdZk6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kVYfP/btsL3OSTtEI/KMMVwc6E0OZBoZtRVdZk6K/img.png&quot; data-alt=&quot;선형 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kVYfP/btsL3OSTtEI/KMMVwc6E0OZBoZtRVdZk6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkVYfP%2FbtsL3OSTtEI%2FKMMVwc6E0OZBoZtRVdZk6K%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;563&quot; height=&quot;439&quot; data-origin-width=&quot;563&quot; data-origin-height=&quot;439&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;선형 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt; &lt;b&gt;✅ line plot2 (선형 그래프2)&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738248513473&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import matplotlib.pyplot as plt

x_data = [ -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
y_data = [ -8, -13, -0, 3, 6, -1, -5, -7, 1, 8, 7, 13, 17]

plt.title(&quot;line plot2&quot;)
plt.grid()
plt.plot(x_data, y_data, color='r', marker='x')
plt.show()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;566&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZLdEz/btsL2bhzCfi/uGzMwldgZDIO9n66MIIPWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZLdEz/btsL2bhzCfi/uGzMwldgZDIO9n66MIIPWK/img.png&quot; data-alt=&quot;선형 그래프2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZLdEz/btsL2bhzCfi/uGzMwldgZDIO9n66MIIPWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZLdEz%2FbtsL2bhzCfi%2FuGzMwldgZDIO9n66MIIPWK%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;566&quot; height=&quot;436&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;선형 그래프2&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI/Python</category>
      <category>matplotlib</category>
      <category>numpy</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/28</guid>
      <comments>https://basecoding.tistory.com/entry/NumPy-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Chapter3-useful-Functions-matplotlib#entry28comment</comments>
      <pubDate>Thu, 30 Jan 2025 23:50:56 +0900</pubDate>
    </item>
    <item>
      <title>NumPy 라이브러리: Chapter2 (dot product, broadcast, indexing/slicing, iterator)</title>
      <link>https://basecoding.tistory.com/entry/NumPy-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Chapter2-dot-product-broadcast-indexingslicing-iterator</link>
      <description>&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  행렬 곱 &lt;span style=&quot;color: #ee2323;&quot;&gt;dot product&lt;/span&gt;&lt;span style=&quot;color: #666666;&quot;&gt; &lt;/span&gt;:&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;NumPy에서 행렬 A,B간의 행렬 곱을 수행하려면 numpy.dot(A,B) 와 같이 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;dot 메서드&lt;/b&gt;&lt;/span&gt;를 사용하면 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;C = numpy.dot(A,B)&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이때 dot product의 조건으로, 앞의 행렬인 A 행렬의 열 벡터와 뒤의 행렬인 B 행렬의 행 벡터가 같아야만 행렬 곱이 가능하다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc9af; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, 앞부분의 열과 뒷부분의 행의 크기가 동일해야한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;7:1-9:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;7:1-7:67&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 A:&lt;/b&gt; shape이 (m, n) 인 행렬. 즉, m개의 행과 n개의 열을 가진 행렬&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;8:1-9:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 B:&lt;/b&gt; shape이 (p, q) 인 행렬. 즉, p개의 행과 q개의 열을 가진 행렬&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;8:1-9:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt;A x B 행렬 곱 결과인 행렬 C&lt;/b&gt;:&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;shape이 (m, q) 인 행렬이 연산 결과로 도출된다.&lt;/span&gt;&lt;/u&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&amp;nbsp; C = (A의 행 개수, B의 열 개수)&lt;/span&gt;&lt;u&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;10:1-10:24&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 곱셈 A @ B 가 가능하려면:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;12:1-13:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;12:1-13:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;A의 열의 개수(n)와 B의 행의 개수(p)가 같아야 한다.&lt;/b&gt;&lt;/span&gt; 즉, n = p 이어야 dot product 연산이 가능하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;만약 두 행렬 간에, 좌측 행렬의 열의 크기와 우측 행렬의 행의 크기가 불일치하다면 reshape 처리 또는 전치행렬(transpose) 등을 사용하여 형 변환을 한 후에야 행렬 곱을 실행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;아래는 행렬 A 와 B 간의 dot product 연산 과정을 보여주는 코드이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737798464895&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np

# dot product: 행렬 간의 곱셈 연산.

# 행렬 곱셈의 조건:
# 행렬 A의 shape이 (m, n) 이고, 행렬 B의 shape이 (n, p) 일 때,
# A의 열 벡터(열의 개수(n))와 B의 행 벡터(행의 개수(n))가 반드시 일치해야 함.
# 곱셈 결과, 행렬 C는 shape이 (m, p) 가 됨.

A = np.array([ [1,2,3],[4,5,6] ])
B = np.array([ [-1, -2],[-3, -4], [-5, -6] ])

# (2 x 3) dot product (3 x 2) = (2 x 2) 행렬.
C = np.dot(A,B)

# matrix A, B 형상 출력 =&amp;gt; (2,3), (3,2)
print(&quot;A.shape ==&quot;, A.shape, &quot;B.shape ==&quot;, B.shape)
print(&quot;C.shape ==&quot;, C.shape)
print(C)&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;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;523&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXK59B/btsL0M28VVB/8m2b5PNa3nB2jZKWcLbXN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXK59B/btsL0M28VVB/8m2b5PNa3nB2jZKWcLbXN1/img.png&quot; data-alt=&quot;A x B dot product 연산흐름&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXK59B/btsL0M28VVB/8m2b5PNa3nB2jZKWcLbXN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXK59B%2FbtsL0M28VVB%2F8m2b5PNa3nB2jZKWcLbXN1%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;523&quot; height=&quot;423&quot; data-origin-width=&quot;523&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;A x B dot product 연산흐름&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 곱이 머신러닝에서 중요한 이유는 무엇일까? :&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;기존, 행렬의 사칙연산 ( + , - , * , / )의 경우 - &amp;gt; 피연산자인 모든 행렬의 원소 개수가 같아야만 계산이 가능하다는 한계가 있다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;예를 들어, 첫번째 피연산자 행렬이 ( 3 x 2 ) 형상이라면 그 다음 피연산자 행렬들 역시 사칙연산을 위해 ( 3 x 2 ) 형상이어야 한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, 행렬의 사칙연산을 위해서는 연산에 사용되는 모든 행렬의 행과 열의 크기가 동일해야만 가능하다는 한계가 있다는 것이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이 한계를 벗어나기위해 dot product, 즉 행렬 곱을 사용하는 것이다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 곱은, 모든 행렬의 원소 개수가 같아야만 계산할 수 있다는 사칙연산의 한계조건을 벗어나,&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;단지 앞의 행렬의 열 부분과 뒤의 행렬의 행 부분의 크기만 동일하게 맞추어주면 행렬 곱셈 연산을 가능하게 해준다.&amp;nbsp;&lt;/b&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;&amp;nbsp;&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;442&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kxsSb/btsL1D5F432/ScsaiHYiXkdhW0cixoTCuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kxsSb/btsL1D5F432/ScsaiHYiXkdhW0cixoTCuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kxsSb/btsL1D5F432/ScsaiHYiXkdhW0cixoTCuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkxsSb%2FbtsL1D5F432%2FScsaiHYiXkdhW0cixoTCuk%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;442&quot; height=&quot;376&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ex) 입력 행렬 형상이 64 x 64 이고, 행렬곱 연산 결과 행렬의 형상이 64 x 10 이라면, &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 중간의 피연산자 행렬들로는 dot product를 만족시키는 어떠한 형상의 행렬이라도 올 수 있다는 것이다.&amp;nbsp;&lt;br /&gt;&lt;b&gt;(마지막 특성 값 행렬의 열의 크기만 10으로 맞춰주면된다)&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 것이 numpy의 dot product를 사용하는 이유이다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;만약 행렬 곱을 사용하지 않고 산술연산을 한다면, 입력 행렬의 64 x 64 크기와 동일한 크기를 가지는 &lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;64 x 64&lt;/span&gt; 특성 값 행렬들만을 사용해야 하기 때문에 다양한 특성을 갖는 필터 개발이 불가능해질 것이다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 행렬 곱 조건을 만족하는 다양한 크기의 행렬을 연속으로 만들고&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 행렬 곱을 연속으로 계산하면서&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 다양한 결과값을 원하는 형식으로 출력할 수 있기 때문에 머신러닝과 이미지 프로세싱 분야에서 자주 사용되는 것이다.&amp;nbsp;&lt;/b&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;&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-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  &lt;/b&gt;&lt;b&gt;NumPy&amp;nbsp;&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;broadcast &lt;/span&gt;: 크기가 다른 행렬 간의 사칙연산 지원&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;앞서 언급했듯이, 행렬의 사칙연산은 기본적으로 &lt;b&gt;두 개의 &lt;/b&gt;피연산자 행렬의 크기가 동일한 경우에만 수행할 수 있다는 한계가 있다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;그래서 행렬 곱셈 연산의 경우엔, 이 한계를 깨고자 numpy의 dot 메서드를 통한 dot product 연산을 소개했었다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;더불어 numpy 에서는 크기가 다른 두 행렬간에도 사칙연산 ( +, -, *, / ) 을 할 수 있도록 확장시켜주는 기능인 &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;브로드캐스트 (broadcast)&lt;/span&gt; 를 지원해준다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;브로드캐스트는 차원이 작은 쪽이, 차원이 큰 쪽에 맞추어 행 단위로 반복적으로 크기를 확장시켜주는 기능이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;차원으로 구분해보면, 일반 리터럴 단일 숫자 값인 &lt;b&gt;스칼라&lt;/b&gt;는 &lt;b&gt;0차원&lt;/b&gt;이고(숫자 1,2,3 ...)&amp;nbsp;&amp;nbsp; &lt;u&gt;shape: ()&amp;nbsp; ndim: 0 &lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 순서가 있는 숫자들의 리스트이자 1차원 배열인 &lt;b&gt;벡터&lt;/b&gt;는 &lt;b&gt;1차원&lt;/b&gt;이며, &lt;u&gt;shape: (n,) (n은 요소의 개수) ndim: 1 &lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;행과 열로 이루어진 숫자들의 집합인 &lt;b&gt;행렬&lt;/b&gt;은 &lt;b&gt;2차원&lt;/b&gt;이다. &lt;u&gt;shape: (m, n) (m은 행의 개수, n은 열의 개수) ndim: 2&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;크기가 다른 행렬간에 or 이 서로다른 차원간에도 사칙연산이 가능하도록 해주는 기능이 바로 브로드캐스트인 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;10:1-10:18&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;브로드캐스팅의 작동 방식:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;12:1-14:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;12:1-12:76&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;차원 맞추기:&lt;/b&gt; 두 배열의 차원 수가 다르면, 더 작은 차원의 배열 shape의 앞쪽에 1을 추가하여 차원 수를 맞춤.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;13:1-14:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;크기 확장:&lt;/b&gt; 각 차원에 대해, 크기가 1인 차원을 다른 배열의 해당 차원의 크기와 동일하게 확장. (반복 복사)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:7&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 브로드케스팅 예시:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:7&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;◾&lt;/b&gt;&amp;nbsp;(3, 3) 행렬 * 스칼라&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot; data-sourcepos=&quot;11:1-14:0&quot;&gt;
&lt;li data-sourcepos=&quot;11:1-11:33&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;스칼라 -&amp;gt; (1, 1) (차원 및 크기 확장) &lt;b&gt;0차원 - &amp;gt; 1차원으로 확장&lt;/b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;12:1-12:31&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(1, 1) -&amp;gt; (3, 3) (크기 확장)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;13:1-14:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(3, 3) * (3, 3) (요소별 곱셈)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-sourcepos=&quot;15:1-15:7&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;◾ (4, 3) 행렬 - (3,) 벡터&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;5:1-8:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;5:1-5:30&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(3,) -&amp;gt; (1, 3) (차원 맞추기) 1차원 - &amp;gt; 2차원으로 확장&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;6:1-6:31&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(1, 3) -&amp;gt; (4, 3) (크기 확장)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;7:1-8:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(4, 3) - (4, 3) (요소별 뺄셈)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt;◾&lt;/b&gt; &amp;nbsp;(3, 1) 행렬 + (1, 3) 행렬&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;27:1-30:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;27:1-27:31&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(3, 1) -&amp;gt; (3, 3) (열 크기 확장)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;28:1-28:31&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(1, 3) -&amp;gt; (3, 3) (행 크기 확장)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;29:1-30:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;(3, 3) + (3, 3) (요소별 덧셈)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;pre id=&quot;code_1737815167557&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np

A = np.array([ [1,2], [3,4] ]) # 2 x 2 matrix
B = 5 # scalar

C = A + B # matrix + scalar =&amp;gt; scalar broadcasting. 

# 0차원인 스칼라 B가 2 x 2 matrix로 차원 확장 broadcasting 되어 2 x 2 matrix + 2 x 2 matrix 연산이 수행됨.

print(C)

X = np.array( [ [1,2], [3,4] ] ) # 2 x 2 matrix
Y = np.array( [4,5] ) # 1 x 2 matrix

Z = X + Y # 2 x 2 matrix + 1 x 2 matrix =&amp;gt; 1 x 2 matrix가 2 x 2 matrix로 행 크기 확장 broadcasting 되어 2 x 2 matrix + 2 x 2 matrix 연산이 수행됨.

print(Z)&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;p data-ke-size=&quot;size16&quot;&gt;&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;441&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3WmXD/btsL1tChGKZ/4CndfTSTvLO30kz4MQrrPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3WmXD/btsL1tChGKZ/4CndfTSTvLO30kz4MQrrPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3WmXD/btsL1tChGKZ/4CndfTSTvLO30kz4MQrrPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3WmXD%2FbtsL1tChGKZ%2F4CndfTSTvLO30kz4MQrrPK%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;441&quot; height=&quot;546&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;546&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;여기서 주의할 점은, 브로드캐스트는 행렬 곱 연산에서는 일어나지않고, 오직 사칙연산에서만 자동으로 발생하는 기능임을 명시해야한다.&lt;/b&gt;&lt;/span&gt;&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;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;전치행렬 (&lt;span style=&quot;color: #ee2323;&quot;&gt;transposed matrix&lt;/span&gt;): 행렬의 행과 열을 change&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;transpose: 전치하다. 뒤바꾸다 (행과 열을)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;전치행렬이란, 원본 행렬의 열은 행으로, 행은 열로 바꾸어진 행렬을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;원본행렬을 A라고 한다면 이에 대한 전치행렬은 A.T 즉 &lt;u&gt;T 연산자&lt;/u&gt;로 구할 수 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;T 연산자는 transpose 즉, 전치를 수행해주는 연산자이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ex) 해당 행렬의 1번 행은 1번 열로 바꾸고, 2번 행은 2번 열로, ... 변경되어진 행렬을 전치행렬이라고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;421&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt6XfN/btsL007RvhJ/IzY3qOoXTqTosKdGHT9AR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt6XfN/btsL007RvhJ/IzY3qOoXTqTosKdGHT9AR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt6XfN/btsL007RvhJ/IzY3qOoXTqTosKdGHT9AR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt6XfN%2FbtsL007RvhJ%2FIzY3qOoXTqTosKdGHT9AR0%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;421&quot; height=&quot;571&quot; data-origin-width=&quot;421&quot; data-origin-height=&quot;571&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8; color: #000000;&quot;&gt;&lt;b&gt; 여기서 !&amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;만약 벡터를 전치행렬로 만들려고하는 경우, 벡터는 행렬이 아니기에 전치행렬을 만들 수 없다.&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;벡터는 열과 행으로 구분되지않는 1차원 배열이기 때문에, 2차원 배열인 행렬로 형 변환해주는 과정이 필요하다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;행과 열을 갖는 행렬 형태로 변환해주어야, 행과 열이 뒤바뀌는 전치행렬이 도출되기 때문이다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;벡터 - &amp;gt; reshape -&amp;gt; 행렬 - &amp;gt; transpose - &amp;gt; 전치행렬!&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;아래의 코드는 행렬에 대한 transpose &amp;amp; 벡터에 대한 transpose 코드 예시이다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737819977733&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np

A = np.array([ [1,2],[3,4],[5,6] ]) # 3 x 2 matrix
B = A.T # A의 전치행렬, 2 x 3 matrix

print(&quot;A.shape ==&quot;, A.shape, &quot;B.shape ==&quot;, B.shape)
print(A) # 3 x 2 matrix 출력
print(B) # 전치된 전치행렬인 2 x 3 matrix 출력
print()
#############################################

# vector 전치행렬

# vector는 행렬이 아닌 1차원 배열형태이기에 전치행렬이 정의되지 않지만,
# 행이나 열이 하나인 행렬로 형변환(reshape)하여 전치행렬을 구할 수 있음.

C = np.array([1,2,3,4,5]) # 5개의 원소를 가지는 vector
D = C.T # C는 vector이기 때문에 C에 대한 전치행렬 정의가 불가능.
# 따라서 C를 (5,1) 형상의 행렬로 형변환 한 후에 전치행렬을 구해야 함.

E = C.reshape(1,5) # (5,) 형상의 벡터 C를 1 x 5 형상의 matrix로 형변환.

# (1 x 5) 1행 5열 형상의 행렬 E를 transpose =&amp;gt; 
# 전치행렬 F 도출. F = (5 x 1) 5행 1열 형상의 matrix.
F = E.T 

print(&quot;C.shape ==&quot;, C.shape, &quot;D.shape ==&quot;, D.shape)
print(&quot;E.shape ==&quot;, E.shape, &quot;F.shape ==&quot;, F.shape)
print(F) # 전치행렬 F 출력&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;p style=&quot;color: #333333; text-align: start;&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;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;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 행렬 &lt;span style=&quot;color: #ee2323;&quot;&gt;indexing / slicing&lt;/span&gt; : 행렬의 원소 접근&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;행렬의 원소값을 얻기위해서는, python 기본 자료형인 리스트 에서처럼 인덱싱 / 슬라이싱을 사용하면된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ &lt;span style=&quot;color: #000000;&quot;&gt;벡터 - &amp;gt; 행렬로 형 변환&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737824972947&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 요소 6개 짜리 vector 생성 후 2 x 3 matrix로 형변환
A = np.array([ 10, 20, 30, 40, 50, 60 ]).reshape(3,2)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; [ 예제 1 ] 인덱싱&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt; A[0,0] 또는 A[0][0]은 1행 1열, A[2,1] 또는 A[2][1]은 3행 2열에 해당하는 요소를 가리킨다. &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이처럼 행렬에서는 콤마를 기준으로 왼쪽은 행, 오른쪽은 열을 나타낸다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;A[n, m]은 n+1번째 행, m+1번째 열에 있는 요소를 가리킴.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;리스트 및 배열에 접근할때와 마찬가지로 인덱스는 0부터 시작하기에 실제 가리키는 요소의 위치는 인덱스 +1 이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737825414666&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 예제 1: indexing
print(&quot;A[0,0] ==&quot;, A[0,0], &quot;, A[0][0] ==&quot;, A[0][0]) # 행렬A의 1행 1열에 해당하는 요소인 10 출력
print(&quot;A[2,1] ==&quot;, A[2,1], &quot;, A[2][1] ==&quot;, A[2][1]) # 행렬A의 3행 2열에 해당하는 요소인 60 출력&lt;/code&gt;&lt;/pre&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;style8&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;[ 예제 2 ] 슬라이싱&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;A[ 0 : -1 , 1 : 2 ] 는 =&amp;gt; 인덱스 0에 해당하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;1행 ~&lt;/span&gt; 인덱스 -1 -1 = -2 에 해당하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;2행까지&lt;/span&gt;,&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;그리고 인덱스 1에 해당하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;2열 ~&lt;/span&gt; 인덱스 2 - 1 = 1에 해당하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;2열까지&lt;/span&gt;의 데이터들을 슬라이싱한 행렬을 반환한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737826430683&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 예제 2: slicing
print(&quot;A[0:-1, 1:2] ==&quot;, A[0:-1, 1:2]) # 행렬A의 1행부터 마지막 행 -1 즉 2행까지, 2열부터 3열까지를 slicing하여 출력

# 행렬 A의 1~2행 &amp;amp; 2열까지의 모든 데이터인 [[20] 
#					 [40]] 출력.

# 슬라이싱 결과 2행 1열 형상의 2x1 matrix가 도출됨.&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;✅&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp;[ 예제 3 ] 슬라이싱&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;리스트 슬라이싱에서와 마찬가지로, 콜론만 있는경우는 모든 범위를 일컫는다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;A[ : , 0] 은 모든 행의 1열을 가리킨다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;A[ : , : ] 은 모든 행의 모든 열을 가리킨다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737827441090&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 예제 3: slicing
print(&quot;A[:,0] ==&quot;, A[:,0]) # 행렬A의 모든 행의 1열 요소 출력
print(&quot;A[:,:] ==&quot;, A[:,:]) # 행렬A의 모든 행과 열의 요소 출력&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;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt; 행렬&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;iterator&lt;/span&gt;&amp;nbsp;:&lt;/b&gt;&lt;b&gt; 행렬의 모든 원소 순차적 접근&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인덱싱과 슬라이싱은 행렬의 특정 범위의 원소들에 접근하기위해 사용했었다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이외에, &lt;span style=&quot;color: #ee2323;&quot;&gt;행렬의 모든 원소를, 즉 처음부터 끝까지를 access하고자하는 경우에는 iterator 를 사용하는 것이 효율적이다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;numpy iterator는 C++, java 등등의 iterator 처럼 next() 메서드를 통해 리스트형 자료구조 내의 요소값들을 처음부터 끝까지 순차적으로 읽어 들이는 방법을 제공해준다.&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;iterator는 행 단위로 데이터를 접근한다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, 해당 행의 끝 요소에 접근하고나서 다음 접근은 - &amp;gt; 다음 행의 첫번째 요소에 대한 접근이다.&amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ex) 1행의 모든 데이터를 접근한 후에 2행의 데이터에 접근 ...&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&amp;nbsp;아래의 코드는 2x4 행렬의 모든 원소를 iterator를 이용하여 순차적으로 접근하는 예시 코드이다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737832107451&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np

A = np.array([[10,20,30,40],[50,60,70,80]]) # 2 x 4 matrix

# 행렬 A의 iterator 생성
it = np.nditer(A, flags=['multi_index'], op_flags=['readwrite'])

# iterator를 이용하여 행렬 A의 모든 원소를 순치적으로 접근.
# it.finished : iterator가 끝에 도달했는지 여부를 반환
while not it.finished:
    # multi_index : iterator가 현재 가리키는 원소의 인덱스를 반환
    idx = it.multi_index

    print(&quot;current value =&amp;gt; &quot;, A[idx])
    
    # iternext() : iterator가 다음 원소를 가리키도록 이동
    it.iternext()&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;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI/Python</category>
      <category>dot product</category>
      <category>numpy</category>
      <category>전치행렬</category>
      <category>행렬 곱</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/27</guid>
      <comments>https://basecoding.tistory.com/entry/NumPy-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Chapter2-dot-product-broadcast-indexingslicing-iterator#entry27comment</comments>
      <pubDate>Sun, 26 Jan 2025 02:53:13 +0900</pubDate>
    </item>
    <item>
      <title>NumPy 라이브러리: Chapter1 (array, vector, matrix, reshape)</title>
      <link>https://basecoding.tistory.com/entry/NumPy-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Chapter1</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;넘파이? 왜 사용할까&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p 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 Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;넘파이 라이브러리는, 파이썬을 이용하여 머신러닝/딥러닝을 개발할 경우에 매우 유용하여 필수적으로 사용되는 라이브러리&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행렬 연산에서의 numpy vs list:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 특히나 넘파이를 이용한 &lt;b&gt;행렬(matrix) 연산&lt;/b&gt;을 하는 경우, 넘파이는 외형적으로는 리스트 자료구조와 비슷해보인다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;둘의 차이는 무엇일까?&amp;nbsp;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;아래처럼 2차원 리스트 A와 B로 행렬을 선언한 다음 이 둘을 더하면 행렬 연산인듯 싶지만, 이는 그저 리스트 간의 연산일 뿐이다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737723392229&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A = [ [1,0], [0,1] ]
B = [ [1,1], [1,1] ]

A + B #이는 행렬 연산이 아닌 그저 리스트 연산!&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 두 2차원 리스트 간의 연산 결과는 우리가 기대한 행렬 덧셈 연산 결과가 아니라 &lt;b&gt;[ [1,0], [0,1], [1,1], [1,1] ]&lt;/b&gt; 로, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그저 &lt;b&gt;A리스트에 B리스트 내부의 요소들이 더해진 append 된 결과일 뿐임을 알 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 numpy의 경우를 보자.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;넘파이에서는 array 자료구조를 이용하여 행렬을 선언하는데, 이는 C나 JAVA 등등에서의 배열과같다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737724184966&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# numpy matrix, 직관적이다. 

A = numpy.array( [ [1,0] , [0,1] ] )
B = numpy.array( [ [1,1] , [1,1] ] )

A + B #행렬 연산&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;넘파이 행렬 연산의 결과는&lt;b&gt;( [2,1], [1,2] )&lt;/b&gt; 로, 우리가 알고있는 행렬 연산의 결과임을 확인해볼 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;691&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ho7BG/btsL2nN98Q8/APhuFcaKsZ8egYWtIBiJaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ho7BG/btsL2nN98Q8/APhuFcaKsZ8egYWtIBiJaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ho7BG/btsL2nN98Q8/APhuFcaKsZ8egYWtIBiJaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHo7BG%2FbtsL2nN98Q8%2FAPhuFcaKsZ8egYWtIBiJaK%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;691&quot; height=&quot;530&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;530&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;머신러닝에서 이미지 속의 숫자, 사람, 동물 등을 인식하기위해서는 이미지 데이터를 행렬로 변환하는 작업이 매우 빈번한데,&amp;nbsp;&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이러한 행렬을 표현하고 연산하기위해서는 위처럼 numpy의 array 자료구조로 행렬을 선언하고, array 연산을 통해서 행렬을 연산하는 것이 무엇보다 중요하다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;물론 행렬을 나타내기 위해서 리스트를 사용할 수도 있지만, 리스트를 사용한 행렬 연산은 직관적이지 않을뿐더러 연산 오류 가능성도 높기에, &lt;span style=&quot;color: #ee2323;&quot;&gt;행렬 연산을 위해서는 numpy 사용이 필수적이다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;라이브러리 설치 &amp;amp; 임포트:&lt;/b&gt;&lt;/span&gt;&lt;/h2&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;넘파이 라이브러리를 사용하기위해선 아래 구문을 입력하여 설치해주어야 사용가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;pip install numpy&amp;nbsp;&lt;/b&gt; &amp;nbsp; // pip는 파이썬으로 작성된 패키지(라이브러리)를 설치하고 관리하는 패키지 관리 시스템.&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그 후, 설치한 넘파이 라이브러리를 현재 파이썬 파일에서 사용하려면 import 해와서 사용해야한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; NumPy 라이브러리는 프로그램 실행 시 &lt;b&gt;바로 메모리에 로드되는 것이 아니라&lt;/b&gt;, import numpy 문이 실행될 때 &lt;b&gt;필요에 따라 메모리에 로드되기 때문이다.&amp;nbsp; &lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;import numpy 문이 실행되는 순간, 파이썬 인터프리터는 NumPy 라이브러리 파일을 찾아서 메모리에 로드하고, NumPy에서 정의된 함수, 클래스, 변수 등을 사용할 수 있도록 준비한다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;메모리 효율성을 위한 것이다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 만약 모든 라이브러리를 프로그램 실행 시점에 무조건 메모리에 로드한다면, 메모리 공간이 부족해기에, import 문을 사용하여 필요한 라이브러리만 선택적으로 로드하도록 되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;import numpy as np&lt;/b&gt;&amp;nbsp; &amp;nbsp;// NumPy 라이브러리를 가져온 후 np라는 별칭으로 편하게 사용. 가장 일반적. =&amp;gt; &lt;b&gt;np.exp()&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;from numpy import exp&lt;br /&gt;&lt;/b&gt;&amp;nbsp; // NumPy 라이브러리에서 진짜 필요한 특정 함수 및 변수만 import 하여 메모리 더욱 효율적으로.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp; // numpy.exp 처럼 라이브러리명 기술할 필요없이 바로 &lt;b&gt;exp()&lt;/b&gt; 처럼 사용가능.&lt;br /&gt;&amp;nbsp; // from 을 사용하여 가져오면 =&amp;gt; 라이브러리의 namespace를 기술할 필요없이 api(함수)를 바로 사용가능.&lt;/span&gt;&lt;/blockquote&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;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;NumPy&amp;nbsp; &lt;span style=&quot;color: #ee2323;&quot;&gt;vector 벡터&lt;span style=&quot;color: #666666;&quot;&gt;( &lt;u&gt;1차원 배열 &lt;/u&gt;)&lt;/span&gt;&lt;/span&gt;:&lt;/b&gt;&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;벡터는 넘파이 라이브러리의 &lt;b&gt;array&lt;/b&gt; 메서드를 사용하여 선언할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;즉, &lt;b&gt;벡터는 배열&lt;/b&gt;이다. array 자료구조.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt; NumPy에서 array 메서드를 사용하여 벡터나 행렬을 생성할 때, &lt;b&gt;array 메서드 안에 리스트(list)를 전달하여 생성한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;A = np.array( [ 1, 2, 3 ] )&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;B = np.array( [ 4, 5, 6 ] )&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;위의 A 와 B는 리스트와 비슷해보이지만, 넘파이의 array 자료구조로 생성한 &lt;span style=&quot;color: #ee2323;&quot;&gt;1차원 배열 벡터&lt;/span&gt;이다.&amp;nbsp;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;머신러닝 코드에서 연산을 하기위해 vector, matrix 등의 &lt;b&gt;형상&lt;/b&gt;(shape)과 &lt;b&gt;차원&lt;/b&gt;(dimension)을 확인하고 - 필요에따라 변경해주어야하는데,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때 형상과 차원을 확인하기위해, 넘파이의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;shape (형상)&lt;/b&gt; &lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;ndim (차원) &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;속성을 &lt;/span&gt;&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;b&gt; shape 속성은 배열의 전체적인 모양 즉 형상 나타내는 튜플을 반환&lt;/b&gt;&lt;/u&gt;&lt;b&gt; &lt;/b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;(ex. 2행 3열인 행렬이면 (2,3) 튜플.. )&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;u&gt;ndim 속성은 해당 배열이 몇 차원인지를 반환&lt;/u&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;벡터 A와 B는 행과 열을 가지지않는 1차원 배열 벡터이기때문에&lt;b&gt; A.ndim &amp;amp; B.ndim 의 값은 1&lt;/b&gt;이며 ( 1차원 배열이니깐. )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;A.shape 과 B.shape의 값은 &lt;b&gt;(3,)&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;벡터의 산술연산(+, -, *, /)은 &lt;b&gt;벡터의 각각의 원소에 대응하여 연산되어진다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;ex 벡터 증감연산) = &amp;gt; &lt;u&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;[&lt;/span&gt;&lt;/u&gt; &lt;u&gt;벡터A의 첫번째 원소 + 벡터B의 첫번째 원소&lt;/u&gt; , &lt;u&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;벡터A의 2번째 원소 + 벡터B의 2번째 원소 ...&lt;/span&gt;&lt;/u&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt; &lt;/span&gt;&lt;u&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737731434073&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 벡터 산술 연산
print(&quot;A + B ==&quot;, A + B)
print(&quot;A - B ==&quot;, A - B)
print(&quot;A * B ==&quot;, A * B)
print(&quot;A / B ==&quot;, A / B)&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;NumPy&amp;nbsp; &lt;span style=&quot;color: #ee2323;&quot;&gt;matrix&amp;nbsp;행렬&lt;span style=&quot;color: #666666;&quot;&gt;(&amp;nbsp;&lt;u&gt;2차원 배열&amp;nbsp;&lt;/u&gt;)&lt;/span&gt;&lt;/span&gt;:&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;행 x 열 (ex. 2 x 3 행렬은 =&amp;gt; 행의 갯수가 2개 &amp;amp; 열의 갯수가 3개인 행렬. 행은 하나의 1차원 배열. 열은 각 행의 요소의 갯수.)&lt;br /&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;행을 matrix의 세로의 크기 및 층&lt;/span&gt;으로, &lt;span style=&quot;color: #ee2323;&quot;&gt;열을 matrix의 가로의 크기 및 각 층의 길이&lt;/span&gt;로 보면 이해하기 쉽다.&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&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;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span&gt;&lt;b&gt;행렬 역시 벡터와 마찬가지로 &lt;u&gt;numpy의 array 메서드. 즉 배열 자료구조를 통해 구현가능&lt;/u&gt;하다.&lt;/b&gt;&lt;/span&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;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span&gt;&lt;b&gt;다만, 다른점은 벡터는 1차원 배열로 표현하였다면, 행렬은 2차원 배열로 표현된다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;행렬은 행과 열, 즉 가로 x 세로 로 표현되니깐 2차원 ㅇㅇ&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이미지는 평면적인 2D니깐 x축 y축 으로만 표현되니 행렬로 표현가능한거.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여기서 입체적인 3D는 z축까지 필요하니 그때부턴 3차원이 등장 ㅇㅇ.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&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;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;vector = numpy.array ( [ 1, 2, 3...] )&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;matrix = numpy.array ( [ [1, 2, 3] , [4, 5, 6] ... ] )&amp;nbsp;&lt;/span&gt;&amp;nbsp;&amp;nbsp; # 2 x 3 행렬&amp;nbsp; (2행 3열)&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&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;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span&gt;&lt;b&gt;행렬은 2차원 배열 형태이기에, array 메서드안에 2차원 리스트(2개의 대괄호 [ ]) 를 사용하여 생성된 모습이다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span&gt;&lt;b&gt;각 내부 리스트는 한 행을 나타낸다. &lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;( [1, 2, 3]은 첫 번째 행, [4, 5, 6]은 두 번째 행을 의미)&lt;/i&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #ffc1c8;&quot;&gt;&lt;span&gt;&lt;b&gt; 여기서 !&amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;게시물 서두에서도 언급되었지만, &lt;u&gt;벡터는 그냥 1차원 리스트, 행렬은 그냥 2차원 리스트로 표현하면 편한거 아닌가? 싶겠지만,&lt;/u&gt;&lt;/b&gt;&lt;/span&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;span style=&quot;color: #333333; background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; NumPy 배열(array)은 파이썬 리스트보다 &lt;b&gt;행렬 연산에 훨씬 효율적이고 다양한 기능을 제공하기 때문에,&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;numpy 의 array 메서드에 리스트를 전달하여 ➡ 넘파이 배열&lt;span style=&quot;color: #000000;&quot;&gt;( array() )&lt;/span&gt;로 벡터 및 행렬을 생성하는 것&lt;/span&gt;이다.&lt;/b&gt;&lt;/b&gt;&lt;/span&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;&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;span style=&quot;color: #333333; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이제 행렬 A와 B의 형상과 차원 값을 출력해보자.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;A와 B는 2행 3열 짜리 행렬이기때문에 형상값은 (2,3) 차원값은 2 가 출력된다.&lt;/span&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;행렬의 shape 속성값은 (m, n) 형태를 가지며, 여기서 m은 &lt;u&gt;행의 개수&lt;/u&gt;, n은 &lt;u&gt;열의 개수&lt;/u&gt;를 나타낸다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737733645745&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# matrix A,B 형상 출력 =&amp;gt; shape 속성
# 2행 x 3열 행렬이니깐 (2,3)이 출력됨
print(&quot;A.shape ==&quot;, A.shape, &quot;, B.shape ==&quot;, B.shape)

# matrix A,B 차원 출력 =&amp;gt; ndim 속성
# 행렬이니깐 2차원이 출력됨
print(&quot;A.ndim ==&quot;, A.ndim, &quot;, B.ndim ==&quot;, B.ndim)&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;span style=&quot;color: #000000;&quot;&gt;&amp;lt;출력&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;A.shape&amp;nbsp;==&amp;nbsp;(2,&amp;nbsp;3)&amp;nbsp;,&amp;nbsp;B.shape&amp;nbsp;==&amp;nbsp;(2,&amp;nbsp;3) &lt;br /&gt;A.ndim&amp;nbsp;==&amp;nbsp;2&amp;nbsp;,&amp;nbsp;B.ndim&amp;nbsp;==&amp;nbsp;2&lt;/blockquote&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;h2 style=&quot;text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;형 변환 (&lt;span style=&quot;color: #ee2323;&quot;&gt;reshape 메서드&lt;/span&gt;):&lt;/b&gt;&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;머신러닝 코드에서 가중치를 계산하거나 이미지 처리를 하기위해서는,&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;행렬의 곱인 dot product 연산을 반드시 해야한다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;이러한 행렬 곱을 하기위해서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;vector를 matrix로 변경&lt;span style=&quot;color: #000000;&quot;&gt;하거나&lt;/span&gt;&lt;/span&gt; or &lt;span style=&quot;color: #ee2323;&quot;&gt;matrix를 다른 형상의 matrix로 변경&lt;span style=&quot;color: #000000;&quot;&gt;해주는 작업이 필요하다.&lt;/span&gt;&lt;/span&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;이럴때 사용하는 것이 바로 &lt;u&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;reshape()&lt;/span&gt; 메서드&lt;/u&gt; 이다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;이름에서도 알 수 있듯이 &lt;u&gt;행렬의 shape 즉 형상을 변경해주는 메서드&lt;/u&gt;이다.&amp;nbsp;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;아래의 그림은 2 x 3 행렬을 3 x 2 행렬로 형 변환한 예시이다. &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;&lt;/b&gt;&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;694&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw7mWC/btsL0OfnWIM/kjnurf07zowGKx1hkjCW31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw7mWC/btsL0OfnWIM/kjnurf07zowGKx1hkjCW31/img.png&quot; data-alt=&quot;matrix 를 다른 형상의 matrix로 reshape&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw7mWC/btsL0OfnWIM/kjnurf07zowGKx1hkjCW31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw7mWC%2FbtsL0OfnWIM%2Fkjnurf07zowGKx1hkjCW31%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;694&quot; height=&quot;563&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;matrix 를 다른 형상의 matrix로 reshape&lt;/figcaption&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;아래의 코드는 1차원 배열 벡터를 1 x 3 행렬로 형 변환환 코드 예시이다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737735891031&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import numpy as np 
# vector 생성
C = np.array([1,2,3])

# vector C 형상 출력 =&amp;gt; (3,)
print(&quot;C.shape ==&quot;, C.shape)

# vector를 1 x 3 형상의 행렬로 형 변환
C = C.reshape(1,3)

print(&quot;C.shape ==&quot;, C.shape)&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;근데 생각해보니 뭔가 이상하다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;요소가 3개짜리인 벡터를 1행 3열짜리 행렬로 형 변환하는게 무슨 의미일까?&amp;nbsp;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 겉으로 보기에는 1 x 3 행렬과 3열짜리 벡터가 같아 보이지만, 벡터를 1행 n열로 볼 수도 있지만,&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt; 벡터는&amp;nbsp;1차원 배열로 취급함을 기억해야한다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt; 겉보기에는 1x3 행렬과 3열 벡터 모두 3개의 숫자를 나열한 것처럼 보이겠지만, 둘의 차원이 다르다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt; 1x3 행렬은 2차원 데이터 구조이고, 3열 벡터는 1차원 데이터 구조이다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt; 이 부분이 혼동스러울 수 있는데, NumPy에서는 벡터와 행렬을 구분하여 다룬다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt; 행렬 곱셈과 같은 행렬 연산은 1x3 행렬에 적용 가능하지만, 3열 벡터에는 적용할 수 없다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #ee2323;&quot;&gt;&lt;b&gt;벡터는 1차원, 행렬은 2차원. 꼭 기억하자.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;저 벡터의 ndim을 출력해보면 1이 나올것이고 형 변환 후 1x3 행렬이 되고나서 ndim값은 2가 출력될 것이다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000; background-color: #f6e199;&quot;&gt;&lt;b&gt;즉 &lt;b&gt;요소가 3개짜리인 벡터를 1행 3열짜리 행렬로 형 변환하는 것은 - &amp;gt; 1차원 데이터 구조를 2차원 데이터 구조로 변환하는 것이다.&lt;/b&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;reshape로 벡터 - &amp;gt; 행렬 변환 후에는 행렬 연산(예: 행렬 곱셈)이 가능해지게 된다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;1차원 에서 2차원으로 차원이 업그레이드 되었기때문!&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000; background-color: #ffc9af;&quot;&gt;&lt;b&gt; 결론적으로, &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000; background-color: #ffc9af;&quot;&gt;&lt;b&gt;3열 벡터를 1x3 행렬로 변환하는 것은 단순히 모양을 바꾸는 것이 아니라, 데이터의 차원을 변경하고 행렬 연산을 가능하게 하는 중요한 과정이다.&lt;/b&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;&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;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;참고자료: &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #000000;&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/ku9-AxaznSA?si=C_psTTAFfEgFqtAg&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/ku9-AxaznSA?si=C_psTTAFfEgFqtAg&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI/Python</category>
      <category>numpy</category>
      <category>넘파이</category>
      <category>파이썬</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/26</guid>
      <comments>https://basecoding.tistory.com/entry/NumPy-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-Chapter1#entry26comment</comments>
      <pubDate>Sat, 25 Jan 2025 01:32:22 +0900</pubDate>
    </item>
    <item>
      <title>[라즈베리파이] LED 제어</title>
      <link>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-LED-%EC%A0%9C%EC%96%B4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  LED: 발광다이오드&lt;/span&gt;&lt;/h2&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LED는 전류를 가하면 빛을 발하는 소형 반도체 소자이다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LED는 2개의 다리를 가지는데, 긴 다리(+극)에서 짧은 다리(-극) 방향으로 전류가 흘러야 빛이 발생한다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;5:1-5:45&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;긴 다리(+)는 양극, 즉 p형 반도체로 전자가 부족한 상태&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;6:1-6:46&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;짧은 다리(-)는 음극, 즉 n형 반도체로 전자가 풍부한 상태&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;7:1-7:68&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전자는 (-)극에서 (+)극으로 이동하려는 성질을 가지고 있음&lt;/b&gt;(전자가 많은 곳에서 적은 곳으로 이동)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;7:1-7:68&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전류의 방향은 전자의 이동 방향과 반대.&lt;/b&gt;&amp;nbsp;즉, 전류는 (+)극에서 (-)극으로 흐름&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;8:1-8:72&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;양극(+)에 전압을 가하면, 양극의 전자 부족 현상이 심화되어, 음극(-)의 전자를 더욱 강하게 끌어당기게 됨&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;8:1-8:72&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, &lt;b&gt;양극(+)에 전압을 가하면 양극 -&amp;gt; 음극으로 전류가 쫙 흐르게되는 것.&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;10:1-11:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;따라서, LED의 긴 다리(+)에 전원의 (+)극 3.3V를 연결하고, 짧은 다리(-)에 전원의 (-)극 gnd를 연결해야, 전자가 (-)극에서 (+)극으로 이동하고, 전류가 (+)극에서 (-)극으로 흘러 LED가 빛을 낼 수 있는 것이다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;191&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kVNm8/btsLV75IhZE/2q5ISV4yawul3i5pkJIRck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kVNm8/btsLV75IhZE/2q5ISV4yawul3i5pkJIRck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kVNm8/btsLV75IhZE/2q5ISV4yawul3i5pkJIRck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkVNm8%2FbtsLV75IhZE%2F2q5ISV4yawul3i5pkJIRck%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;432&quot; height=&quot;191&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;191&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때, LED가 빛을 내기위한 적절한 전압은 2.2V ~ 2.4V 사이이며, 전류는 20~50mA가 적당한데, +극인 긴다리쪽에 3.3V 혹은 5V의 전압을 그대로 줘버리면 LED에 과전류가 형성되어 LED는 밝게빛나더라도 고장나게될 우려가있다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그래서, 이 전압에 추가적으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;저항&lt;/b&gt;&lt;/span&gt;을 달아주어 전압을 감소시켜 LED가 손상되지않을 적절한 전압으로 걸어주어야한다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때는 보통 1K&amp;Omega; 이하의 220 &amp;Omega; 저항을 사용해주면 된다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;구성 회로도는 아래와같다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;661&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A9Tp4/btsLVFVEvII/U1Ud0nB142I1zOK54jdjDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A9Tp4/btsLVFVEvII/U1Ud0nB142I1zOK54jdjDK/img.png&quot; data-alt=&quot;LED 제어 회로도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A9Tp4/btsLVFVEvII/U1Ud0nB142I1zOK54jdjDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA9Tp4%2FbtsLVFVEvII%2FU1Ud0nB142I1zOK54jdjDK%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;661&quot; height=&quot;483&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;661&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;LED 제어 회로도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1. 최상단 전원부와 GND 핀을 점퍼선으로 연결하여 해당 열에 GND를 전달하여 공유하도록 하였다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. 해당 GND를 공유하는 전원부와 한 연결부 간에 점퍼선으로 연결하여 해당 연결부에도 GND를 공유하도록 설정하였다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. 해당 연결부에 LED의 짧은 다리를 꽂아두어 LED의 음극으로 흘러온 전류를 GND쪽으로 흘려보내도록 설정한 것이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. 이제 LED의 긴다리 쪽에는 전압을 가하기위해 GPIO16번 핀과 연결하였는데, 그 사이에 220옴 저항을 사이에 두어서 적절한 전압량으로 변환하여 긴다리쪽으로 적절한 전압을 가하도록 하였다.&amp;nbsp;&lt;/b&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;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000; background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;LED제어 예제코드:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737435819773&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import RPi.GPIO as GPIO  #RPi.GPIO 모듈 가져옴
import time              #딜레이 사용하기 위해 time모듈 가져옴
GPIO.setmode(GPIO.BCM)   # BCM모드로 GPIO핀들을 사용  
                          
GPIO.setup(16,GPIO.OUT)  #GPIO 16번 핀을 출력용으로 설정
print ('start')          #시작을 알기 위해 start 프린트 출력

while(True):
    a = input('1 or 0 : ') // 사용자로부터 입력받는 값은 문자열형태
    a = int(a) // 정수형으로 변환하여 함수에 넘겨줘야함
    GPIO.output(16,a) // 1 이나 0 중에서 입력받은 값으로 16번핀으로 디지털 값 출력.
    //1은 디지털 출력 값 3.3V. -&amp;gt; 3.3V의 전압이 16번 핀을 통해 LED의 긴다리쪽으로 흐름.
    //0은 디지털 출력 값 0V. -&amp;gt; 0V가 흘러서 LED의 불이 꺼짐.
    
    # 입력받은 0 또는 1 값은 GPIO 핀을 통해 디지털 신호로 변환되어 출력됨
    # 이 디지털 신호는 LED의 긴다리쪽으로 전달됨.
    # 3.3V(HIGH) 신호가 인가되면 LED가 켜지고, 0V(LOW) 신호가 인가되면 LED가 꺼짐.
    
    time.sleep(1)    # 스레드 1초 딜레이
    if a == 1:
        print ('led on')
    elif a == 0 :
        print ('led off')&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이때 중요한 부분이있다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;우리가 리눅스 os 환경에서 실행중인 프로그램을 종료하려면 Ctrl + C 키를 입력하여 종료해야한다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;근데, 위 코드처럼 GPIO 핀을 통해서 전압이 출력되고있는 상황에서 프로그램을 종료하게되면, 즉 이 핀에 디지털 값 1이 출력된 상태로 프로그램이 종료되면 이 핀에 3.3V의 전압이 출력되는 상태가 지속되게된다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;혹여나, 이 상태에서 해당 핀에 0V 즉 GND가 연결되게되면 합선 문제가 발생하는 등 회로 고장같은 문제가 발생할 가능성이 있다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이를 해결하기위해, Rpi.GPIO 모듈의 &lt;span style=&quot;color: #ee2323;&quot;&gt;cleanup() 함수&lt;/span&gt;를 사용해주면 된다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;클린업 함수의 기능은 다음과 같다.&amp;nbsp;&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;GPIO 라이브러리가 현재 프로그램이 사용한 GPIO 핀의 설정을 초기화하고, 프로그램이 사용했던 핀들에 대한 정보를 삭제 &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 프로그램 사용한 모든 핀을 입력(GPIO.IN)으로 초기화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;자원 관리:&lt;/b&gt; cleanup() 함수는 GPIO 핀과 관련된 리소스를 해제하여 시스템 자원을 효율적으로 관리하는 데 도움을 줌&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 이를 통해 다른 프로그램이 동일한 핀을 사용할 때 충돌이 발생하는 것을 방지할 수 있게되며&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;( 이전 프로그램이 사용했던 핀 설정들은 클린업으로 지워졌기때문 ), &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;모든 핀들을 일단 입력모드로 초기화 시켜주기때문에 무언가 전압이 출력될 일이 없음 -&amp;gt; 핀이 출력 모드로 설정되어 있을 때 발생할 수 있는 잠재적인 위험(예: 의도하지 않은 전류 흐름)을 미연에 방지할 수 있게된다.&amp;nbsp;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;GPIO 응용프로그램은 주로 try - except - finally 구조로 작성하기를 권장하고있다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;except 부분에 Ctrl + C 입력으로인한 키보드 인터럽트 예외를 처리해주고 + finally 부분에 클린업과 같은 프로그램 종료시의 처리를 해주면된다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;아래 코드가 안정성을 더한 완벽한 코드이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737448348606&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import RPi.GPIO as GPIO  #RPi.GPIO 모듈 가져옴
import time              #딜레이 사용하기 위해 time모듈 가져옴

try:
	GPIO.setmode(GPIO.BCM)   # BCM모드로 GPIO핀들을 사용  
                          
	GPIO.setup(16,GPIO.OUT)  #GPIO 16번 핀을 출력용으로 설정
	print ('start')          #시작을 알기 위해 start 프린트 출력

	while(True):
   	 	a = input('1 or 0 : ') // 사용자로부터 입력받는 값은 문자열형태
  	    a = int(a) // 정수형으로 변환하여 함수에 넘겨줘야함
   		GPIO.output(16,a) // 1 이나 0 중에서 입력받은 값으로 16번핀으로 디지털 값 출력.
    	//1은 디지털 출력 값 3.3V. -&amp;gt; 3.3V의 전압이 16번 핀을 통해 LED의 긴다리쪽으로 흐름.
   		//0은 디지털 출력 값 0V. -&amp;gt; 0V가 흘러서 LED의 불이 꺼짐.
    
    	# 입력받은 0 또는 1 값은 GPIO 핀을 통해 디지털 신호로 변환되어 출력됨
   		# 이 디지털 신호는 LED의 긴다리쪽으로 전달됨.
   		# 3.3V(HIGH) 신호가 인가되면 LED가 켜지고, 0V(LOW) 신호가 인가되면 LED가 꺼짐.
    
    	time.sleep(1)    # 스레드 1초 딜레이
   	    if a == 1:
        print ('led on')
    	elif a == 0 :
        print ('led off')
        
 except KeyboardInterrupt:   # 프로그램 실행중에 Ctrl + C 인터럽트 발생시 예외처리 
 	print(&quot;Ctrl + C 종료&quot;)
 
 finally: # try 블럭이 정상종료하든 예외가 발생하든 에러가 발생하든 무조건 실행되는 블록. 
 	print(&quot;clean up 함수 호출&quot;)
    	GPIO.cleanup()&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>IOT/Raspberry Pi</category>
      <category>라즈베리파이</category>
      <category>라즈베리파이 led</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/25</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-LED-%EC%A0%9C%EC%96%B4#entry25comment</comments>
      <pubDate>Tue, 21 Jan 2025 14:04:17 +0900</pubDate>
    </item>
    <item>
      <title>[라즈베리파이] 회로에 대한 이해</title>
      <link>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-%ED%9A%8C%EB%A1%9C%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;회로에 대한 이해:&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; 브레드 보드:&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;라즈베리파이를 이용한 회로를 구성할때는 &lt;b&gt;브레드보드&lt;/b&gt; 라는 도구를 이용한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;브레드 보드(Bread Board)는 전자 부품을 연결하여 회로를 쉽게 구성해주는 보드로, 아래와 같은 모습을 하고있다.&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;1163&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VU8nO/btsLTI0t0uQ/4CxI3DvZEzQbXiecVWKES1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VU8nO/btsLTI0t0uQ/4CxI3DvZEzQbXiecVWKES1/img.png&quot; data-alt=&quot;브레드보드 외형과 내부연결도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VU8nO/btsLTI0t0uQ/4CxI3DvZEzQbXiecVWKES1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVU8nO%2FbtsLTI0t0uQ%2F4CxI3DvZEzQbXiecVWKES1%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;1163&quot; height=&quot;406&quot; data-origin-width=&quot;1163&quot; data-origin-height=&quot;406&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;브레드보드는 &lt;b&gt;전원부&lt;/b&gt;와 &lt;b&gt;연결부&lt;/b&gt; 총 2개의 구역으로 나누어진다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 그림에서 보이는 상단과 하단에 2개의 홈이 한 행으로 쭉 나열된 부분이 &lt;b&gt;전원부&lt;/b&gt; 부분이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;반면 2개의 &lt;b&gt;전원부&lt;/b&gt;를 제외한 가운데의 여러 홈들이 바로 &lt;b&gt;연결부&lt;/b&gt; 부분으로, 내부 연결도에 보이듯이 해당 1개의 열이 하나의 연결부이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;브레드보드의 &lt;b&gt;전원부&lt;/b&gt; 부분과 &lt;b&gt;연결부&lt;/b&gt; 부분은 해당 행 및 열 간에 연결된 접점끼리 같은 전류를 공유한다.&amp;nbsp;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;내부 연결도를 보면 하나의 행으로 쭉 연결된 &lt;b&gt;&lt;b&gt;전원부&lt;/b&gt; &lt;/b&gt;부분에 전류를 흘려주면 해당 버스 라인에는 동일한 전기가 흐르게 되는것이고, A B C D E 홈 중에서 하나의 홈에 전류를 흘려주면 해당 단자 라인에는 동일한 전기가 흘러 공유하게된다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;그렇기 때문에, 우리가 라즈베리파이를 이용하여 회로를 구성할때 이 브레드보드의 접점간 연결 상태를 고려하여 회로를 구성해야하는 것이 중요하다.&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;전원부&lt;/b&gt;는 양극(+)과 음극(-)을 넣어서 사용하는 공간인데, &lt;b&gt;양극이란 5V 및 3.3V의 &lt;span style=&quot;color: #ee2323;&quot;&gt;전원(VCC)&lt;/span&gt; - 음극이란 0V인 &lt;span style=&quot;color: #ee2323;&quot;&gt;GND&lt;/span&gt;를 일컫는다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;단자 띠는 LED - 온습도 센서 등 센서나 기타 hw 모듈들을 넣어서 사용하는 공간이다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;GPIO 정의:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p 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 Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; GPIO 핀은 소프트웨어를 통해 전압을 출력하거나 입력받을 수 있는 핀&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;GPIO(General Purpose Input/Output) 는 &lt;b&gt;소형 컴퓨터인 라즈베리파이와 외부 하드웨어 장치인 센서 - 모터 - 기타 HW 디바이스들 간에 디지털 신호 및 아날로그 신호를 주고받을 수 있도록해주는 입출력 핀&lt;/b&gt;이다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;GPIO 핀에 1값을 출력하면 &lt;b&gt;3.3V 전압&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;라즈베리파이에는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이 GPIO핀이 40개 존재하며, &lt;/span&gt;말 그대로 범용 입출력 핀이기 때문에 개발자의 마음대로 다목적으로 활용이 가능한데, &lt;b&gt;파이썬 - C++ 등과 같은 언어로 각 GPIO핀들을 입력-출력 중에서 선택하여 소프트웨어로 제어할 수 있다.&lt;/b&gt; &amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;앞으로의 포스팅에서는 풍부한 라이브러리와 레퍼런스가 존재하는 파이썬 언어를 이용하여 실습할 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1280&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRMckc/btsLSdmfhPR/K0JptAlYb1bY4Uk7Wqd3Uk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRMckc/btsLSdmfhPR/K0JptAlYb1bY4Uk7Wqd3Uk/img.png&quot; data-alt=&quot;라즈베리파이의 GPIO핀 도 다이어그램&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRMckc/btsLSdmfhPR/K0JptAlYb1bY4Uk7Wqd3Uk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRMckc%2FbtsLSdmfhPR%2FK0JptAlYb1bY4Uk7Wqd3Uk%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;1280&quot; height=&quot;734&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;라즈베리파이의 GPIO핀 도 다이어그램&lt;/figcaption&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5V 핀:&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #555555; text-align: justify;&quot;&gt;라즈베리파이4 모델 기준, 라즈베리파이의 전원을 인가하는데 연결해야하는 c타입 어댑터는 5V 3~4 암페어 표준이다.&lt;/span&gt;&lt;span style=&quot;color: #555555; text-align: justify;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #555555; text-align: justify;&quot;&gt;여기서, 5V 핀은 바로 이 &lt;/span&gt;&lt;span style=&quot;color: #555555; text-align: justify;&quot;&gt;Type-C 어댑터에서 인가하는 5V 전원 공급 장치를 출력하는 데 사용되는 핀이다.&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #555555; text-align: justify;&quot;&gt;즉, 콘센트에서 어댑터를 통해 공급되는 5V 전압은 라즈베리 파이를 실행하는 데에도 사용되고, 라즈베리파이의 GPIO 핀을 통해 외부 장치에 전압을 공급하는 데에도 사용되는 것이다.&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #555555; text-align: justify;&quot;&gt; 5V 핀은 라즈베리파이 Board 번호 기준 2와 4로 번호로 매겨져 있다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #555555; text-align: justify;&quot;&gt;이 2개의 5V핀들은 USB-C 어댑터에서 출력되는 5V 전압을 라즈베리 파이의 다른 부품들에 공급하는 역할을 하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;V는 전압, A는 암페어(전류)를 나타냄. 어댑터가 5V 3A라는 것은 5V의 전압으로 최대 3A의 전류를 공급할 수 있다는 뜻&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;콘센트는 전압을 제공하는 곳. 콘센트에 전선을 연결하면 콘센트에서 전압이 발생하고, 이 전압이 전자를 움직이게 하여 전류가 흐르게 됨.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;콘센트에 전선을 연결하면 전압이 발생하고(콘센트에 연결한 어댑터를 라즈베리파이에 연결), 어댑터가 라즈베리파이에 인가해주는 이 전압에 의해 전자가 움직이면서 전류가 흐르고, 전기 에너지가 발생하는 것.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;전압은 전자를 움직이게 하는 힘. 라즈베리 파이의 GPIO 핀에 전압을 가하면, 브레드보드와 연결된 &lt;b&gt;도체(전기가 잘 통하는 물질: 브레드보드에 사용되는 전선, LED, 센서, 모터 등 )&lt;/b&gt; 내부의 전자들이 움직이기 시작하고, LED, 센서, 모터 등이 작동하게 되는 것.&lt;/span&gt;&lt;/blockquote&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 키워드:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;br /&gt;전압(V):&lt;/b&gt; &lt;b&gt;전기를 흐르게 하는 힘.&lt;/b&gt; 높은 곳에서 낮은 곳으로 물이 흐르듯이, 전압이 높을수록 전류가 세게 흐름&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전류(A): 실제로 흐르는 전기의 양.&lt;/b&gt; 수도관에 흐르는 물의 양에 비유할 수 있음. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;전류는 전자의 흐름. 전자는 (-) 전하를 가진 아주 작은 입자로, 전압이 가해지면 높은 전압에서 낮은 전압쪽으로 이동 &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전기:&lt;/b&gt; 전기는 전자의 움직임으로 발생하는 에너지. 전자가 움직이면 전류가 흐르고, 전류가 흐르면 전기가 발생하는 것&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;닫힌 회로:&lt;/b&gt; 전류가 흐르기 위해서는 전자가 이동할 수 있는 닫힌 회로가 필요. 닫힌 회로는 전원(VCC)에서 시작하여 전선, 부품(LED, 센서 등)을 거쳐 GND로 돌아오는 경로를 말함. 이 순환 경로가 형성되어야 전류가 쭉~ 물레방아처럼 흐름&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅ 전원 관련 핀 분류:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 80px;&quot; border=&quot;1&quot; data-sourcepos=&quot;27:1-31:33&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot;&gt;&lt;b&gt; 핀 종류&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot;&gt;&lt;b&gt; 기능 &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot;&gt;&lt;b&gt; 입력 &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot;&gt;&lt;b&gt; 출력 &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot;&gt;&lt;b&gt; 전압 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-sourcepos=&quot;29:1-29:29&quot;&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;29:1-29:6&quot;&gt;&lt;b&gt;5V 핀&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;29:8-29:14&quot;&gt;고정적인 전원 공급&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;29:16-29:18&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;29:20-29:22&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;29:24-29:27&quot;&gt;5V (항상 5V 출력)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-sourcepos=&quot;30:1-30:33&quot;&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;30:1-30:8&quot;&gt;&lt;b&gt;3.3V 핀&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;30:10-30:16&quot;&gt;고정적인 전원 공급&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;30:18-30:20&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;30:22-30:24&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;30:26-30:31&quot;&gt;3.3V (항상 3.3V 출력)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-sourcepos=&quot;31:1-31:33&quot;&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;31:1-31:8&quot;&gt;&lt;b&gt;GPIO 핀&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;31:10-31:16&quot;&gt;선택적 전압 제어 가능&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;31:18-31:20&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;31:22-31:24&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;text-align: center; height: 20px;&quot; data-sourcepos=&quot;31:26-31:31&quot;&gt;0V ~ 3.3V (입력 값 0 or 1)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt; GND 핀&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;접지&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;0V (기준 전압)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;✅&lt;/b&gt;&lt;/span&gt;&lt;b&gt;GPIO 핀과의 차이점&lt;/b&gt;&lt;/h4&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 style=&quot;text-align: center;&quot;&gt;&lt;b&gt; 특징 &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt; 3.3V/5V 핀 &lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt; GPIO 핀 &lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt;출력 전압&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;고정 (3.3V 또는 5V)&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;디지털 신호 (0V 또는 3.3V), 제어 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt;제어 가능 여부&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;불가능 (항상 켜짐)&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;Python 등으로 소프트웨어 제어 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt;용도&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;센서, 모듈, 팬 등의 전원 공급&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;LED 깜박임, 신호 출력, 입력 신호 수신 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;b&gt;안전성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;고정된 전압으로 신뢰성 높음&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;프로그래밍 오류로 잘못된 출력 가능성 존재&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;br /&gt;&lt;b&gt;ex) 5V 핀 사용:&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;팬(쿨링 팬):&lt;/b&gt; 라즈베리파이의 발열을 줄이기 위해 팬이 항상 켜져 있어야 함.&lt;br /&gt;➡ &lt;b&gt;연결 예:&lt;/b&gt; (전원) &amp;rarr; 5V 핀&amp;nbsp; (접지) &amp;rarr; GND 핀&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;GND (Ground) 핀 &lt;span style=&quot;color: #666666;&quot;&gt;(접지 핀)&lt;/span&gt;: 전기 회로에 숨어있는 핵심 - 전압의 기준점&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; GND는 0V의 기준 전압 &amp;amp; 회로에서 흐르는 전류가 최종적으로 돌아오는 곳&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;GND는 전류가 돌아오는 길을 제공하여 닫힌 회로를 완성하는 역할을 한다. &lt;br /&gt;만약 GND가 없다면 전류는 흐를 곳을 찾지 못하고 회로가 작동하지 않게 된다.&lt;br /&gt;&lt;span style=&quot;color: #555555; text-align: justify;&quot;&gt;접지 핀은 전기 회로를 닫는 데 사용&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;GND&lt;/b&gt;란, 회로에서 전압을 측정하는 공통 기준점으로, -극 0V 의 전압을 일컫는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;회로에서 측정되고 다루어지는 모든 전압은 GND에 대한 상대 전압이다. 0V 이자 이름이 ground 즉 기반인 이유.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; GND는 'Ground'의 약자로, &lt;b&gt;전기 회로에서 전류가 돌아오는 길을 제공하는 필수적인 요소&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;물은 높은 곳에서 낮은 곳으로 흐르려고 하듯이, 전류도 높은 전압에서 낮은 전압으로 흐르려고하는 성질이있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 마치 물이 높은 곳에서 낮은 곳으로 흐르듯, 전류도 전압이 높은 곳에서 낮은 곳, 즉 GPIO -&amp;gt; GND로 흐른다.&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;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전류가 흐르기위해선 전압으로 인해 전기가 출발되더라도 도착지가 있어야 전기가 전류가 되어흐를 것이다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;그 도착지, 목적지 역할을 하는것이 바로 이 GND이다.&amp;nbsp;&lt;/b&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;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; GND가 없다면 전류는 흐를 곳을 찾지 못하고 회로가 작동하지 않게 된다.&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;라즈베리 파이의 GPIO 핀에 1값을 출력하면, GPIO 핀은 높은 전압 상태가 되고, 이때 전류는 GPIO 핀(높은 전압)에서 LED를 거쳐 GND(낮은 전압)로 흘러 다시 라즈베리파이의 GPIO 부분으로 흘러들어오게된다.&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;gpio를 통해 흐르는 전류는 GND를 통해서 다시 라즈베리 파이로 회귀-돌아오게되는데, 왜 다시 라즈베리파이로 회귀하는 것일까?&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;➡&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;전류가 계속 흐르기 위해서는&amp;nbsp;닫힌 회로가 필요하다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;마치 물레방아를 돌리기 위해서는 물이 계속 흘러야 하는 것처럼, 전기 회로도 전류가 계속 흐르는 닫힌 회로를 구성해야 작동할 수 있는 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;만약 전류가 라즈베리 파이로 돌아오지 않는다면, 이 순환되는 닫힌 회로가 끊어져 전류가 흐르지 못하게 되고, LED도 꺼지게 된다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전류는 마치 물이 흐르는 것처럼 순환하는 닫힌 회로를 통해 흐른다. 만약 전류가 라즈베리 파이로 돌아오지 않는다면, 이 순환 회로가 끊어져 전류가 흐르지 못하게 되고, LED도 꺼지게 된다.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예를 들어, 물(전류)은 수도관(gpio)를 통해 흘러나와 물레방아(LED)를 돌리고, 수로(GND)를 통해 다시 물탱크(라즈베리 파이)로 돌아오는 것과 같다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이처럼 전류는 항상 출발점(GPIO)에서 도착점(GND)까지 흐르는 폐쇄 회로-완전한 회로를 구성해야 작동한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:63&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;또한,&amp;nbsp; GND는 회로에서 발생하는 노이즈, 과전압 과전류 등을 배출되는 땅으로써 사용된다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;마치 우리 주변에 보이는 고전압 전선, 심지어 번개로 인한 벼락까지도 땅에 흘려보내 듯이,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;전류가 흘러 도착하는 장소이자 배출장소: 바로 이 GND가 이름이 ground인 이유이다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;전기 분야에서는 GND를 &lt;span style=&quot;color: #ee2323;&quot;&gt;접지&lt;/span&gt;라고도 표현한다. 콘센트에도 보면 과전류를 막기위해 GND(접지)가 존재한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;362&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/npdG9/btsLTtCeseY/SqgHnkkGkspGdNlw7oX681/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/npdG9/btsLTtCeseY/SqgHnkkGkspGdNlw7oX681/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/npdG9/btsLTtCeseY/SqgHnkkGkspGdNlw7oX681/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnpdG9%2FbtsLTtCeseY%2FSqgHnkkGkspGdNlw7oX681%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;362&quot; height=&quot;198&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;198&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;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;참고 자료:&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://youtu.be/gdlxa-ScfoI?si=_gjTGVJIrIbzzXvH&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/gdlxa-ScfoI?si=_gjTGVJIrIbzzXvH&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IOT/Raspberry Pi</category>
      <category>gnd</category>
      <category>GPIO</category>
      <category>라즈베리파이</category>
      <category>라즈베리파이 회로</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/24</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%9D%BC%EC%A6%88%EB%B2%A0%EB%A6%AC%ED%8C%8C%EC%9D%B4-%ED%9A%8C%EB%A1%9C%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4#entry24comment</comments>
      <pubDate>Tue, 21 Jan 2025 08:09:00 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter7. Text 개념 &amp;amp; 활용 실습</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter7-Text-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;h2 data-sourcepos=&quot;1:1-1:6&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;개요:&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-sourcepos=&quot;3:1-3:63&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 챕터에서는 &lt;b&gt;Jetpack Compose의 핵심 컴포저블 중 하나인 Text&lt;/b&gt;에 대해 자세히 알아보겠습니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:63&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:63&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; Text 컴포저블은 화면에 텍스트를 표시하는 데 사용되며, Android의 XML 레이아웃에서 TextView와 유사한 역할을 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:63&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; Jetpack Compose의 &lt;b&gt;Text&lt;/b&gt;는 다양한 스타일링 옵션과 유연한 텍스트 처리 기능을 제공해주기 때문에, 사용자 인터페이스에 풍부한 텍스트 표현을 가능하게 해줍니다.&lt;/span&gt;&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;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;5:1-5:16&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Text의 기본 사용법:&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-sourcepos=&quot;7:1-7:54&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Text 컴포저블은 가장 간단하게 문자열 리소스 또는 직접 입력한 텍스트를 화면에 표시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;Text(text = &quot;안녕하세요, Jetpack Compose!&quot;)
Text(text = stringResource(id = R.string.string_name)) 
// 위 코드는 리소스 폴더 (res) 안에 있는 strings.xml 파일에서
// string_name이라는 ID를 가진 문자열을 가져와서 Text 컴포저블에 표시하는 코드
// stringResource(): ID를 이용하여 문자열 리소스 값을 가져오는 함수

// 이렇게 코드를 작성하면 앱의 이름을 하드코딩하는 대신
// strings.xml 파일에 정의하여 관리할 수 있어서 편리하고 유지보수도 좋음&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;14:1-14:101&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;14:1-14:101&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;14:1-14:101&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;또한, Text 컴포저블은 Modifier를 비롯한 매개변수들을 사용하여 다양한 스타일과 레이아웃 속성을 적용할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;14:1-14:101&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예를 들어, 텍스트의 색상, 글꼴, 크기, 정렬 등을 변경할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;Text(
    text = &quot;Hello, Compose!&quot;,
    modifier = Modifier
        .background(Color.Yellow)
        .padding(16.dp)
        .fillMaxWidth(),
    color = Color.Blue,
    fontSize = 20.sp,
    fontWeight = FontWeight.Bold,
    textAlign = TextAlign.Center
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-sourcepos=&quot;66:1-66:38&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-sourcepos=&quot;30:1-30:14&quot; data-ke-size=&quot;size26&quot;&gt;T&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ext의 스타일링 ( &lt;b&gt;TextStyle&lt;/b&gt; ):&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-sourcepos=&quot;32:1-32:113&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Text 컴포저블은 &lt;b&gt;TextStyle&lt;/b&gt;을 사용하여 텍스트의 스타일을 세밀하게 제어할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;32:1-32:113&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;TextStyle은 텍스트의 색상, 글꼴, 크기, 정렬, 줄 간격 등 다양한 속성을 포함합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;32:1-32:113&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;32:1-32:113&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;34:1-34:23&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  TextStyle의 주요 속성&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;36:1-46:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;36:1-36:30&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;color&lt;/b&gt;: 텍스트의 색상을 지정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;37:1-37:35&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;fontFamily&lt;/b&gt;: 텍스트의 글꼴을 지정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;38:1-38:41&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;fontSize&lt;/b&gt;: 텍스트의 크기를 지정합니다. (sp 단위)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;39:1-39:79&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;fontWeight&lt;/b&gt;: 텍스트의 굵기를 지정합니다. (예: FontWeight.Bold, FontWeight.Normal)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;40:1-40:59&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;fontStyle&lt;/b&gt;: 텍스트의 스타일을 지정합니다. (예: FontStyle.Italic)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;41:1-41:115&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;textAlign&lt;/b&gt;: 텍스트의 정렬을 지정합니다. (예: TextAlign.Start, TextAlign.Center, TextAlign.End, TextAlign.Justify)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;42:1-42:112&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;textDecoration&lt;/b&gt;: 텍스트에 밑줄, 취소선 등의 장식을 추가합니다. (예: TextDecoration.Underline, TextDecoration.LineThrough)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;43:1-43:45&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;lineHeight&lt;/b&gt;: 텍스트의 줄 간격을 지정합니다. (sp 단위)&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;44:1-44:37&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;maxLines&lt;/b&gt;: 텍스트의 최대 줄 수를 지정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;45:1-46:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;overflow&lt;/b&gt;: 텍스트가 지정된 영역을 넘어갈 경우 어떻게 처리할지 지정합니다. (예: TextOverflow.Ellipsis)&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;style1&quot; /&gt;
&lt;h3 data-sourcepos=&quot;47:1-47:22&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-sourcepos=&quot;47:1-47:22&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;AnnotatedString&lt;/u&gt;&amp;nbsp; &lt;/span&gt;&amp;amp;&amp;nbsp; &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;u&gt;buildAnnotatedString&lt;/u&gt;&amp;nbsp;&lt;/span&gt; &amp;amp;&amp;nbsp; &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;u&gt;withStyle&lt;/u&gt;&amp;nbsp;&lt;/span&gt; &amp;amp;&amp;nbsp; &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;u&gt;SpanStyle &lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-sourcepos=&quot;47:1-47:22&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;( 텍스트에 부분적으로 개별 스타일 적용해보기 )&lt;/b&gt;&lt;/span&gt;&lt;/h3&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-sourcepos=&quot;49:1-49:172&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;AnnotatedString을 사용하면 텍스트의 일부분에만 다른 스타일을 적용할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;49:1-49:172&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;buildAnnotatedString 빌더 함수를 사용하여 AnnotatedString을 생성하고, withStyle 함수를 사용하여 특정 범위의 텍스트에 SpanStyle을 적용함으로써 텍스트에 부분적으로 개별 스타일을 적용해볼 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;49:1-49:172&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:214&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;AnnotatedString은 Jetpack Compose에서 텍스트의 일부분에만 &lt;b&gt;다양한 스타일&lt;/b&gt;을 적용할 수 있도록 해주는 강력한 도구입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:214&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:214&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;AnnotatedString을 사용하면 텍스트의 특정 단어, 구절, 또는 문장에 &lt;b&gt;각기 다른 색상, 폰트, 크기, 장식 등을 적용&lt;/b&gt;하여 풍부한 텍스트 표현을 만들어낼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:162&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:162&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:162&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:162&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:60&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;buildAnnotatedString, withStyle, SpanStyle의 역할 분담:&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;9:1-15:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;9:1-9:149&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;buildAnnotatedString&lt;/b&gt;&lt;/span&gt;: AnnotatedString이라는 캔버스를 생성하는 빌더 함수입니다. 이 함수 안에서 append를 통해 일반 텍스트를 추가하거나, withStyle을 통해 특정 부분에 스타일을 적용할 수 있습니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;9:1-15:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;10:1-13:83&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;withStyle&lt;/b&gt;&lt;/span&gt;: buildAnnotatedString 내에서 사용되는 함수로, 특정 범위의 텍스트에 스타일을 적용합니다. &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;SpanStyle을 인자로 받아 해당 스타일을 적용할 텍스트 범위를 지정합니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;11:5-13:83&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;11:5-11:52&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;withStyle의 첫 번째 인자로 SpanStyle 객체를 전달합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;12:5-12:102&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;withStyle의 두 번째 인자로 스타일을 적용할 텍스트를 추가하는 람다 함수를 전달합니다. 람다 함수 내에서 append 함수를 사용하여 텍스트를 추가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;13:5-13:83&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;withStyle은 buildAnnotatedString에게 어떤 부분에 어떤 스타일을 적용해야 하는지 알려주는 역할을 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;9:1-15:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;14:1-15:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;SpanStyle&lt;/b&gt;&lt;/span&gt;: 텍스트의 일부분에 적용될 스타일을 정의하는 클래스입니다. color, fontWeight, fontFamily, textDecoration 등 TextStyle에서 제공하는 대부분의 스타일 속성을 사용할 수 있습니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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-sourcepos=&quot;16:1-16:10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #ffc9af;&quot;&gt;&lt;b&gt;동작 과정:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;18:1-23:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;18:1-18:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;buildAnnotatedString 함수를 사용하여 AnnotatedString 객체를 생성합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;19:1-19:36&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;append 함수를 사용하여 일반 텍스트를 빌더에 차곡차곡 추가합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;20:1-21:65&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;withStyle 함수를 사용하여 특정 범위의 텍스트에 SpanStyle을 적용합니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;21:5-21:65&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;21:5-21:65&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;바로 이 withStyle 함수 내에서 append 함수를 사용하여 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: left;&quot;&gt;withStyle에서 지정한 &lt;/span&gt;스타일을 적용할 텍스트를 추가하는 것.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-sourcepos=&quot;22:1-23:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;buildAnnotatedString 함수는 append와 withStyle에서 추가된 텍스트와 스타일 정보를 바탕으로 최종 AnnotatedString 객체를 생성합니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;31:1-31:13&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;예제 코드:&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;Text(
    text = buildAnnotatedString {
        append(&quot;This is &quot;) // 일반 텍스트 추가
        withStyle(style = SpanStyle(color = Color.Red, fontWeight = FontWeight.Bold)) { // 빨간색, 굵은 글씨 스타일 적용 시작
            append(&quot;Red&quot;) // &quot;Red&quot; 텍스트에 스타일 적용
        } // 스타일 적용 끝
        append(&quot; and &quot;) // 일반 텍스트 추가
        withStyle(style = SpanStyle(color = Color.Blue, textDecoration = TextDecoration.Underline)) { // 파란색, 밑줄 스타일 적용 시작
            append(&quot;Blue&quot;) // &quot;Blue&quot; 텍스트에 스타일 적용
        } // 스타일 적용 끝
        append(&quot; text.&quot;) // 일반 텍스트 추가
    }
)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;49:1-49:39&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;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;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-sourcepos=&quot;66:1-66:38&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #9feec3;&quot;&gt;&lt;b&gt;&amp;nbsp;실습:&lt;/b&gt; Text 컴포저블을 활용한 텍스트 표시 및 다양한 텍스트 스타일 지정해보기&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //enableEdgeToEdge()
        setContent {
            Chapter7Theme {
                TextContainer()
            }
        }
    }
}

@Composable
fun TextContainer() {
    val name = &quot;WjLee&quot;
    val words = stringResource(R.string.dummy_short_test)
    var wordArray = words.split(&quot; &quot;)

    // 텍스트 목록을 저장할 상태 변수
    val textList = remember { mutableStateListOf&amp;lt;String&amp;gt;() }

    // Random 색상을 remember로 기억 (클릭텍스트로 인해 재렌더링 일어나더라도 기존 색상이 유지되도록 Color 객체를 기억해두기.)
    val randomColors = remember {
        // map 함수는 컬렉션(예: 배열, 리스트)의 각 요소에 특정 연산(transform람다 내부에 기술)을 적용하여 새로운 컬렉션을 생성하는 함수
        // 여기서는,map 함수을 사용하여 wordArray의 length만큼 순환하면서 Color 객체를 생성하고, 이를 randomColors에 저장
        wordArray.map {
            Color(Random.nextInt(0, 255), Random.nextInt(0, 255), Random.nextInt(0, 255))
        }
    }
    // rememberScrollState: 스크롤 상태를 기억하는 함수. 스크롤 위치를 저장하고, 스크롤 위치를 변경할 때마다 스크롤 상태를 업데이트.
    val scrollState = rememberScrollState()

    Column(
        verticalArrangement = Arrangement.spacedBy(10.dp),
        modifier = Modifier
            .padding(16.dp)
            .fillMaxSize()
            .verticalScroll(scrollState)
    ) {

        Text(
            // buildAnnotatedString: AnnotatedString을 생성하는 빌더 함수. buildAnnotatedString를 사용하면 텍스트의 각 부분에 원하는 스타일을 자유롭게 적용할 수 있음.
            // AnnotatedString: 텍스트의 일부분에 각기 다른 스타일(색상, 폰트, 크기 등)을 적용할 수 있게 해주는 클래스.
            // withStyle: buildAnnotatedString 안에서 특정 텍스트 범위에 스타일을 적용할 때 사용하는 함수.
            // spanStyle: 텍스트의 스타일을 지정하는 클래스. 색상, 글꼴, 크기 등을 지정할 수 있음.

            // withStyle을 사용하여 스타일을 지정하고(SpanStyle을 통해) -&amp;gt; withStyle의 람다 함수 내부에 append를 사용하여 텍스트를 추가하면 -&amp;gt; append 함수로 추가된 텍스트에는 withStyle에서 지정한 스타일이 적용됨.
            // buildAnnotatedString는 이 정보들을 바탕으로 최종적으로 AnnotatedString을 생성

            text = buildAnnotatedString {

                // Brush.linearGradient: 선형 그라데이션을 생성하는 함수. 여러 색상을 지정하면 그 색상들을 선형으로 연결한 그라데이션을 생성.
                withStyle(
                    style = SpanStyle(
                        brush = Brush.linearGradient(
                            listOf(
                                Color.Red,
                                Color(255, 165, 0),
                                Color.Green,
                                Color.Blue,
                                Color(75, 0, 130),
                                Color(238, 130, 238)
                            )
                        )
                    )
                ) {
                    append(&quot;안녕하세요? 반갑습니다!\n&quot;)
                }
                withStyle(style = SpanStyle(color = Color.Blue, fontWeight = FontWeight.Bold))
                {
                    append(&quot;오늘도 좋은하루되세요!\n&quot;)
                }

                withStyle(
                    style = SpanStyle(
                        color = Color.Green,
                        fontFamily = FontFamily(Font(R.font.bamin_pro))
                    )
                )
                {
                    append(&quot;감사합니다~!&quot;)
                }
            },

            modifier = Modifier
                .fillMaxWidth()
                .background(Color(0xFFF5ECEC)),

            style = TextStyle(
                textAlign = TextAlign.Start,
            ),

            fontSize = 20.sp,
            lineHeight = 30.sp
        )

        Text(
            text = &quot;안녕하세요? 반갑습니다! ${name}&quot;,
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Yellow),
            style = TextStyle(
                textAlign = TextAlign.Center,
            ),
            fontWeight = FontWeight.Bold,
            fontSize = 20.sp,
        )

        Text(
            text = stringResource(id = R.string.dummy_short_test),
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Yellow),
            style = TextStyle(
                //Justify: 텍스트를 양쪽 맞춤으로 정렬
                textAlign = TextAlign.Justify,
                // 데코레이션: 밑줄, 취소선 등 텍스트에 추가적인 장식을 부여
                // combine: 여러 데코레이션을 리스트로 받아서 결합
                textDecoration = TextDecoration.combine(
                    listOf(
                        TextDecoration.LineThrough,
                        TextDecoration.Underline
                    )
                ),
            )
        )

        Text(
            text = buildAnnotatedString {
                wordArray.forEachIndexed { index, word -&amp;gt;
                    withStyle(
                        style = SpanStyle(
                            fontWeight = FontWeight.Bold,
                            color = randomColors[index]
                        )
                    ) {
                        append(&quot;${word} &quot;)
                    }
                }
            }
        )

        Text(
            text = stringResource(id = R.string.dummy_short_test),
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Yellow),
            style = TextStyle(
                textAlign = TextAlign.Start,
                // fontFamily: 텍스트의 글꼴을 지정, 여기서는 배달의 민족 꾸부림체 사용.
                fontFamily = FontFamily(Font(R.font.bamin_ggu)),
            ),
            fontSize = 18.sp,
            // lineHeight: 텍스트의 줄 간격을 지정
            lineHeight = 30.sp
        )

        Text(
            text = stringResource(id = R.string.dummy_long_test),
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Yellow),
            style = TextStyle(
                textAlign = TextAlign.Start,
            ),
            // maxLines: 텍스트의 최대 행 수를 지정
            maxLines = 3,
            // overflow: 텍스트가 표시 영역을 벗어났을 때 처리 방법을 지정.
            // Ellipsis: 텍스트가 표시 영역을 벗어났을 때 생략 부호(...)를 표시
            overflow = TextOverflow.Ellipsis
        )

        ClickableText(
            text = AnnotatedString(&quot;클릭!&quot;), onClick = {
                textList.add(&quot;클릭되었습니다~&quot;)
            }, style = TextStyle(
                color = Color.Blue,
                fontSize = 20.sp
            )
        )

        // 텍스트 목록을 표시
        textList.forEach { text -&amp;gt;
            Text(text = text, modifier = Modifier.padding(10.dp))
        }

    }
}


@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Chapter7Theme {
        TextContainer()
    }
}&lt;/code&gt;&lt;/pre&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 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;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #666666; color: #ffffff;&quot;&gt;&lt;b&gt;&amp;nbsp; 결과 화면&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;758&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xiz4h/btsLLsw6d4N/q1QdhFrcjQmccMGPlIW1Jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xiz4h/btsLLsw6d4N/q1QdhFrcjQmccMGPlIW1Jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xiz4h/btsLLsw6d4N/q1QdhFrcjQmccMGPlIW1Jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxiz4h%2FbtsLLsw6d4N%2Fq1QdhFrcjQmccMGPlIW1Jk%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;370&quot; height=&quot;679&quot; data-origin-width=&quot;413&quot; data-origin-height=&quot;758&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt; &lt;b&gt;  res 디렉터리에 다운로드받은 폰트 추가해주기!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zYEmV/btsLK3YwRZw/q75W11ffa0L5R1k60izCSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zYEmV/btsLK3YwRZw/q75W11ffa0L5R1k60izCSk/img.png&quot; data-alt=&quot;리소스 디렉터리에 font 하부 디렉터리 추가 &amp;amp;amp; 사용할 .ttf 폰트파일들 넣어주기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zYEmV/btsLK3YwRZw/q75W11ffa0L5R1k60izCSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzYEmV%2FbtsLK3YwRZw%2Fq75W11ffa0L5R1k60izCSk%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;318&quot; height=&quot;357&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;리소스 디렉터리에 font 하부 디렉터리 추가 &amp;amp; 사용할 .ttf 폰트파일들 넣어주기&lt;/figcaption&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;&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;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고 자료:&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/rZ5k-b3xmkU?si=p5wwIOxM2s8sOLPz&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/rZ5k-b3xmkU?si=p5wwIOxM2s8sOLPz&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/develop/ui/compose/text?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.android.com/develop/ui/compose/text?hl=ko&lt;/a&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;폰트 사이트:&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.woowahan.com/fonts&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.woowahan.com/fonts&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1736800636785&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;우아한형제들&quot; data-og-description=&quot;문 앞으로 일상의 행복을 배달합니다.&quot; data-og-host=&quot;www.woowahan.com&quot; data-og-source-url=&quot;https://www.woowahan.com/fonts&quot; data-og-url=&quot;https://www.woowahan.com&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/1e1kk/hyX0r6dOIY/Nv08cPd31r7FOdzMonr0K0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/E7Lqg/hyX0wfpdNz/up2cmCwkW4hguheny1JtB0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.woowahan.com/fonts&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.woowahan.com/fonts&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/1e1kk/hyX0r6dOIY/Nv08cPd31r7FOdzMonr0K0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/E7Lqg/hyX0wfpdNz/up2cmCwkW4hguheny1JtB0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;우아한형제들&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;문 앞으로 일상의 행복을 배달합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.woowahan.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/23</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter7-Text-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5#entry23comment</comments>
      <pubDate>Tue, 14 Jan 2025 05:00:01 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter6. BoxWithConstraints 개념 &amp;amp; 활용 실습</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter6-BoxWithConstraints-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;개요:&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;BoxWithConstraints 레이아웃은 이름에서도 알 수 있듯이 &lt;b&gt;기존 Box 레이아웃에 + Constraints 즉,&lt;/b&gt; &lt;b&gt;부모로부터 받은 제약 조건(Constraints)을 추가로 제공해주는 레이아웃&lt;/b&gt;입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;BoxWithConstraints는 부모로부터 받은 제약 조건(Constraints)을 활용하여 더욱 유연한 반응형 UI를 만들 수 있게 해주는 강력한 도구입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 이 제약 조건에는 minWidth, maxWidth, minHeight, maxHeight와 같은 정보가 포함되어 있으며, 이를 활용하여 자식 컴포저블의 크기나 위치를 동적으로 결정할 수 있습니다. &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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;23:1-23:28&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;BoxWithConstraints 활용 예시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;25:1-25:119&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;BoxWithConstraints를 사용하면 화면 크기나 방향에 따라 UI를 다르게 구성하거나, 부모로부터 받은 제약 조건에 따라 자식 컴포저블의 크기를 동적으로 조정하는 등 다양한 작업을 수행할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;25:1-25:119&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;25:1-25:119&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;27:1-27:25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;예시 1: 디바이스 방향에 따른 UI 변경&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
  
  //디바이스가 세로 모드인 경우, 화면의 너비가 높이보다 작으니깐  
    if (constraints.maxWidth &amp;lt; this.maxHeight) {
        // 디바이스 세로 모드
        Column {
            Text(&quot;Portrait Mode&quot;)
            // ...
        }
    } else {
        // 디바이스 가로 모드
        Row {
            Text(&quot;Landscape Mode&quot;)
            // ...
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;49:1-49:28&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;49:1-49:28&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;49:1-49:28&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;예시 2: 제약 조건에 따른 자식 요소의 크기 조정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
  
    val boxSize = if (this.maxWidth &amp;gt; 600.dp) {
        300.dp
    } else {
        150.dp
    }

    Box(modifier = Modifier
        .size(boxSize)
        .background(Color.Red))
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;66:1-66:38&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-sourcepos=&quot;66:1-66:38&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-sourcepos=&quot;66:1-66:38&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;실습: BoxWithConstraints를 활용한 반응형 UI&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;68:1-68:125&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이제 BoxWithConstraints를 사용하여 디바이스 가로모드-세로모드 전환에 따른 화면 크기 변동에 따라 동적으로 변하는 UI를 만들어 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;68:1-68:125&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 실습에서는 화면의 높이에 따라 다른 색상의 박스를 표시하고, 현재 화면의 높이값인 minHeight 값을 화면에 출력합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;68:1-68:125&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Chapter6Theme {
                BoxWithConstraintContainer()
            }
        }
    }
}

@Composable
fun BoxWithConstraintContainer() {

    BoxWithConstraints(
        modifier = Modifier
            .fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {


        // 디바이스의 세로-가로모드 마다 현재 이 컨테이너의 높이는 변경되기 때문에 이를 이용하여 조건을 걸어서 다른 색상의 뷰를 보여줄 수 있다.
        if (this.minHeight &amp;gt; 600.dp) {
            DummyBox(modifier = Modifier.size(200.dp), color = Color.Green)
        } else {
            DummyBox(modifier = Modifier.size(200.dp), color = Color.Yellow)
        }

        // this.minHeight: 현재 이 컨테이너의 제약조건인 높이 값을 가져올 수 있다.
        Text(text = &quot;minHeight: ${this.minHeight}&quot;)
    }
}

@Composable
fun DummyBox(modifier: Modifier = Modifier, color: Color? = null) {
    val red = Random.nextInt(256)
    val green = Random.nextInt(256)
    val blue = Random.nextInt(256)

    val randomColor = color?.let { it } ?: Color(red, green, blue)
    Box(
        modifier = modifier
            .size(100.dp)
            .background(randomColor)
    ) {
    }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Chapter6Theme {
        BoxWithConstraintContainer()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;135:1-135:10&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #666666; color: #ffffff; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;&lt;b&gt;결과 화면&lt;/b&gt;&amp;nbsp; &lt;span style=&quot;color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;lt;디바이스 세로모드&amp;gt;&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qfYRu/btsLKpGUleH/PjFcA90rehLu1fkLVAyrV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qfYRu/btsLKpGUleH/PjFcA90rehLu1fkLVAyrV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qfYRu/btsLKpGUleH/PjFcA90rehLu1fkLVAyrV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqfYRu%2FbtsLKpGUleH%2FPjFcA90rehLu1fkLVAyrV1%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;370&quot; height=&quot;624&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;676&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 이 디바이스의 높이는 790dp, 너비는 360dp 이기에, 기본모드인 세로모드의 경우&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt; if (this.minHeight &amp;gt; 600.dp) { // 세로모드 일 때
            DummyBox(modifier = Modifier.size(200.dp), color = Color.Green)&lt;/code&gt;&lt;/pre&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 조건식에 따라 초록색 박스가 화면에 그려집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;143:1-143:10&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #666666; color: #ffffff; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;&lt;b&gt;결과 화면&lt;/b&gt; &amp;nbsp;&lt;span style=&quot;color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;lt;디바이스 가로모드&amp;gt;&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;379&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crLdBd/btsLJWZubuT/Cq8h782o6Wp3RWlz8WpZ7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crLdBd/btsLJWZubuT/Cq8h782o6Wp3RWlz8WpZ7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crLdBd/btsLJWZubuT/Cq8h782o6Wp3RWlz8WpZ7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrLdBd%2FbtsLJWZubuT%2FCq8h782o6Wp3RWlz8WpZ7K%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;678&quot; height=&quot;379&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;379&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;디바이스를 옆으로 돌려서 가로모드가 된 경우,&amp;nbsp; 이때의 화면의 높이는 360dp로 변경되었기때문에&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;else { // 가로모드 일 때 (this.minHeight &amp;lt;= 600.dp)
    DummyBox(modifier = Modifier.size(200.dp), color = Color.Yellow)
}&lt;/code&gt;&lt;/pre&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 조건식에 따라 노란색 박스가 화면에 그려집니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고 자료:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://youtu.be/g2pd3a87-E4?si=BMHrHHclpQp6g3NL&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/g2pd3a87-E4?si=BMHrHHclpQp6g3NL&lt;/a&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/22</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter6-BoxWithConstraints-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5#entry22comment</comments>
      <pubDate>Mon, 13 Jan 2025 02:00:15 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter5. Box Layout 개념 &amp;amp; 활용 실습</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter5-Box-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;개요:&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;저번 챕터에서 알아본 Row &amp;amp; Column에 이어서, 이번 챕터에서는 Jetpack Compose의 또 다른 표준 레이아웃 중 하나인 Box 컴포저블에 대해 자세히 알아보겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row 가 x축, Column 이 y축 이었다면 Box는 화면상의 z축 배치를 담당하는 레이아웃 컴포저블 함수입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, &lt;b&gt;Box는 뷰(컴포저블 UI)를 겹쳐서 표현하고 싶을때 사용&lt;/b&gt;합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이는 XML 방식에서의 FrameLayout과 유사합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;272&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBJ9sU/btsLJAPQrBW/FmOyCXiJI7z8TWTjxzDKak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBJ9sU/btsLJAPQrBW/FmOyCXiJI7z8TWTjxzDKak/img.png&quot; data-alt=&quot;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBJ9sU/btsLJAPQrBW/FmOyCXiJI7z8TWTjxzDKak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBJ9sU%2FbtsLJAPQrBW%2FFmOyCXiJI7z8TWTjxzDKak%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;272&quot; height=&quot;301&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box의 핵심 속성 ➡&amp;nbsp; &lt;span style=&quot;color: #ee2323;&quot;&gt;contentAlignment &lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box 레이아웃의 핵심은 contentAlignment속성입니다.&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box는 Row - Column과는 달리 Arrangement 속성이 없고, Alignment 속성만 신경써주면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; contenteditable=&quot;true&quot; 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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box 레이아웃에 Arrangement 속성이 없는 이유는, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box는 Row, Column처럼 일렬로 배치하지 않고 자식들을 겹쳐서 배치하기 때문에, 자식들 간의 순차적인 정렬이나 간격을 조정하는 개념이 적용되지 않습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box의 Alignment는 vertival - horizontal 도 아닌 contentAlignment 속성으로 내부 요소들을 배치-정렬합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;contentAlignment 는 전체 자식들을 하나의 덩어리로 보고 정렬합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&amp;nbsp;개별 자식의 정렬이 아닌, 쌓여 있는 &lt;b&gt;전체 자식들의 정렬&lt;/b&gt;을 제어합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; 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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이는 마치 여러 장의 종이를 겹쳐 놓는 것과 유사합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;contentAlignment&amp;nbsp;는 겹쳐진 종이 뭉치를 책상 위 어디에 놓을지를 결정하는 속성과 같다고 할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box 레이아웃의 Alignment는 vertical 단독, horizontal 단독이 아닌,&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;vertical &amp;amp; horizontal, 즉 수직&amp;amp;수평 정렬을 모두 고려하는 속성이라고 생각하시면 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span&gt; contentAlignment &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;의 속성값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Column&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;자식 요소들의 수직 배치를 담당&lt;/b&gt;하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;vertical&lt;/span&gt;Arrangement&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;는 Arrangement 객체의 상수값을 인자로 받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Arrangement는 요소들을 배치하는 다양한 전략을 제공하는데, 다음과 같은 상수 속성값들이 제공됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  contentAlignment.TopCenter:&lt;/b&gt; 자식요소들을 수직 상단&amp;amp;수평 중앙에 배치합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt; contentAlignment.TopStart:&lt;/span&gt;&lt;/b&gt; 자식요소들을 수직 상단&amp;amp;수평 시작점(좌측)에 배치합니다. &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;default값&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;)&lt;/span&gt; &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt; contentAlignment.TopEnd:&lt;/span&gt;&lt;/b&gt; 자식요소들을 수직 상단&amp;amp;수평 끝점(우측)에 배치합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  contentAlignment.Center:&lt;/b&gt;&lt;span&gt; 자식요소들을 수직&amp;amp;수평 중앙에 배치&lt;/span&gt;합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;contentAlignment.CenterStart:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 자식요소들을 수직 중앙&amp;amp;수평 시작점(좌측)에 배치&lt;/span&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;contentAlignment.CenterEnd:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 자식요소들을 수직 중앙&amp;amp;수평 끝점(우측)에 배치&lt;/span&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style3&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  contentAlignment.BottomCenter:&lt;/b&gt;&lt;span&gt; 자식요소들을 수직 하단&amp;amp;수평 중앙에 배치합&lt;/span&gt;니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;contentAlignment.BottomStart:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 자식요소들을 수직 하단&amp;amp;수평 시작점(좌측)에 배치&lt;/span&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;contentAlignment.BottomEnd:&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 자식요소들을 수직 하단&amp;amp;수평 끝점(우측)에 배치&lt;/span&gt;합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;style6&quot; /&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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box의 추가 속성 ➡ &lt;span style=&quot;color: #009a87;&quot;&gt; propagateMinConstraints &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;propagateMinConstraints은 Box 의 속성 중 하나로,&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 해당 속성의 값을 true로 주면&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;해당 Box 내에서 크가가 가장 작은 뷰가 컨테이너 박스의 크기 만큼 constraint를 부여받게됩니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, Box의 자식들 중에서 가장 크기가 작은 컴포저블이 Box의 크기를 차지하게됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;디폴드 값은 false 입니다. &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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1736687580482&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Box( propagateMinConstraints = true ) {}&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;&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;style5&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #9feec3;&quot;&gt;&lt;b&gt;Box활용 실습 (랜덤 색상 박스 배치하기):&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //enableEdgeToEdge()
        setContent {
            Chapter5Theme {
                BoxContainer()
            }
        }
    }
}

@Composable
fun BoxContainer() {
    Box(
        modifier = Modifier
            .fillMaxSize(),
        //contentAlignment의 default값은 Alignment.TopStart.
        contentAlignment = Alignment.Center //Center 정렬: 모든 요소들 모아서 중앙에 배치
    ) {
        DummyBox(modifier = Modifier.size(200.dp), color = Color.Green)
        DummyBox(modifier = Modifier.size(150.dp), color = Color.Yellow)
        DummyBox(color = Color.Blue)

    }
}

@Composable
fun DummyBox(modifier: Modifier = Modifier, color: Color? = null) {
    val red = Random.nextInt(256)
    val green = Random.nextInt(256)
    val blue = Random.nextInt(256)

    //만약 외부에서 넘어오는 Color가 있다면 해당 값을 적용하고, 만약 color값이 null값이라면 -&amp;gt; 즉 없다면, 랜덤 색상을 적용.

    //?.: Safe Call 연산자. color 변수가 null이 아니면 let 함수를 호출하고, null이면 let 함수를 호출하지 않고 null을 반환
    //let { it }: let 함수는 람다 표현식을 인자로 받아서 실행하는 함수. 여기서는 color가 null이 아닐 경우, color 값을 it이라는 이름으로 람다 표현식 내부에서 사용할 수 있도록 전달하고, 람다 표현식의 결과를 반환. 이 경우, 람다 표현식은 단순히 it을 반환하므로, color 값이 그대로 반환
    //?:: 엘비스 연산자. 왼쪽 피연산자가 null이 아니면 왼쪽 피연산자를 반환하고, null이면 오른쪽 피연산자를 반환.
    // &amp;lt; ?.let{} ?: &amp;gt;  ?. 의 좌변 값이 null이 아니라면 우변인 let함수 실행하고(let 함수의 람다의 매개변수로 color가 it으로 넘어오고 이를 반환),&amp;lt; ?: &amp;gt; ?. 연산자가 null을 반환하고 -&amp;gt; 엘비스 연산자가 이어 받아서 처리. null이라면 우변값을 반환한다.
    // 즉, color가 null이 아니라면 color값을 그대로 대입하고, null이라면 랜덤 색상을 사용한다.
    val randomColor = color?.let{ it } ?: Color(red, green, blue)
    Box(
        modifier = modifier
            .size(100.dp)
            .background(randomColor),
        /*contentAlignment = Alignment.Center*/
    ) {

    }
}
fun add(x: Int, y: Int) { x + y }


@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    BoxContainer()
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;135:1-135:10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;135:1-135:10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;실습 단계별 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;137:1-142:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;137:1-137:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;BoxContainer&lt;/span&gt;는 Box를 사용하여 세 개의 DummyBox를 z축으로 겹쳐서 배치하는 컨테이너 컴포저블 함수&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;138:1-138:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Box의 modifier에 fillMaxSize()를 적용하여 Box 레이아웃이 화면 전체를 채우도록 설정&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;138:1-138:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #009a87; text-align: left;&quot;&gt;DummyBox1&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt; 은 200dp 사이즈의 초록색, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #f3c000; text-align: left;&quot;&gt;DummyBox2&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&amp;nbsp;은 150dp 사이즈의 노란색,&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7; text-align: left;&quot;&gt;DummyBox3&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;은 100dp 사이즈의 파란색 box 컴포저블이며,&amp;nbsp; &lt;span style=&quot;background-color: #f6e199; color: #333333; text-align: left;&quot;&gt;DummyBox1&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt; - &lt;span style=&quot;background-color: #f6e199; color: #333333; text-align: left;&quot;&gt;DummyBox2&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt; - &lt;span style=&quot;background-color: #f6e199; color: #333333; text-align: left;&quot;&gt;DummyBox3&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&amp;nbsp; 순서대로 겹쳐서 화면에 렌더링됨&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;140:1-140:91&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;contentAlignment를 contentAlignment.Center 로 설정하여 DummyBox들이 수직&amp;amp;수평 중앙에 정렬&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #666666; color: #ffffff;&quot;&gt;&amp;nbsp;결과 화면&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lfvGx/btsLJwzSDp6/6Jn5wt7MDynsrZvKdQoNSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lfvGx/btsLJwzSDp6/6Jn5wt7MDynsrZvKdQoNSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lfvGx/btsLJwzSDp6/6Jn5wt7MDynsrZvKdQoNSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlfvGx%2FbtsLJwzSDp6%2F6Jn5wt7MDynsrZvKdQoNSk%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;370&quot; height=&quot;674&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;143:1-143:10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고 자료:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/4W9rDwaiEPQ?si=AfJGgZjsAIWZfFvP&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/4W9rDwaiEPQ?si=AfJGgZjsAIWZfFvP&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/21</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter5-Box-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5#entry21comment</comments>
      <pubDate>Sun, 12 Jan 2025 22:07:59 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter4. Column Layout 개념 &amp;amp; 활용 실습</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter4-Column-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;개요:&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;저번 챕터에서 알아본 Row에 이어서, 이번 챕터에서는 Jetpack Compose의 또 다른 표준 레이아웃 중 하나인 Column 컴포저블에 대해 자세히 알아보겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Colomn은 Row와 반대 개념으로, &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;자식 Composable 요소들을 열방향 즉 세로 방향으로 배치하는 레이아웃입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이는 XML 기반 레이아웃의 LinearLayout에서 orientation을 vertical로 설정한 것과 유사합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&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;216&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1Bz5Q/btsLL6lAJ5U/EEMBSwRTCYfWoRpKFeL3S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1Bz5Q/btsLL6lAJ5U/EEMBSwRTCYfWoRpKFeL3S0/img.png&quot; data-alt=&quot;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1Bz5Q/btsLL6lAJ5U/EEMBSwRTCYfWoRpKFeL3S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1Bz5Q%2FbtsLL6lAJ5U%2FEEMBSwRTCYfWoRpKFeL3S0%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;216&quot; height=&quot;301&quot; data-origin-width=&quot;216&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Column의 핵심 속성 ➡&amp;nbsp; vertical&lt;span style=&quot;color: #ee2323;&quot;&gt;Arrangement&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;amp; horizontal&lt;span style=&quot;color: #ee2323;&quot;&gt;Alignment&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row 레이아웃의 핵심은 verticalArrangement 와 horizontalAlignment 속성입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;&lt;b&gt; &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;vertical&lt;/span&gt;Arrangement&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;속성을 통해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Column 내부 자식 요소들의 수직 배치&lt;/b&gt;를,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt; &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;horizontal&lt;/span&gt;Alignment&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;속성을 통해&lt;span&gt; &lt;b&gt;Column&lt;/b&gt; &lt;/span&gt;&lt;b&gt;내부 자식 요소들의 수평 정렬 방식&lt;/b&gt;을 조정할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;vertical&lt;/span&gt;Arrangement&lt;/b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;의 속성값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;Column&lt;/b&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;자식 요소들의 수직 배치를 담당&lt;/b&gt;하는 &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;vertical&lt;/span&gt;Arrangement &lt;/b&gt;&lt;/span&gt;&lt;/b&gt;는 Arrangement 객체의 상수값을 인자로 받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Arrangement는 요소들을 배치하는 다양한 전략을 제공하는데, 다음과 같은 상수 속성값들이 제공됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  Arrangement.Top&lt;/b&gt;: 자식 요소들을 Column 레이아웃의 시작 부분(상단)에 딱 붙여서 배치합니다. &lt;b&gt;(&lt;span style=&quot;color: #ee2323;&quot;&gt;default값&lt;/span&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Arrangement.Bottom&lt;/b&gt;: 자식 요소들을 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;Column&lt;/span&gt;의 끝 부분(하단)에 딱 붙여서 배치합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Arrangement.Center&lt;/b&gt;: 자식 요소들을 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;Column&lt;/span&gt;의 중앙에 딱 붙여서 배치합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Arrangement.SpaceBetween&lt;/b&gt;: 자식 요소들을 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;Column&lt;/span&gt;의 양 끝에 배치하고, 나머지 여백을 요소들 사이에 균등하게 분배합니다. 첫 번째 요소는 상단에, 마지막 요소는 하단에 붙고, 그 사이 요소들은 동일한 간격으로 배치됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Arrangement.SpaceAround&lt;/b&gt;: 자식 요소들의 상-하단에 동일한 크기의 여백을 둡니다. 즉, 각 요소의 위쪽과 아래쪽에 같은 크기의 공간이 추가됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Arrangement.SpaceEvenly&lt;/b&gt;: &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;Column&lt;/span&gt;의 시작과 끝, 그리고 각 자식 요소들 사이에 모두 동일한 크기의 여백을 둡니다. 즉, 첫 번째 요소의 위쪽 &amp;amp; 마지막 요소의 아래쪽 &amp;amp; 각 요소들 사이에 모두 동일한 크기의 공간이 추가됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-sourcepos=&quot;20:1-20:35&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;horizontal&lt;/span&gt;Alignment&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;의 속성값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-sourcepos=&quot;20:1-20:35&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;22:1-22:100&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;Column&lt;/b&gt;의 &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;horizontal&lt;/span&gt;Alignment &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;속성은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;자식 요소들의 수평 정렬을 담당하는 속성&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;22:1-22:100&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;verticalAlignment 속성값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;다음과 같이 Alignment 객체의 3가지 상수값들로 제공됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Alignment.Start&lt;/b&gt;: 자식 요소들을 Column의 좌측에 정렬합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Alignment.CenterHorizontally&lt;/b&gt;: 자식 요소들을 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;Column&lt;/span&gt;의 수평기준 중앙에 정렬합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Alignment.End&lt;/b&gt;: 자식 요소들을 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;Column&lt;/span&gt;의 우측에 정렬합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #9feec3;&quot;&gt;&lt;b&gt;Column활용 실습 (랜덤 색상 박스 배치하기):&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Chapter4Theme {
                VerticalContainer()
            }
        }
    }
}

@Composable
fun VerticalContainer() {
    //Column 레이아웃 컴포저블: 자식 요소들을 수직으로 배치하는 레이아웃.
    //Column의 핵심적인 속성은 verticalArrangement와 horizontalAlignment.


    // verticalArrangement: 자식 요소들을 수직 기준으로 어떻게 배치할지 결정. 기본값은 Top.
    // 컨테이너가 Column이기 때문에 verticalArrangement을 사용하여 수직상으로 어디에 배치할지 결정.

    // Arrangement.Top: 시작점을 기준으로 배치(Column 레이아웃의 상단에 붙어서 배치됨)
    // Arrangement.Bottom: 끝점을 기준으로 배치(하단에 붙어서 배치됨)
    // Arrangement.Center: 수직 중앙에 배치
    // Arrangement.SpaceAround: 자식요소들 상하측 주변에 동일한 간격을 두고 배치(요소들의 상-하 양 끝에 일정 간격이 생김)
    // Arrangement.SpaceBetween: 시작점(상단)과 끝점(하단)에 각각 붙어서 배치(양 끝에 붙어서 배치됨. 내부 요소들은 동일한 간격으로 배치됨)
    // Arrangement.SpaceEvenly: &amp;lt;시작부분 여백 &amp;amp; 끝부분 여백 &amp;amp; 자식요소들 사이 여백&amp;gt; 모두 동일한 간격을 두고 배치

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

    // horizontalAlignment: 자식 요소들을 수평 기준으로 어떻게 정렬할지 결정. 기본값은 Start.
    // 컨테이너가 Column이기 때문에 horizontalAlignment을 사용하여 수평상으로 어디에 배치할지 결정.

    // Alignment.Start: 시작점(Column의 좌측)을 기준으로 배치(자식 요소들이 Column의 좌측벽에 딱 붙어서 배치됨)
    // Alignment.End: 끝점(Column의 우측)을 기준으로 배치(자식 요소들이 Column의 우측벽에 딱 붙어서 배치됨)
    // Alignment.CenterHorizontally: 중앙을 기준으로 배치(중앙 배치)


    Column(

        modifier = Modifier
            .background(Color.White)
            //fillMaxSize: 컴포저블이 부모 컴포저블의 크기를 최대한 채우도록 지시. 가로, 세로 모두 최대 크기로 채움.
            //여기서는, Chapter3Theme이 Container()의 부모 역할을 하고, Container() 안에 있는 Column은 Chapter3Theme을 최종적인 부모로 갖는다.
            //Chapter3Theme은 기본적으로 화면 전체를 채우도록 설계되어 있음. 따라서, Column은 화면 전체를 채우게된다.
            //Chapter3Theme은 Material Design 컴포넌트를 제공하는 테마 컴포저블이자 최상위 컴포저블. 그 안에 Container()가 있고, Container() 안에 Column이 있음.
            .fillMaxSize(),

        verticalArrangement = Arrangement.SpaceEvenly, //SpaceEvenly 배치: 시작과 끝부분&amp;amp;자식요소들 사이에 동일한 간격을 두고 배치

        horizontalAlignment = Alignment.CenterHorizontally //CenterHorizontally 정렬: 수평 중앙에 배치
    ) {
        DummyBox ()
        DummyBox ()
        DummyBox ()

    }
}

@Composable
fun DummyBox(modifier: Modifier = Modifier) {
    val red = Random.nextInt(256)
    val green = Random.nextInt(256)
    val blue = Random.nextInt(256)
    val randomColor = Color(red, green, blue)
    Box(
        modifier = modifier
            .size(100.dp)
            .background(randomColor)
    ) {

    }
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Chapter4Theme {
        VerticalContainer()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;135:1-135:10&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;135:1-135:10&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;실습 단계별 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot; data-sourcepos=&quot;137:1-142:0&quot;&gt;
&lt;li data-sourcepos=&quot;137:1-137:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;VerticalContainer&lt;/span&gt;는 Column를 사용하여 세 개의 DummyBox를 수직으로 배치하는 컨테이너 컴포저블 함수&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;138:1-138:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Column의 modifier에 fillMaxSize()를 적용하여 Column 레이아웃이 화면 전체를 채우도록 설정&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;138:1-138:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;DummyBox&lt;/span&gt;는 랜덤한 색상의 배경을 가진 정사각형 Box를 생성하는 컴포저블 함수&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;139:1-139:104&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;verticalArrangement를 Arrangement.SpaceEvenly로 설정하여 DummyBox들이 Column내에서 균등한 간격으로 배치&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;140:1-140:91&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;verticalAlignment를 Alignment.CenterHorizontally로 설정하여 DummyBox들이 수평 중앙에 정렬&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #666666; color: #ffffff;&quot;&gt;&amp;nbsp;결과 화면&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;817&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4euTF/btsLKCeI19Z/l0l63XjqKYI64XnEHdnwoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4euTF/btsLKCeI19Z/l0l63XjqKYI64XnEHdnwoK/img.png&quot; data-alt=&quot;세 개의 랜덤색상 정사각형 박스가 화면 전체에 수직 방향으로 균등하게 배치되고, 수평 방향으로는 중앙에 정렬&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4euTF/btsLKCeI19Z/l0l63XjqKYI64XnEHdnwoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4euTF%2FbtsLKCeI19Z%2Fl0l63XjqKYI64XnEHdnwoK%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;370&quot; height=&quot;626&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;817&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세 개의 랜덤색상 정사각형 박스가 화면 전체에 수직 방향으로 균등하게 배치되고, 수평 방향으로는 중앙에 정렬&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;143:1-143:10&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;145:1-145:80&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고 자료:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/kkT1Sos2p2k?si=FnG-RHTYm_1I21zS&quot;&gt;https://youtu.be/kkT1Sos2p2k?si=FnG-RHTYm_1I21zS&lt;/a&gt;&lt;/p&gt;</description>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/20</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter4-Column-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5#entry20comment</comments>
      <pubDate>Sun, 12 Jan 2025 04:55:43 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter3. Row Layout 개념 &amp;amp; 활용 실습</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter3-Row-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;개요:&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 챕터에서는 Jetpack Compose의 또 다른 핵심 레이아웃 중 하나인 Row 컴포저블에 대해 자세히 알아보겠습니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row는 이름에서 알 수 있듯이, 자식 Composable 요소들을 행방향 즉 가로 방향으로 배치하는 레이아웃입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이는 XML 기반 레이아웃의 LinearLayout에서 orientation을 horizontal로 설정한 것과 유사합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row는 여러 Composable들을 수평(가로) 방향으로 나란히 배열할 때 사용합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row를 사용하면 버튼, 텍스트, 이미지 등 다양한 UI 요소들을 가로로 정렬하여 사용자 인터페이스를 구성할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;319&quot; data-origin-height=&quot;281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lHolE/btsLJKdpv6h/J3vxQkUZwuSiayeM5nalok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lHolE/btsLJKdpv6h/J3vxQkUZwuSiayeM5nalok/img.png&quot; data-alt=&quot;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lHolE/btsLJKdpv6h/J3vxQkUZwuSiayeM5nalok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlHolE%2FbtsLJKdpv6h%2FJ3vxQkUZwuSiayeM5nalok%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;319&quot; height=&quot;281&quot; data-origin-width=&quot;319&quot; data-origin-height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&lt;/figcaption&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row의 핵심 속성 ➡&amp;nbsp; horizontal&lt;span style=&quot;color: #ee2323;&quot;&gt;Arrangement&lt;/span&gt; &amp;amp; vertical&lt;span style=&quot;color: #ee2323;&quot;&gt;Alignment&amp;nbsp; &lt;span style=&quot;color: #000000;&quot;&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h4&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row 레이아웃의 핵심은 horizontalArrangement 와 verticalAlignment 속성입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;&lt;b&gt;horizontalArrangement&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;속성을 통해 &lt;b&gt;Row 내부 자식 요소들의 수평 배치&lt;/b&gt;를,&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;verticalAlignment&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;속성을 통해 &lt;b&gt;Row 내부 자식 요소들의 수직 정렬 방식&lt;/b&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;&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;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  horizontalArrangement&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 의 속성값&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row의 &lt;b&gt;자식 요소들의 수평 배치를 담당&lt;/b&gt;하는 horizontalArrangement는 Arrangement 객체의 상수값을 인자로 받습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Arrangement는 요소들을 배치하는 다양한 전략을 제공하는데, 다음과 같은 상수 속성값들이 제공됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;  Arrangement.Start&lt;/b&gt;: 자식 요소들을 Row의 시작 부분(좌측) 에 딱 붙여서 배치합니다. &lt;b&gt;(&lt;span style=&quot;color: #ee2323;&quot;&gt;default값&lt;/span&gt;)&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt; &lt;/b&gt; Arrangement.End&lt;/b&gt;: 자식 요소들을 Row의 끝 부분(우측) 에 딱 붙여서 배치합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt; &lt;/b&gt; Arrangement.Center&lt;/b&gt;: 자식 요소들을 Row의 중앙에 배치합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt; &lt;/b&gt; Arrangement.SpaceBetween&lt;/b&gt;: 자식 요소들을 Row의 양 끝에 배치하고, 나머지 여백을 요소들 사이에 균등하게 분배합니다. 첫 번째 요소는 왼쪽에, 마지막 요소는 오른쪽에 붙고, 그 사이 요소들은 동일한 간격으로 배치됩니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt; &lt;/b&gt; Arrangement.SpaceAround&lt;/b&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt; &lt;/b&gt; Arrangement.SpaceEvenly&lt;/b&gt;: Row의 시작과 끝, 그리고 각 자식 요소들 사이에 모두 동일한 크기의 여백을 둡니다. 즉, 첫 번째 요소의 왼쪽 &amp;amp; 마지막 요소의 오른쪽 &amp;amp; 요소들 사이에 모두 동일한 크기의 공간이 추가됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;20:1-20:35&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; &lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  verticalAlignment &lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;의 속성값&lt;/span&gt;&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;20:1-20:35&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;22:1-22:100&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row의 verticalAlignment 속성은 &lt;b&gt;자식 요소들의 세로 정렬을 담당하는 속성&lt;/b&gt;입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;22:1-22:100&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; verticalAlignment 속성값은 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;다음과 같이 Alignment 객체의 3가지 상수값들로 제공됩니다.&lt;/span&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;/b&gt; Alignment.Top&lt;/b&gt;: 자식 요소들을 Row의 상단에 정렬합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;/b&gt; Alignment.CenterVertically&lt;/b&gt;: 자식 요소들을 Row의 수직 중앙에 정렬합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; &lt;b&gt;&lt;b&gt; &lt;/b&gt;&lt;/b&gt; Alignment.Bottom&lt;/b&gt;: 자식 요소들을 Row의 하단에 정렬합니다.&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;&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;style6&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #9feec3;&quot;&gt;&lt;b&gt;Row 활용 실습 (랜덤 색상 박스 배치하기):&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Chapter3Theme {
                Container()
            }
        }
    }
}

@Composable
fun Container() {
    //Row 레이아웃 컴포저블: 자식 요소들을 가로로 배치하는 레이아웃.
    //Row의 핵심적인 속성은 arrangement와 alignment.

    // arrangement: 자식 요소들을 수직or수평 기준으로 어떻게 배치할지 결정. 기본값은 Start. css의 flex와 비슷한 개념.
    //컨테이너가 Row이기 때문에 가로로 배치되니깐 horizontalArrangement(수평 배치)을 사용.

    // Arrangement.Start: 시작점을 기준으로 배치(좌측에 딱 붙어서 배치됨)
    // Arrangement.End: 끝점을 기준으로 배치(우측에 딱 붙어서 배치됨)
    // Arrangement.Center: 중앙을 기준으로 배치(중앙 배치)
    // Arrangement.SpaceBetween: 시작점과 끝점에 각각 붙어서 배치(양 끝에 붙어서 배치됨. 내부 요소들은 동일한 간격으로 배치됨)
    // Arrangement.SpaceAround: 자식요소들 좌우측 주변에 동일한 간격을 두고 배치(요소들의 양 끝에 일정 간격이 생김)
    // Arrangement.SpaceEvenly: &amp;lt;시작부분 여백 &amp;amp; 끝부분 여백 &amp;amp; 자식요소들 사이 여백&amp;gt; 모두 동일한 간격을 두고 배치

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//

    // alignment: 자식 요소들을 수직or수평 기준으로 어떻게 정렬할지 결정. 기본값은 Top.
    // xml의 linearlayout의 gravity와 비슷한 개념. 즉, 내부 요소들을 어떻게 정렬할 것인지
    // 컨테이너가 Row이기 때문에 verticalAlignment을 사용하여 수직상으로 어디에 배치할지 결정.

    // Alignment.Top: 시작점을 기준으로 배치(상단에 붙어서 배치됨)
    // Alignment.Bottom: 끝점을 기준으로 배치(하단에 붙어서 배치됨)
    // Alignment.CenterVertically: 수직 중앙에 배치

    Row(

        modifier = Modifier
            .background(Color.White)
            //fillMaxSize: 컴포저블이 부모 컴포저블의 크기를 최대한 채우도록 지시. 가로, 세로 모두 최대 크기로 채움.
            //여기서는, Chapter3Theme이 Container()의 부모 역할을 하고, Container() 안에 있는 Row는 Chapter3Theme을 최종적인 부모로 갖는다.
            //Chapter3Theme은 기본적으로 화면 전체를 채우도록 설계되어 있음. 따라서, Row는 화면 전체를 채우게된다.
            //Chapter3Theme은 Material Design 컴포넌트를 제공하는 테마 컴포저블이자 최상위 컴포저블. 그 안에 Container()가 있고, Container() 안에 Row가 있음.
            .fillMaxSize(),
        
        horizontalArrangement = Arrangement.SpaceEvenly, //SpaceEvenly 배치: 시작과 끝부분&amp;amp;자식요소들 사이에 동일한 간격을 두고 배치 
        
        verticalAlignment = Alignment.CenterVertically //CenterVertically 정렬: 수직 중앙에 배치
            ) {
                DummyBox ()
                DummyBox ()
                DummyBox ()

    }
}

@Composable
fun DummyBox(modifier: Modifier = Modifier) {
    val red = Random.nextInt(256)
    val green = Random.nextInt(256)
    val blue = Random.nextInt(256)
    val randomColor = Color(red, green, blue)
    Box(
        modifier = modifier
            .size(100.dp)
            .background(randomColor)
    ) {

    }
}


@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Chapter3Theme {
        Container()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;135:1-135:10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;135:1-135:10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;실습 단계별 설명:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;137:1-142:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;137:1-137:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Container&lt;/span&gt;는 Row를 사용하여 세 개의 DummyBox를 수평으로 배치하는 컨테이너 컴포저블 함수&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;138:1-138:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Row의 modifier에 fillMaxSize()를 적용하여 Row 레이아웃이 화면 전체를 채우도록 설정&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;138:1-138:64&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;DummyBox&lt;/span&gt;는 랜덤한 색상의 배경을 가진 정사각형 Box를 생성하는 컴포저블 함수&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;139:1-139:104&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;horizontalArrangement를 Arrangement.SpaceEvenly로 설정하여 DummyBox들이 Row 내에서 균등한 간격으로 배치&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;140:1-140:91&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;verticalAlignment를 Alignment.CenterVertically로 설정하여 DummyBox들이 세로 중앙에 정렬&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #666666; color: #ffffff;&quot;&gt;&amp;nbsp;결과 화면&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;657&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIsj0A/btsLKGOM6os/ehxrfL7UKoJFC2NTOnccE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIsj0A/btsLKGOM6os/ehxrfL7UKoJFC2NTOnccE0/img.png&quot; data-alt=&quot;세 개의 랜덤색상 정사각형 박스가 화면 전체에 가로 방향으로 균등하게 배치되고, 수직 방향으로는 중앙에 정렬&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIsj0A/btsLKGOM6os/ehxrfL7UKoJFC2NTOnccE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIsj0A%2FbtsLKGOM6os%2FehxrfL7UKoJFC2NTOnccE0%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;370&quot; height=&quot;657&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;657&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세 개의 랜덤색상 정사각형 박스가 화면 전체에 가로 방향으로 균등하게 배치되고, 수직 방향으로는 중앙에 정렬&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-sourcepos=&quot;143:1-143:10&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;145:1-145:80&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고 자료:&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/kkT1Sos2p2k?si=FnG-RHTYm_1I21zS&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/kkT1Sos2p2k?si=FnG-RHTYm_1I21zS&lt;/a&gt;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/19</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter3-Row-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5#entry19comment</comments>
      <pubDate>Sat, 11 Jan 2025 04:42:58 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter2. LazyColumn 개념 &amp;amp; 활용 실습</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter2-LazyColumn-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5</link>
      <description>&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;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LazyColumn은 &lt;b&gt;화면에 보이는 항목만 렌더링&lt;/b&gt;하여 &lt;b&gt;메모리 사용량을 줄이고 성능을 향상&lt;/b&gt;시키는 Composable 함수입니다. 이는 XML 기반의 RecyclerView와 유사한 역할을 하며, 일종의 &lt;b&gt;Jetpack Compose 버젼의 RecyclerView&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p 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 Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: center;&quot;&gt;간단히 요약하면,&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: center;&quot;&gt; &lt;/span&gt;&lt;b&gt;화면에 보이는 Composable 요소만 표시해주는 스크롤 가능한 Column 레이아웃&lt;/b&gt; 입니다.&lt;/span&gt;&lt;/blockquote&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; LazyColumn의 이점 &amp;amp; Column과의 차이:&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Column은 모든 항목을 한 번에 렌더링하기 때문에 예를 들어, 수백 수천 개의 아이템을 가진 리스트를 Column으로 표시하 하는 등, 내부 요소들이 많아지면 성능 저하를 일으킬 수 있습니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;반면, LazyColumn은 &lt;b&gt;화면에 표시되는 항목만 렌더링&lt;/b&gt;하고 &lt;b&gt;스크롤할 때 동적으로 로드&lt;/b&gt;하므로 매우 효율적이며, 이 덕분에 사용자는 부드러운 스크롤 경험을 즐길 수 있고, 앱의 전반적인 성능 향상에도 도움이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그리고, 사용자가 스크롤을 통해 새로운 항목을 보려고 할 때만 해당 항목들을 로드하기 때문에, 초기 로딩 속도가 빠르고 메모리 사용량도 적습니다.&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;또한, Column에서 스크롤 기능을 구현하려면 Modifier.verticalScroll()을 사용하고 rememberScrollState()를 통해 스크롤 상태를 관리해야 하는 추가적인 작업이 필요합니다. 하지만 LazyColumn은 내부적으로 스크롤 상태를 관리해주며, 스크롤 기능이 기본적으로 내장되어 있어 별도의 설정 없이 바로 사용할 수 있다는 장점이 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;9:1-9:47&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;LazyColumn을 사용하면 얻을 수 있는 이점 요약:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;11:1-16:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;11:1-11:59&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;성능 향상:&lt;/b&gt; 화면에 보이는 항목만 렌더링하여 메모리 사용량을 최소화하고 앱 성능 향상&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;12:1-12:58&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;편의성:&lt;/b&gt; 스크롤 기능이 기본적으로 내장되어 있어 추가적인 설정 없이 사용가능&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;13:1-13:51&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;효율적인 리소스 관리:&lt;/b&gt; 필요한 항목만 동적으로 로드하여 메모리 사용량 감소&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;14:1-16:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;부드러운 스크롤:&lt;/b&gt; 사용자에게 부드러운 스크롤 경험을 제공&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-sourcepos=&quot;17:1-17:131&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이러한 장점들 때문에 Jetpack Compose에서 리스트를 표시할 때는 LazyColumn을 사용하는 것이 권장됩니다. 특히 항목의 개수가 많거나 성능이 중요한 경우에는 LazyColumn을 활용하는 것이 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:131&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:131&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:131&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;38:1-38:25&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;LazyColumn vs Column:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-sourcepos=&quot;40:1-46:89&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 style=&quot;color: #456771;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;특징&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LazyColumn&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Column&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-sourcepos=&quot;42:1-42:83&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;42:1-42:10&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;렌더링 방식&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;42:12-42:44&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;화면에 보이는 항목만 렌더링&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;42:46-42:81&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;모든 항목을 한 번에 렌더링&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-sourcepos=&quot;43:1-43:88&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;43:1-43:12&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;성능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;43:14-43:49&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;항목이 많을 때 효율적&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;43:51-43:86&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;항목이 많을 때 비효율적&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-sourcepos=&quot;44:1-44:98&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;44:1-44:9&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;메모리 사용량&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;44:11-44:52&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;적음&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;44:54-44:96&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;많음&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-sourcepos=&quot;45:1-45:87&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;45:1-45:11&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;사용 사례&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;45:13-45:46&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;긴 목록, 동적 콘텐츠 로딩&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;45:48-45:85&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;짧은 목록, 정적 콘텐츠&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-sourcepos=&quot;46:1-46:89&quot;&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;46:1-46:11&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;스크롤&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;46:13-46:46&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기본적으로 스크롤 가능&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;text-align: center;&quot; data-sourcepos=&quot;46:48-46:87&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Modifier 속성 및 상태관리 사용하여 스크롤 가능&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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 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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; LazyColumn의 &lt;span style=&quot;color: #ee2323;&quot;&gt;item&lt;/span&gt;, &lt;span style=&quot;color: #ee2323;&quot;&gt;items&lt;/span&gt;, &lt;span style=&quot;color: #ee2323;&quot;&gt;itemsIndexed&lt;/span&gt; :&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:173&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;LazyColumn의 마지막 매개변수인 content 람다 내에서 사용할 수 있는 item, items, itemsIndexed 함수들은 LazyColumn 내에 표시할 항목들을 정의하는 데 사용됩니다. 이 함수들을 통해 리스트, 헤더, 구분선 등 다양한 UI 요소를 유연하게 구성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:173&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;5:1-5:13&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;1. item&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;7:1-7:110&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;item 함수는 &lt;b&gt;단일 항목&lt;/b&gt;을 LazyColumn에 추가할 때 사용합니다. 주로 리스트의 Header&lt;b&gt;, Footer 또는 구분선&lt;/b&gt;과 같이 &lt;b&gt;고정된 단일 UI 요소&lt;/b&gt;를 추가하는 데 유용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:110&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;(ex. 리스트의 타이틀 제목, 검색 창, 저작권 정보 ...)&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:110&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;LazyColumn {
    item {
    //상품 리스트의 타이틀 제목 
        Text(&quot;List Title&quot;, style = TextStyle(fontWeight = FontWeight.Bold, fontSize = 20.sp))
    }
}

LazyColumn {
    item {
    //하단에 기술하는 저작권 정보
        Text(&quot;Copyright &amp;copy; 2023&quot;, style = TextStyle(fontSize = 12.sp))
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;25:1-25:14&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;25:1-25:14&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;2. items&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;27:1-27:104&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;items 함수는 &lt;b&gt;여러 항목(Composable UI들)&lt;/b&gt;을 LazyColumn에 추가할 때 사용합니다. 일반적으로 &lt;b&gt;데이터 리스트를 기반으로 반복적인 UI&lt;/b&gt;를 구성하는 데 사용됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;items 함수는 마지막 매개변수로 itemContent 람다식을 갖는데, 이&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;itemContent 람다식에는 인자값으로 -&amp;gt; items 함수로 넘겨받은 &lt;b&gt;리스트(또는 배열) 과 같은 iterable한 객체&lt;/b&gt;를 순회하면서 iterable의 각 요소들이 eachItem으로써 인자값으로 들어옵니다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;val itemList = listOf(&quot;Item 1&quot;, &quot;Item 2&quot;, &quot;Item 3&quot;)

LazyColumn {
    items(itemList) { eachItem -&amp;gt; // 리스트의 각 요소
        Text(text = eachItem)
    }
}

val itemArray = arrayOf(&quot;Item 1&quot;, &quot;Item 2&quot;, &quot;Item 3&quot;)

LazyColumn {
    items(itemArray) { item -&amp;gt;
        Text(text = item)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;39:1-39:53&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;19:1-19:10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;정리하자면:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-sourcepos=&quot;21:1-24:0&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-sourcepos=&quot;21:1-21:50&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;items 함수는 리스트나 배열과 같은 &lt;b&gt;iterable 객체&lt;/b&gt;를 인자로 받습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;22:1-22:56&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;items 함수는 마지막 매개변수로 &lt;b&gt;itemContent&lt;/b&gt;라는 람다식을 받습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;23:1-24:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;itemContent 람다는 items 함수에 전달된 iterable 객체의 &lt;b&gt;각 요소를 인자(eachItem)로 받아 해당 요소에 대한 UI를 생성&lt;/b&gt;합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;h3 data-sourcepos=&quot;51:1-51:21&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;itemsIndexed&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;53:1-53:150&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;itemsIndexed 함수는 items와 유사하지만, &lt;b&gt;항목의 인덱스(index)를 함께 제공&lt;/b&gt;합니다. 이를 통해 &lt;b&gt;홀수/짝수 항목에 다른 스타일을 적용&lt;/b&gt;하거나, &lt;b&gt;특정 인덱스에 특별한 UI를 표시&lt;/b&gt;하는 등 &lt;b&gt;인덱스 기반의 로직을 구현&lt;/b&gt;할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;br /&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;val itemList = listOf(&quot;Apple&quot;, &quot;Banana&quot;, &quot;Orange&quot;)

LazyColumn {
    itemsIndexed(itemList) { index, item -&amp;gt;
        if (index % 2 == 0) {
            Text(text = item, color = Color.Red) // 짝수 항목은 빨간색
        } else {
            Text(text = item, color = Color.Blue) // 홀수 항목은 파란색
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-sourcepos=&quot;69:1-69:6&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;69:1-69:6&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;정리:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100.233%; height: 97px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-sourcepos=&quot;71:1-75:147&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; text-align: center;&quot; data-sourcepos=&quot;73:1-73:15&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;item&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; text-align: center;&quot; data-sourcepos=&quot;73:17-73:82&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;단일 항목 추가&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; text-align: center;&quot; data-sourcepos=&quot;73:84-73:173&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;헤더, 푸터, 구분선 등 고정된 단일 UI 요소&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 37px;&quot;&gt;
&lt;td style=&quot;height: 37px; text-align: center;&quot; data-sourcepos=&quot;74:1-74:15&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;items&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px; text-align: center;&quot; data-sourcepos=&quot;74:17-74:75&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;리스트 형태의 여러 항목 추가 (List, Array, Set, Map...)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 37px; text-align: center;&quot; data-sourcepos=&quot;74:77-74:163&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;데이터 리스트를 기반으로 반복적인 UI 구성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;height: 40px; text-align: center;&quot; data-sourcepos=&quot;75:1-75:16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;itemsIndexed&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 40px; text-align: center;&quot; data-sourcepos=&quot;75:18-75:71&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;리스트 형태의 여러 항목 추가 (&lt;span style=&quot;color: #ee2323;&quot;&gt;+&amp;nbsp;&lt;b&gt;인덱스 제공&lt;/b&gt;&lt;/span&gt;)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;height: 40px; text-align: center;&quot; data-sourcepos=&quot;75:73-75:145&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;홀수/짝수 항목에 다른 스타일 적용, 특정 인덱스에 특별한 UI 표시 등 인덱스 기반의 로직 구현&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;77:1-77:150&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;77:1-77:150&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;77:1-77:150&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;LazyColumn 활용 실습:&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;background-color: #c1bef9; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;MainActivity.kt&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //enableEdgeToEdge()
        setContent {
            Chapter2Theme {
                ContentView()
            }
        }
    }
}

@Composable
fun ContentView() {
    Surface {
        Scaffold(
            containerColor = Color.White,
            topBar = {
                MyAppBar()
            },
        ) {
            //object 키워드로 선언된 싱글턴 객체인 DummyDataProvider의 userList를 인자로 전달
            RandomUserListView(DummyDataProvider.userList, modifier = Modifier.padding(it))
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MyAppBar() {
    TopAppBar(
        modifier = Modifier.height(58.dp),
        // 최신 Material 3에서는 TopAppBar의 색상을 변경하기 위해 TopAppBarDefaults.topAppBarColors() 함수를 사용해야 함.
        colors = TopAppBarDefaults.topAppBarColors(containerColor = Purple80),
        title = {
            Text(
                text = stringResource(id = R.string.my_app_name),
                fontWeight = FontWeight.Bold,
                color = Color.White,
                lineHeight = 58.sp // 텍스트 높이를 앱 바 높이와 동일하게 설정하여 수직 중앙 정렬
            )
        })
}

@Composable
fun RandomUserListView(randomUsers: List&amp;lt;RandomUser&amp;gt;, modifier: Modifier) {
    //일반적인 Column은 모든 아이템을 한 번에 메모리에 로드하기 때문에 아이템 개수가 많아질수록 메모리 사용량이 증가하고 성능이 저하될 수 있음.
    //하지만 LazyColumn은 화면에 보이는 아이템만 메모리에 로드하고, 화면에서 사라진 아이템은 메모리에서 제거합니다. 이러한 방식을 통해 메모리 사용량을 줄이고 성능을 향상시킬 수 있음
    //xml 시절의 RecyclerView와 비슷한 역할을 함. 화면에 보이는 일정 아이템들만 로드하고, 스크롤 시에만 새로운 아이템을 로드함
    LazyColumn(modifier = modifier) {
        //items(): 인자값으로 받은 리스트를 순회하면서 각 요소에 대해 람다식에 정의된 동작을 수행. LazyColumn은 items() 함수를 통해 효율적으로 리스트의 각 요소를 화면에 표시할 수 있는 것.
        items(items = randomUsers) { randomUser -&amp;gt;// itemContent 람다
            RandomUserView(randomUser)
        }
    }
}

@Composable
fun RandomUserView(randomUser: RandomUser) {
    //MaterialTheme.typography를 사용하여 텍스트 스타일을 지정. MaterialTheme.typography는 Material Design에 정의된 텍스트 스타일을 제공.
    //Type.kt에서 원하는대로 커스텀하여 사용할 수도 있음. -&amp;gt; 이 예제에서는 bodySmall과 bodyLarge 스타일을 커스텀하여 사용.
    val typography = MaterialTheme.typography
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(10.dp),
        //Card 컴포저블의 elevation 속성에는 Dp 타입이 아닌 CardElevation 타입의 값을 지정하도록 변경됨.
        //CardElevation을 사용하려면 CardDefaults.cardElevation() 함수를 사용하여 CardElevation 객체를 생성해야 함.
        // elevation 속성은 카드가 떠있는 정도를 나타냄.
        elevation = CardDefaults.cardElevation(defaultElevation = 10.dp),
        //카드 모서리 둥글게.
        shape = RoundedCornerShape(12.dp),

        )
    {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.White)
                .padding(10.dp),
            //내부 컴포저블들 수직 정렬
            verticalAlignment = Alignment.CenterVertically,
            // 내부 컴포저블들 간의 간격 지정
            horizontalArrangement = Arrangement.spacedBy(10.dp)
        ) {
/*            Box(
                modifier = Modifier
                    .size(width = 60.dp, height = 60.dp)
                    .clip(CircleShape)
                    .background(Color.Red)
            )*/

            //프로필 이미지를 표시하는 ProfileImg 컴포저블을 사용하여 프로필 이미지 표시.
            ProfileImg(imgUrl = randomUser.profileImage)

            Column() {
                Text(
                    text = randomUser.name,
                    //material 2 시절에는 typography에 직접 타이포그레피 정의가 가능했지만, material 3에서는 기존에 있는 상수형 속성들만 사용가능해짐.
                    style = typography.bodySmall
                )
                Text(
                    text = randomUser.description,
                    style = typography.bodyLarge
                )
            }
        }
    }

}


@Composable
fun ProfileImg(imgUrl: String, modifier: Modifier = Modifier) {
    //이미지 비트맵

    // MutableState 객체는 Compose에서 상태를 저장하고 관리하는 데 사용되는 특별한 객체. 이 객체는 value라는 프로퍼티를 가지고 있으며, 이 프로퍼티에 상태 값이 저장됨.
    // mutableStateOf() 함수: 상태 객체를 생성 &amp;amp; 반환. 상태 객체는 상태 값을 저장하고, 상태 값이 변경되면 UI업데이트 트리거 -&amp;gt; Composable 함수를 다시 호출하여 UI를 업데이트함.
    // remember: 컴포저블 함수가 다시 호출(재 컴포지션, UI 업데이트, UI재구성)되더라도 상태 값이 초기화되지 않고 이전 값을 유지할 수 있도록 해줌.
    val bitmap: MutableState&amp;lt;Bitmap?&amp;gt; = remember { mutableStateOf(null) }

   // 이미지 뷰의 크기와 모양을 지정하기 위한 modifier
    val imageModifier = modifier
        .size(50.dp)
        .clip(CircleShape)

    //Glide 라이브러리를 통해서 원격 이미지에 있는 비트맵을 다운로드받고 그 비트맵을 이미지뷰에 넣는식.
    //Glide.with() 함수는 Glide 인스턴스를 생성. Glide.with() 함수는 인자로 LocalContext.current로 현재 컨텍스트를 받음.
    //asBitmap().load(source): 해당 이미지를 비트맵으로 로드.
    //into(target): 비트맵 로드가 완료되면 해당 비트맵을 어디에 표시할지 지정.
    Glide.with(LocalContext.current)
        .asBitmap()
        .load(imgUrl)
        .into(object : CustomTarget&amp;lt;Bitmap&amp;gt;() { //CustomTarget: Glide에서 제공하는 비트맵 로드 콜백 인터페이스
            //onResourceReady(): 비트맵 로드가 완료되면 호출되는 콜백 메서드.
            //resource 매개변수: 다운로드 받은 비트맵 이미지 파일 추출물.
            override fun onResourceReady(resource: Bitmap, transition: Transition&amp;lt;in Bitmap&amp;gt;?) {
                bitmap.value = resource //Glide 라이브러리를 통해 다운로드받은 비트맵을 상태 값으로 저장.
            }

            override fun onLoadCleared(placeholder: Drawable?) {}
        })
    // 이제, 이 추출해낸 비트맵을 Image 컴포저블을 사용하여 화면에 표시.

    // if 비트맵이 정상적으로 존재한다면,
    // 비트맵을 ImageBitmap(이미지 비트맵)으로 변환하고, Image 컴포저블을 사용하여 화면에 표시.
    bitmap.value?.asImageBitmap()?.let {
        Image(
            bitmap = it, //최종 추출물인 비트맵 이미지를 Image 컴포저블에 전달하여 화면에 이미지 표시.
            contentDescription = null,
            contentScale = ContentScale.Fit,
            modifier = imageModifier
        )
    }
    // else 만약 비트맵이 존재하지 않는다면, 기본 이미지를 표시.
        ?: Image(
        painter = painterResource(R.drawable.ic_empty_user_img),
        contentDescription = null,
        contentScale = ContentScale.Fit,
        modifier = imageModifier
    )



}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Chapter2Theme {
        ContentView()
    }
}&lt;/code&gt;&lt;/pre&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 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;span style=&quot;background-color: #c1bef9; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;DummyDataProvider.kt&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;( LazyColumn에 표시될 랜덤 사용자 데이터를 생성하는 역할 )&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;package com.example.chapter2.utils

data class RandomUser(
    val name: String = &quot;어서오세요 개발자님  &amp;zwj; &quot;,
    val description: String = &quot;오늘도 즐거운 코딩하세요  &quot;,
    //더미 human이미지
    val profileImage: String = &quot;https://randomuser.me/api/portraits/women/74.jpg&quot;
    )
object DummyDataProvider { //object 키워드 -&amp;gt; 싱글턴 객체 선언
    //200개의 요소를 담을 수 있는 RandomUser 타입의 리스트를 생성 &amp;amp; 각 요소를 람다식 실행 결과인 RandomUser 객체로 초기화
    val userList = List&amp;lt;RandomUser&amp;gt;(200){RandomUser()}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;  RandomUser 클래스의 profileImage 속성에 있는 URL( &lt;a style=&quot;color: #666666;&quot; href=&quot;https://randomuser.me/api/portraits/women/74.jpg&quot;&gt;https://randomuser.me/api/portraits/women/74.jpg&lt;/a&gt; )과 같이 인터넷 상의 이미지를 앱에서 사용하려면 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;AndroidManifest.xml 파일에 아래와 같이 INTERNET 권한을 추가해줘야 합니다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; Android 운영체제는 앱이 인터넷에 접근하는 것을 기본적으로 제한하기때문에, INTERNET 권한을 AndroidManifest.xml에 추가함으로써, 앱이 인터넷에 접근해야 함을 명시적으로 선언하고, 사용자에게 해당 권한을 요청하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;&amp;lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #666666; color: #ffffff;&quot;&gt;&amp;nbsp;결과 화면&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen_recording_20250109_155419.gif&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;867&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s9TNn/btsLHwTX0Il/p3AWahdrEWf4bqLkGq8UNk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s9TNn/btsLHwTX0Il/p3AWahdrEWf4bqLkGq8UNk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s9TNn/btsLHwTX0Il/p3AWahdrEWf4bqLkGq8UNk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/s9TNn/btsLHwTX0Il/p3AWahdrEWf4bqLkGq8UNk/img.gif&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;400&quot; height=&quot;867&quot; data-filename=&quot;Screen_recording_20250109_155419.gif&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;867&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;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;참고 자료:&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://youtu.be/CFY0RWskVTA?si=uuwkWiMrwgtgxAJ7&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/CFY0RWskVTA?si=uuwkWiMrwgtgxAJ7&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/18</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter2-LazyColumn-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5#entry18comment</comments>
      <pubDate>Thu, 9 Jan 2025 15:57:55 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] 앱의 시작점, MainActivity 클래스 분석</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-%EC%95%B1%EC%9D%98-%EC%8B%9C%EC%9E%91%EC%A0%90-MainActivity-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%B6%84%EC%84%9D</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGo6P9/btsLK9jbafU/Orja2FT0u9OATXKdrvWn7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGo6P9/btsLK9jbafU/Orja2FT0u9OATXKdrvWn7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGo6P9/btsLK9jbafU/Orja2FT0u9OATXKdrvWn7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGo6P9%2FbtsLK9jbafU%2FOrja2FT0u9OATXKdrvWn7k%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;480&quot; height=&quot;325&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:248&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이번 포스팅에서는 Jetpack Compose 프레임워크를 이용한 Android 앱 개발의 기본이 되는 MainActivity 클래스와 그 안의 onCreate, setContent 등 MainActivity를 구성하는 핵심 요소들을 하나씩 짚어보는 시간을 갖도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Chapter1Theme {
                Greeting(&quot;반갑습니다!&quot;)
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;3:1-3:248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:248&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;5:1-5:22&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;MainActivity&lt;/b&gt;&lt;/span&gt; 클래스란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;7:1-7:123&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;MainActivity는 Android 앱의 시작점을 담당하는 핵심 클래스입니다. 앱이 실행되면 가장 먼저 MainActivity가 실행되고, 이 클래스 안에서 앱의 UI를 구성하고 초기화하는 작업이 이루어집니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:123&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;class MainActivity : ComponentActivity() {
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 코드에서 : ComponentActivity()는 MainActivity가 ComponentActivity를 상속받는다는 것을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;MainActivity는 &lt;/span&gt;ComponentActivity의 모든 기능을 물려받아 사용할 수 있으며, 추가로 자신만의 기능을 더하여 앱의 동작을 정의합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 즉, MainActivity는 &lt;b&gt;앱의 시작점이자 UI를 구성하고 앱의 로직을 담당하는 핵심적인 역할&lt;/b&gt;을 수행합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-sourcepos=&quot;5:1-5:22&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt; &lt;b&gt;ComponentActivity&lt;/b&gt;&lt;/span&gt; 클래스?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt; ComponentActivity&lt;/b&gt;는 Jetpack Compose를 사용하여 Android UI를 구성하기 위한 필수적인 기본 클래스로, Jetpack Compose와의 호환성을 보장하고 Compose UI를 표시하기 위한 핵심 기능을 제공하는 클래스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; ComponentActivity는 Activity 클래스를 상속받아 만들어졌습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Activity는 Android 앱에서 화면을 구성하는 기본 단위이며, ComponentActivity는 Activity의 기능을 확장하여 Jetpack Compose를 지원하도록 설계되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;9:1-9:133&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ComponentActivity는 setContent 확장 함수를 제공합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;9:1-9:133&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;11:1-11:195&quot; data-ke-size=&quot;size16&quot;&gt;ComponentActivity 클래스는 setContent 확장 함수를 통해 Jetpack Compose UI를 표시할 수 있도록 지원합니다. &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;setContent 함수는 ComponentActivity의 인스턴스에서 호출할 수 있으며, Composable 함수를 인자로 받아 액티비티의 콘텐츠 영역에 Compose UI를 구성시킵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;11:1-11:195&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;13:1-13:114&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;또한, ComponentActivity는 Jetpack Compose의 상태 관리, 생명 주기 관리 등 다양한 기능을 지원하여 Compose UI를 효율적으로 관리하고 업데이트할 수 있도록 도와줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;13:1-13:114&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;13:1-13:114&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;13:1-13:114&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;즉, MainActivity가 ComponentActivity를 상속받는 이유는 &lt;/span&gt;&lt;b&gt;Jetpack Compose를 사용하여 Android UI를 쉽고 효율적으로 구성하고 관리하기 위함&lt;/b&gt;이며, MainActivity는 ComponentActivity를 상속받음으로써 &lt;b&gt;Jetpack Compose의 강력한 기능을 활용하여 현대적인 Android UI를 구축할 수 있게 되는 것&lt;/b&gt;입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;15:1-15:216&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;17:1-17:20&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;onCreate()&lt;/b&gt;&lt;/span&gt; 함수 분석&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;19:1-19:106&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;onCreate() 함수는 MainActivity가 생성될 때 Android 시스템에 의해 자동으로 호출되는 함수입니다. 앱이 실행되면 가장 먼저 실행되는 부분이라고 생각하시면 됩니다. 마치 클래스의 생성자와 유사한 역할을 수행한다고 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;19:1-19:106&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-sourcepos=&quot;7:1-7:24&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;onCreate() 메서드의 역할&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;9:1-13:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;9:1-9:92&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;앱 초기화:&lt;/b&gt; 앱 실행에 필요한 리소스를 로드하고 초기 설정을 수행합니다. 예를 들어, 앱의 테마 설정, 언어 설정, 네트워크 연결 확인 등&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;10:1-10:95&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;UI 설정:&lt;/b&gt; setContent 블록을 사용하여 앱의 UI를 구성합니다. Compose에서는 @Composable 함수를 사용하여 UI를 선언적으로 정의합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;11:1-11:36&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시스템 설정:&lt;/b&gt; 앱의 화면 방향, 테마, 언어 등을 설정합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;12:1-13:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;이벤트 리스너 등록:&lt;/b&gt; 버튼 클릭, 터치 등의 이벤트에 대한 리스너를 등록합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;12:1-13:0&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;override fun onCreate(savedInstanceState: Bundle?) {
    // ...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;27:1-27:140&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;27:1-27:140&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;override 키워드는 부모 클래스(ComponentActivity)의 onCreate() 함수를 재정의한다는 의미입니다. 즉, MainActivity에서 onCreate() 함수를 재정의하여 앱의 초기화 작업을 수행하는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;27:1-27:140&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;29:1-29:46&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;super.onCreate() 왜 필요할까?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;31:1-31:119&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;super.onCreate()는 부모 클래스(ComponentActivity)의 onCreate() 함수를 호출하는 코드입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;31:1-31:119&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;왜 부모 클래스의 함수를 호출해야 할까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;31:1-31:119&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;33:1-33:133&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ComponentActivity의 onCreate() 함수는 액티비티의 생명주기 관리, 리소스 할당, UI 초기화 등 중요한 작업들을 수행합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;33:1-33:133&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이러한 작업들이 제대로 이루어지지 않으면 앱이 정상적으로 작동하지 않을 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;35:1-35:122&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;따라서 ComponentActivity의 onCreate() 함수를 재정의할 때는 반드시 super.onCreate()를 호출하여 부모 클래스의 초기화 작업을 수행해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;37:1-37:25&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-sourcepos=&quot;37:1-37:25&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;enableEdgeToEdge()&lt;/span&gt; 함수&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;39:1-39:84&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 이 함수는 이름 그대로 화면의 가장자리까지 UI를 확장하는 역할을 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;39:1-39:84&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;39:1-39:84&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;최신 Android 기기들은 화면의 베젤(테두리)이 거의 없이 화면 전체를 사용하는 경우가 많기때문에,&lt;/span&gt; enableEdgeToEdge() 함수는 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;최신 Android 기기의 화면을 최대한 활용하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;상태바, 내비게이션 바 영역까지 UI를 확장하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;역할을 합니다.&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;41:1-41:97&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;41:1-41:97&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;enableEdgeToEdge()는 &lt;/span&gt;최근에 기본적으로 MainActivity에 같이 포함되어진 함수로, 앱의 UI를 화면 가장자리까지 확장하여 더욱 몰입감 있는 사용자 경험을 제공하고싶다면 그대로 사용하시거나 원치않다면 제거해주시면 되겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;41:1-41:97&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;41:1-41:97&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-sourcepos=&quot;43:1-43:17&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;setContent&lt;/span&gt; 함수&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; setContent 함수는 Jetpack Compose에서 Activity 화면에 UI를 표시하기 위해 사용하는 핵심 함수입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 이 함수를 사용하면 앱의 UI를 Kotlin 코드로 간결하고 효율적으로 작성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;XML 레이아웃 파일 없이 Kotlin 코드만으로 Activity의 전체 UI를 Compose로 구성할 수 있는건 바로 이 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;setContent 덕분입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; setContent 함수는 ComponentActivity의 확장 함수로 제공되며, 내부적으로 Compose UI를 생성하고 관리하는 데 필요한 작업들을 수행합니다. 더 자세히 풀어보면, setContent는 Compose UI를 Activity에 연결하여 화면에 UI를 표시할 수 있도록해주며, 컴포저블 함수들을 호출하여 UI 트리를 생성하는 역할을 합니다. 이 UI 트리가 화면에 렌더링되어 우리 눈에 보이는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; setContent가 호출되어 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;UI 트리가 화면에 렌더링된 &lt;/span&gt;이후에는 State 변경(state.value) 등을 통해 UI를 업데이트하고 다시 그리는&amp;nbsp; 재구성(&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #333333; text-align: start;&quot;&gt;recomposition&lt;/span&gt;)이 발생합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;45:1-45:55&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-sourcepos=&quot;5:1-5:26&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;setContent 함수의 주요 기능&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;7:1-11:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;7:1-7:83&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;컴포저블 함수 호출&lt;/b&gt;: setContent 블록 안에는 @Composable 어노테이션이 붙은 컴포저블 함수들을 자유롭게 배치할 수 있습니다. setContent는 이러한 컴포저블 함수들을 호출하여 UI를 구성합니다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;7:1-7:83&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; &lt;b&gt;UI 트리 생성&lt;/b&gt;: setContent는 컴포저블 함수들을 호출하는 순서대로 UI 트리를 생성합니다. UI 트리는 화면에 표시될 UI 요소들의 계층 구조를 나타내며 각 컴포저블 함수는 UI 트리의 노드에 해당합니다. &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;setContent {
    BaseCodingTheme {
        Greeting(&quot;반갑습니다!&quot;)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-sourcepos=&quot;55:1-55:183&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;55:1-55:183&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위 코드에서는 BaseCodingTheme이라는 앱 테마를 적용하고, Greeting(&quot;반갑습니다!&quot;)라는 Composable 함수를 호출하여 &quot;반갑습니다!&quot;라는 텍스트 UI를 화면에 표시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;55:1-55:183&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;59:1-59:219&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/17</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-%EC%95%B1%EC%9D%98-%EC%8B%9C%EC%9E%91%EC%A0%90-MainActivity-%ED%81%B4%EB%9E%98%EC%8A%A4-%EB%B6%84%EC%84%9D#entry17comment</comments>
      <pubDate>Mon, 6 Jan 2025 12:23:27 +0900</pubDate>
    </item>
    <item>
      <title>[Jetpack Compose] Chapter1. 기초</title>
      <link>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter1-%EA%B8%B0%EC%B4%88</link>
      <description>&lt;h3 data-sourcepos=&quot;5:1-5:7&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;개요:&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-sourcepos=&quot;7:1-7:206&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Jetpack Compose는 Google에서 출시한 최신 네이티브 Android UI 툴킷입니다. Kotlin 언어 기반의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;선언형&lt;/b&gt;&lt;/span&gt; UI 프레임워크로, 기존의 명령형 XML 레이아웃 방식에서 벗어나 Kotlin 코드로 UI를 정의함으로써 더욱 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;직관적&lt;/span&gt;이고 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;효율적인 UI 개발 방식&lt;/span&gt;을 제시하며 Android 개발의 새로운 표준으로 자리 잡고 있습니다. 이 글에서는 Jetpack Compose의 핵심 개념, XML과의 차이점, 주요 장점, 그리고 간단한 예제를 통해 Jetpack Compose를 소개하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:206&quot; 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;style6&quot; /&gt;
&lt;h3 data-sourcepos=&quot;7:1-7:206&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;XML vs &lt;b&gt;Jetpack Compose:&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:233&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;안드로이드 UI 개발은 오랫동안 XML을 기반으로 이루어져 왔습니다. XML은 UI 레이아웃을 명확하게 정의할 수 있다는 장점이 있지만, 코드가 길어지고 복잡해지는 경향이 있었습니다. UI를 업데이트할 때마다 개발자가 변경부분을 직접 수정해야 하므로 번거롭고 오류가 발생하기 쉬워 유지보수가 어려우며,&amp;nbsp; XML은 각 레이아웃마다 별도의 XML 파일을 사용해야했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;3:1-3:233&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:232&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;반면, 최근에는 선언형 UI 모델이 업계 전반의 트렌드로 자리 잡으면서 Jetpack Compose가 등장했습니다. Compose는 UI를 Kotlin 코드로 직접 inline으로 작성하는 선언형 UI 방식을 통해 UI 개발을 혁신적으로 간소화해주고, 개발자는 UI의 현재 상태를 선언하기만 하면 Compose가 자동으로 UI를 업데이트해줍니다. 덕분에 코드가 간결해지고 유지보수가 쉬워졌으며, UI 업데이트 로직을 직접 작성할 필요가 없어 오류 발생 가능성도 줄어들었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;5:1-5:232&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:32&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Compose는 다음과 같은 장점들을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;9:1-13:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;9:1-9:59&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;간결하고 직관적인 코드:&lt;/b&gt; xml없이 간단한 Kotlin 코드만으로 UI를 작성하여 가독성을 높이고 코드량을 줄입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;10:1-10:47&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;쉬운 유지보수:&lt;/b&gt; 선언형 UI 방식을 통해 UI 변경 및 관리가 용이합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;11:1-11:51&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;향상된 성능:&lt;/b&gt; 최적화된 렌더링 엔진을 사용하여 XML보다 빠른 성능을 제공합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;12:1-13:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;강력한 기능:&lt;/b&gt; 애니메이션, Material Design 지원 등 다양한 기능을 제공합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉,&lt;/b&gt; Jetpack Compose는 선언형 UI 방식을 통해 안드로이드 UI 개발을 더욱 간결하고 효율적으로 만들어주는 새로운 프레임워크이며, 기존 주류로 사용되어왔던 XML에 비해 코드 작성, 유지보수, 성능 측면에서 많은 이점을 제공해줍니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;i&gt;&lt;b&gt;&lt;u&gt;&amp;lt;기존 명령형 프로그래밍 방식: &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;XML&lt;/span&gt; &lt;/span&gt;&amp;gt;&lt;/u&gt;&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735813553647&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; val textView: TextView = findViewById(R.id.textView)
        val button: Button = findViewById(R.id.button)

        button.setOnClickListener {
            textView.text = &quot;텍스트가 변경되었습니다!&quot;
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;&amp;lt;신규 선언형 프로그래밍 방식: &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Jetpack Compose&lt;/span&gt;&amp;gt; &lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;u&gt;&lt;b&gt;(&lt;/b&gt;&lt;/u&gt;&lt;u&gt;&lt;b&gt; UI 구성 &amp;amp; 인터렉션을 한번에!)&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735813637200&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var text by remember { mutableStateOf(&quot;안녕하세요&quot;) }

Text(text = text)
Button(onClick = { text = &quot;텍스트가 변경되었습니다!&quot; }) {
Text(&quot;텍스트 변경&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;위의 간단한 코드블럭 예제를 보더라도, Jetpack Compose로 넘어오면서 기본적인 코드량이 확실하게 감소되었음을 파악해볼 수 있습니다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; 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;style6&quot; /&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-sourcepos=&quot;7:1-7:206&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;키워드로 알아보는&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;이번 Chapter 중요 개념들:&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-sourcepos=&quot;5:1-5:32&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 선언형 UI&lt;/span&gt; (Declarative UI):&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;UI의 현재 상태를 선언적으로 기술하기만 하면 UI가 구성되는 방식.&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&lt;br /&gt;Compose는 이러한 선언을 기반으로 UI를 자동으로 그려줌.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-sourcepos=&quot;6:1-10:0&quot;&gt;
&lt;li data-sourcepos=&quot;7:1-7:47&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&quot;화면에 텍스트를 표시하고 싶다&quot; ➡️ &lt;b&gt;Text(text = &quot;안녕하세요&quot;)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;8:1-9:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&quot;버튼을 클릭하면 텍스트가 바뀌었으면 좋겠다&quot; ➡️ &lt;b&gt;Button(onClick = { /* 텍스트 변경 */ }) { Text(text = text) }&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&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;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-ke-style=&quot;style3&quot; data-sourcepos=&quot;5:1-5:32&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt; &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #222222; text-align: start;&quot;&gt;Composable&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; 함수&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; (&lt;b&gt;&lt;b&gt;&lt;b&gt;구성 가능한 함수&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; ):&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 앱의 UI를 구성하는 구성 요소이자 함수&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;(앱 화면이 하나의 요리라고 한다면, Composable 함수는 각각의 재료).&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;br /&gt;Jetpack Compose는 Kotlin 컴파일러를 사용하여 Composable 함수를 &lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;➡️ 앱의 UI요소로 변환.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;이는 마치 React Native 에서의 함수형 컴포넌트와 유사&lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;( &lt;span style=&quot;color: #ee2323;&quot;&gt;상태 관리 &amp;amp; 변경된 부분만을 다시 렌더링하여 UI 업데이트&lt;/span&gt; )&lt;br /&gt;&lt;br /&gt;✅ 함수를 구성 가능한 함수로 만드려면 &lt;span style=&quot;color: #ee2323; background-color: #9feec3;&quot;&gt;@Composable &lt;/span&gt;어노테이션을 함수의 맨 위에 추가해줘야함&lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;✅ Composable 함수는 Composable함수에서만 호출가능&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;✅ &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이 컴포저블 함수 선언으로 앱의 UI의 일부분인 UI 컴포넌트들을 쉽게 구성가능!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;6:1-10:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;7:1-7:47&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;ex) Compose UI 라이브러리에 정의된 텍스트를 화면에 표시해주는&amp;nbsp; &lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;Composable 함수&lt;/span&gt; Text()&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&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;blockquote style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot; data-sourcepos=&quot;5:1-5:32&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #222222;&quot;&gt;@Preview &lt;/span&gt;(&lt;/b&gt;&lt;/b&gt; &lt;b&gt;&lt;b&gt;&lt;b&gt;미리보기&lt;/b&gt;&lt;/b&gt;&lt;/b&gt; &lt;b&gt;&lt;b&gt;):&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;@preview 어노테이션을 사용하면, &lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;@preview가 달린 Composable 함수에서 생성한 UI요소를 앱 빌드전에 미리 확인해볼 수 있음&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;967&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TgszD/btsLDwyzyOr/AIXYnQ2acxajp1t4CvEUPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TgszD/btsLDwyzyOr/AIXYnQ2acxajp1t4CvEUPk/img.png&quot; data-alt=&quot;Android 스튜디오 내의 분할(디자인/코드) 보기에서의 미리보기 창&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TgszD/btsLDwyzyOr/AIXYnQ2acxajp1t4CvEUPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTgszD%2FbtsLDwyzyOr%2FAIXYnQ2acxajp1t4CvEUPk%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;478&quot; height=&quot;643&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;967&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Android 스튜디오 내의 분할(디자인/코드) 보기에서의 미리보기 창&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;이렇듯, @Preview 어노테이션이 붙은 Composable UI 구성요소들을 번거로운 에뮬레이터 및 빌드과정 없이 미리 확인 가능.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1735823757952&quot; class=&quot;kotlin&quot; style=&quot;color: #666666;&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    JetpackTheme {
        Greeting(&quot;안드로이드&quot;)

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #666666;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&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;blockquote style=&quot;background-color: #fcfcfc; text-align: left;&quot; data-ke-style=&quot;style3&quot; data-sourcepos=&quot;5:1-5:32&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style=&quot;color: #222222;&quot;&gt;Scaffold() &lt;/span&gt;&lt;b&gt;&lt;b&gt;:&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;앱 화면의 기본적인 틀을 잡아주는 역할을 하는 기본 Composable 함수.&lt;br /&gt;앱의 상단 바, 플로팅 버튼, 하단 바, 콘텐츠 영역 등, 앱 화면을 구성하는 주요 UI 요소들을 쉽게 배치하고 관리해줌.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p style=&quot;text-align: center;&quot; data-sourcepos=&quot;3:1-3:26&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&amp;lt;Scaffold가 제공하는 주요 구성 요소들&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;5:1-11:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;5:1-5:68&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;topBar:&lt;/b&gt;&lt;/span&gt; 앱의 상단에 위치하는 앱 바. 앱의 제목, 메뉴 등&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;6:1-6:67&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;bottomBar:&lt;/b&gt;&lt;/span&gt; 앱의 하단에 위치하는 앱 바. 탐색 버튼, 액션 버튼 등&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;7:1-7:69&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;floatingActionButton:&lt;/b&gt;&lt;/span&gt; 화면 위에 떠 있는 액션 버튼. 주요 액션을 수행하는 데 사용&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;10:1-11:0&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;content:&lt;/b&gt;&lt;/span&gt; 위 주요 요소들을 제외한, 개발자가 자유롭게 배치할 수 있는 앱의 주요 콘텐츠가 표시되는 영역.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;✅&lt;/span&gt; &lt;b&gt;&lt;span&gt;위의 구성 요소들은 &lt;/span&gt;&lt;b&gt;Scaffold의 매개변수로 설정 가능. (마지막 매개변수는 content 영역이며, 람다 type 입니다)&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;✅ &lt;b&gt;Scaffold 컴포저블의 마지막 매개변수는 content: @Composable (PaddingValues) -&amp;gt; Unit 으로, 람다 type 이기때문에 타 매개변수들과 구분하여 밖에 따로 작성해주는 것이 좋습니다. &lt;span style=&quot;color: #9d9d9d;&quot;&gt;( 코틀린 trailing lambda 문법 )&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;✅ &lt;b&gt;Text() 같은 화면에 문자열 표시와같은 단순한 컴퍼저블의 content 영역은 text라는 단일 문자열 매개변수 하나로만 구성되지만, Scaffold의 content 영역에는 여러 UI 구성요소 컴퍼저블들이 포함되기때문에 Scaffold는 content 영역을 람다식으로 받음&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;❗ &lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;❗&lt;/span&gt;&lt;/b&gt; 이전 버전에서는 Scaffold의 content 영역에 padding 값을 명시적으로 지정하지 않아도 되었지만, &lt;span style=&quot;color: #333333;&quot;&gt;compose 가 많은 변화를 거치면서 Scaffold의 content 영역에 padding values를 써주도록 변경되었습니다.&lt;br /&gt;이는 Scaffold의 content 영역에 배치되는 컴포저블들이 Scaffold 내부의 padding 값을 고려하여 배치되어야 하기 때문입니다.&amp;nbsp;&lt;br /&gt;예를 들어, topBar나 bottomBar가 화면의 일부 영역을 차지하기 때문에, content 영역에 padding을 적용시켜주지 않는다면 content 영역의 컴포저블들이 이들과 겹쳐 화면에 보이지 않게됩니다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #ffffff; text-align: start;&quot;&gt;그럼에도 불구하고 Scaffold&lt;/span&gt; 를 사용하면서 padding을 적용시키고 싶지않은 경우에는 &lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #ffffff; text-align: start;&quot;&gt;Scaffold 상단에&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@SuppressLint(&quot;UnusedMaterial3ScaffoldPaddingParameter&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위와 같은 어노테이션을 작성해주면 됩니다.&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p data-sourcepos=&quot;9:1-9:98&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #666666;&quot;&gt;&lt;b&gt;하지만 이 방법은 권장하지 않습니다. padding 값을 무시하면 content 영역의 컴포저블들이 TopAppBar나 BottomAppBar와 겹쳐 보일 수 있기 때문입니다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;11:1-11:164&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;따라서 Scaffold를 사용할 때는 content 영역에 innerPadding 매개변수를 명시적으로 전달하고, Modifier.padding(innerPadding)을 사용하여 컴포저블에 padding을 적용하는 것이 좋습니다. 이렇게 하면 컴포저블들이 화면에 정상적으로 표시됩니다&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fcfcfc; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p style=&quot;text-align: center;&quot; data-sourcepos=&quot;3:1-3:26&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #9feec3;&quot;&gt;&lt;b&gt;&amp;lt;간단한 Scaffold 사용 예시&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;Scaffold(
//플로팅 버튼
    floatingActionButtonPosition = FabPosition.End,
    floatingActionButton = {
    FloatingActionButton(onClick = { } , shape = CircleShape, containerColor = Color.Yellow) {

        Text(&quot;클릭&quot;)
}},
//상단 바
    topBar = {
        TopAppBar(
            title = { Text(&quot;WJ's Android App&quot;) },
            colors = TopAppBarDefaults.topAppBarColors(
                containerColor = Color(0xFFF25287),
            )
        )
    },
//하단 바
    bottomBar = {
        BottomAppBar(
            contentColor = Color.Red,
            containerColor = Color(0xFF00FF00),

        ) {
            Text(&quot;BottomAppBar&quot;)
            IconButton(onClick = {}) {
                Icon(Icons.Default.Favorite, contentDescription = &quot;Favorite&quot;)
            }
        }
    },


) 
// content 영역
{
  // Scaffold의 content 영역에 innerPadding 적용
        // Compose 업데이트 이후, Scaffold의 content 영역에 padding values를 써주도록 변경되었음.
        // Scaffold의 content 영역에 배치되는 컴포저블들은 Scaffold 내부의 padding 값을 고려하여 배치되어야 함.
        // Scaffold의 content 람다식의 유일한 하나의 매개변수인 innerPadding은, 탑 바, 하단 바 등을 고려하여 자동으로 계산된 패딩 값임.
        // 즉 Scaffold는 content 람다식에 PaddingValues 타입의 매개변수를 전달하여, 앱 바, 하단 탐색 바 등의 크기를 고려한 패딩 값을 제공해주는 것인데,
        // 왜 자동으로 제공하느냐? -&amp;gt; 상단 바, 하단 바 등 앱 기본 UI요소들 때문에 content에 정의한 컴포저블 UI요소들이 하단 바 등등에 가려지기 때문에
        // 가려지지않고 올바르게 배치될 수 있도록 compose 프레임워크에서 적절히 padding 값을 자동으로 계산하여 넘겨주는 것.
        // 즉, PaddingValues 타입 매개변수인 innerPadding을 적용해야 하단바, 상단바 등등의 요소들과 겹치지 않게돠어 화면에 보임.
            innerPadding -&amp;gt; MyComposableView(innerPadding) // innerPadding을 MyComposableView에 전달
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #666666;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&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;blockquote style=&quot;background-color: #fcfcfc; text-align: left;&quot; data-sourcepos=&quot;5:1-5:32&quot; data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;span style=&quot;background-color: #f6e199; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style=&quot;color: #222222;&quot;&gt;표준 레이아웃 구성요소(&lt;span style=&quot;color: #ee2323;&quot;&gt;Column, Row, Box&lt;/span&gt;) &lt;/span&gt;&lt;b&gt;&lt;b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&amp;nbsp;Composable&lt;span style=&quot;background-color: #ffffff; color: #202124; text-align: start;&quot;&gt; 함수는 여러 UI 요소를 내보낼 수 있습니다. 하지만, 그 &lt;span style=&quot;background-color: #ffffff; color: #202124; text-align: start;&quot;&gt;UI 요소들을 어떻게 배치해야 하는지에 대한 가이드를 제공하지 않으면 UI 요소들이 뒤죽박죽 겹쳐서 그려지는 등 원치않는 구성으로 배치되어질 것 입니다. &lt;br /&gt;이를 위해, &lt;span style=&quot;background-color: #ffffff; color: #202124; text-align: start;&quot;&gt;Compose는 UI 요소를 배치하는 데 도움을 주는 표준 레이아웃 컬렉션을 제공해줍니다.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-sourcepos=&quot;5:1-11:0&quot;&gt;
&lt;li data-sourcepos=&quot;5:1-5:68&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Column&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;:&lt;/b&gt;&lt;span&gt; UI 요소들을 수직으로 배치&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;a href=&quot;https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter4-Column-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5&quot;&gt; 관련 게시물&lt;/a&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;6:1-6:67&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Row&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;/b&gt;&lt;span&gt; UI 요소들을 수평으로 배치&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter3-Row-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; 관련 게시물&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-sourcepos=&quot;7:1-7:69&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #222222;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Box&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;/b&gt;&lt;span&gt; UI 요소들을 겹쳐서 배치&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter5-Box-Layout-%EA%B0%9C%EB%85%90-%ED%99%9C%EC%9A%A9-%EC%8B%A4%EC%8A%B5&quot;&gt; 관련 게시물&lt;/a&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rY66R/btsLBWyL6SZ/GxgC3zdYO8TQMZgslCVzv1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rY66R/btsLBWyL6SZ/GxgC3zdYO8TQMZgslCVzv1/img.jpg&quot; data-alt=&quot;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rY66R/btsLBWyL6SZ/GxgC3zdYO8TQMZgslCVzv1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrY66R%2FbtsLBWyL6SZ%2FGxgC3zdYO8TQMZgslCVzv1%2Fimg.jpg&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;744&quot; height=&quot;344&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://developer.android.com/develop/ui/compose/layouts/basics?hl=ko&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-sourcepos=&quot;5:1-11:0&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;7:1-7:69&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; Modifier &lt;/span&gt;: &lt;span style=&quot;color: #666666;&quot;&gt;Modifier는 레이아웃을 비롯한 UI요소들의 크기, 위치, 정렬, 패딩,효과 등을 조정하는 데 사용하는 조정자.&lt;br /&gt;&lt;br /&gt;✅ Jetpack Compose의 모든 컴포저블은&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; modifier&lt;/span&gt; 매개변수&lt;/span&gt;를 가지고 있으며, modifier는 컴포저블의 크기, 위치, 정렬, 배경, 패딩, 클릭 이벤트 처리 등 다양한 속성을 변경하는 데 사용됨. &lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;✅&lt;/span&gt;&lt;/b&gt; modifier 매개변수는 항상 컴포저블 함수의 첫 번째 선택적 매개변수인 것이 특징&amp;nbsp;&lt;br /&gt;&lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;✅&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;Modifier는 .(점)연산자를 사용하여 체이닝(chaining)을 통해 여러 수정자를 연결하여 사용할 수 있음&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&amp;lt; &lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;Modifier&lt;/span&gt;&lt;/b&gt; 일부 속성들 및 간단한 사용예시&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #202124; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #666666;&quot;&gt;clickable: 컴포저블이 사용자 입력에 반응하도록 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #666666;&quot;&gt;padding: 요소 내부에 여백공간 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #666666;&quot;&gt;fillMaxWidth: 컴포저블이 상위 요소로부터 부여받은 최대 너비를 채우도록 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR'; color: #666666;&quot;&gt;background(): 요소의&amp;nbsp; 배경 색상 설정&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1735943520435&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Text(
    text = &quot;Hello&quot;,
    modifier = Modifier
        .padding(16.dp)
        .background(Color.Blue)
)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #fcfcfc; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc; color: #666666; text-align: left;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot; data-sourcepos=&quot;3:1-3:26&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR'; background-color: #9feec3;&quot;&gt;&lt;b&gt;&amp;lt;간단한 레이아웃 사용 예시&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;android_compose_layout_basics_6-code-sample&quot; class=&quot;kotlin&quot; style=&quot;color: #000000; text-align: left;&quot; data-copy-event-label=&quot;android_compose_layout_basics_6-LayoutBasicsSnippets&quot; data-region-tag=&quot;android_compose_layout_basics_6&quot; data-github-path=&quot;android/snippets/compose/snippets/src/main/java/com/example/compose/snippets/layouts/LayoutBasicsSnippets.kt&quot; data-code-snippet=&quot;true&quot; data-scope=&quot;android_compose_layout_basics_6&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;@Composable
fun LayoutSample() {
    Column(){
        Text(
           //...
        )
    }

    Row{
        Text(
            //...
        )
    }

    Box(
        modifier = Modifier
            .clickable(onClick = { /* 클릭 이벤트 처리 */ })
            .padding(16.dp)
            .fillMaxWidth()
    ) {
        Image(
           //...
        )
        Text(
            //...
        )
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #666666;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;참고 자료 및 같이 참고하면 좋은 자료들:&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;17:1-17:158&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://developer.android.com/develop/ui/compose/tutorial?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.android.com/develop/ui/compose/tutorial?hl=ko&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1735926993630&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Android Compose 튜토리얼 &amp;nbsp;|&amp;nbsp; Jetpack Compose &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose는 네이티브 Android UI를 빌드하기 위한 최신&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/develop/ui/compose/tutorial?hl=ko&quot; data-og-url=&quot;https://developer.android.com/develop/ui/compose/tutorial?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dGcuWz/hyXWnI8EMh/Q51pbrID6NhuMZHk0OGnEK/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676,https://scrap.kakaocdn.net/dn/eaWWpG/hyXWxZix9j/YK5YfGtwciCnvkObrBsEa0/img.png?width=2668&amp;amp;height=1922&amp;amp;face=0_0_2668_1922,https://scrap.kakaocdn.net/dn/sIh2s/hyXWAItUVO/cfrs1IsX9EvzSuo4dCuB80/img.png?width=1176&amp;amp;height=2360&amp;amp;face=0_0_1176_2360&quot;&gt;&lt;a href=&quot;https://developer.android.com/develop/ui/compose/tutorial?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/develop/ui/compose/tutorial?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dGcuWz/hyXWnI8EMh/Q51pbrID6NhuMZHk0OGnEK/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676,https://scrap.kakaocdn.net/dn/eaWWpG/hyXWxZix9j/YK5YfGtwciCnvkObrBsEa0/img.png?width=2668&amp;amp;height=1922&amp;amp;face=0_0_2668_1922,https://scrap.kakaocdn.net/dn/sIh2s/hyXWAItUVO/cfrs1IsX9EvzSuo4dCuB80/img.png?width=1176&amp;amp;height=2360&amp;amp;face=0_0_1176_2360');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Android Compose 튜토리얼 &amp;nbsp;|&amp;nbsp; Jetpack Compose &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지는 Cloud Translation API를 통해 번역되었습니다. 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose는 네이티브 Android UI를 빌드하기 위한 최신&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;33:1-33:311&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;a href=&quot;https://youtu.be/BX0rQvYgf1I?si=hFUGvW9DRHZ3G21c&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/BX0rQvYgf1I?si=hFUGvW9DRHZ3G21c&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignLeft&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=BX0rQvYgf1I&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cfC2Rp/hyXWAuW71Q/tj5OdOfwTig1q797WmQxq1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=944_216_1068_352,https://scrap.kakaocdn.net/dn/bXDJWn/hyXWqskGMV/Qghc6UWKmZSzk5hbi79hP0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=944_216_1068_352&quot; data-video-width=&quot;350&quot; data-video-height=&quot;197&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;배달의민족에 Jetpack Compose 적용을 시도해보았다 #우아콘2021 #첫째날_배민비하인드&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/BX0rQvYgf1I&quot; width=&quot;350&quot; height=&quot;197&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/1apENzDbtCQ?si=QkTOpsGhfx-gs3E9&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/1apENzDbtCQ?si=QkTOpsGhfx-gs3E9&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignLeft&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=1apENzDbtCQ&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/syQCp/hyXWxZiyku/Uy3y9maMZuR2yNalmvH7B0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=172_324_394_566,https://scrap.kakaocdn.net/dn/qCUaB/hyXWw0oljt/04cKoOTXTeKvqx4JkGZLV1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=172_324_394_566&quot; data-video-width=&quot;350&quot; data-video-height=&quot;197&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;취준생을 위한 안드로이드 앱만들기 콤포즈UI 기본개념 JetPack Compose - Android Kotlin jetpack Tutorial (202&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/1apENzDbtCQ&quot; width=&quot;350&quot; height=&quot;197&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-sourcepos=&quot;7:1-7:206&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>jetpack compose</category>
      <category>안드로이드</category>
      <category>제트팩 컴포즈</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/16</guid>
      <comments>https://basecoding.tistory.com/entry/Jetpack-Compose-Chapter1-%EA%B8%B0%EC%B4%88#entry16comment</comments>
      <pubDate>Thu, 2 Jan 2025 22:24:24 +0900</pubDate>
    </item>
    <item>
      <title>[디자인 패턴] 옵서버(Observer) 패턴 - 예제를 통해 알아보기</title>
      <link>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%98%B5%EC%84%9C%EB%B2%84Observer-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;h1&gt;Observer Pattern&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Observer(옵서버) 패턴이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성적 출력 예제를 통해 알아보는 Observer Pattern&lt;/h2&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러가지 출력방식을 구현하기에 앞서, 목록형태로만 출력되도록 일단 구현해보자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;ScoredRecord 클래스: 성적정보들을 저장/관리하는 클래스&lt;/li&gt;
&lt;li&gt;DataSheetView클래스: 성적을 목록형태로 출력하는 클래스&lt;/li&gt;
&lt;/ul&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;div align=&quot;center&quot;&gt;이 성적정보 출력 프로그램을 설계하면 아래와 같다.&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt;기존 설계&amp;gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/be3f9a48-fda4-42de-926e-802919389281&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class ScoredRecord {
    private DataSheetView dataSheetView;
    private List&amp;lt;Integer&amp;gt; scores = new ArrayList&amp;lt;Integer&amp;gt;();

    public void setDataSheetView(DataSheetView dataSheetView) {
        this.dataSheetView = dataSheetView;
    }

    public void addScore(int score) {
        scores.add(score);
        dataSheetView.update(); //출력 클래스에게 성적 정보 변경 통지.
    }

    public List&amp;lt;Integer&amp;gt; getScoreRecord() {
        return scores;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.util.List;

public class DataSheetView {
    private ScoredRecord scoredRecord;
    private int viewCount;

    public DataSheetView(ScoredRecord scoredRecord, int viewCount) {
        this.scoredRecord = scoredRecord;
        this.viewCount = viewCount;
    }

    public void update() {
        List&amp;lt;Integer&amp;gt; record=scoredRecord.getScoreRecord();
        displaySCores(record, viewCount);
    }

    private void displaySCores(List&amp;lt;Integer&amp;gt; record, int viewCount) {
        System.out.println(&quot;List of &quot;+ viewCount + &quot; entries&quot;);
        for(int i=0; i&amp;lt;viewCount &amp;amp;&amp;amp; i&amp;lt; record.size(); i++) {
            System.out.println(record.get(i));
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;axapta&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        ScoredRecord scoredRecord = new ScoredRecord();
        DataSheetView dataSheetView = new DataSheetView(scoredRecord, 3);
        scoredRecord.setDataSheetView(dataSheetView);

        for(int index=1; index &amp;lt;= 5; index++) {
            int score= index*10;
            System.out.println(&quot;Adding &quot;+score);
            scoredRecord.addScore(score);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt;기존 설계에 추가 요구사항 적용&amp;gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;요구사항1&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;현재 프로그램은, 성적정보를 특정 갯수만큼 목록형태로 출력해주고있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 만약 리스트형식으로 출력해주지않고, 다른 방식으로 성적을 출력하도록 변경하고싶다면, 예를 들어 성적정보들 중 최소/최대값만을 출력해주는 방식으로 변경하려면 코드에 어떤 영향을 주게되는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;요구사항2&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;뿐만 아니라 성적을 동시에 여러 가지 형태로 출력하려면 어떤 변경작업을 해야하는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 기존처럼 목록형태로도 출력시키고 + 최소/최대값 형태로도 출력시키고자한다면 어떻게 해야하는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;요구사항3&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;프로그램을 실행시에 성적 출력방식이 변경되도록한다면 어떤 변경작업을 해야하는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 처음에는 기존처럼 목록형태로 출력하고, 나중에 실행중에 최소/최대값 형태로 출력하고자 한다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/b897b82a-777c-4918-92cc-379040bee67f&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;요구사항에 맞게 변경된 ScoredRecord클래스 코드&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class ScoredRecord {
    private MinMaxView minMaxView;
    private List&amp;lt;DataSheetView&amp;gt; dataSheetViews = new ArrayList&amp;lt;DataSheetView&amp;gt;();
    private List&amp;lt;Integer&amp;gt; scores = new ArrayList&amp;lt;Integer&amp;gt;();

    public void setMinMaxView(MinMaxView minMaxView) {
        this.minMaxView=minMaxView;
    }

    public void addScore(int score) {
        scores.add(score);
        minMaxView.update();

        for(DataSheetView dataSheetView : dataSheetViews)
            dataSheetView.update();
    }

    public void addDataSheetView(DataSheetView dataSheetView) {
        dataSheetViews.add(dataSheetView);
    }

    public List&amp;lt;Integer&amp;gt; getScoreRecord() {
        return scores;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        ScoredRecord scoredRecord = new ScoredRecord();
        MinMaxView minMaxView = new MinMaxView(scoredRecord);
        DataSheetView dataSheetView3 = new DataSheetView(scoredRecord, 3);
        DataSheetView dataSheetView5 = new DataSheetView(scoredRecord, 5);

        scoredRecord.setMinMaxView(minMaxView);
        scoredRecord.addDataSheetView(dataSheetView3);
        scoredRecord.addDataSheetView(dataSheetView5);

        for(int index=1; index &amp;lt;= 5; index++) {
            int score= index*10;
            System.out.println(&quot;Adding &quot;+score);
            scoredRecord.addScore(score);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;기존설계의 문제점&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 요구사항들을 만족시키도록 변경할 경우, 성적 정보 관리 클래스인 ScoreRecord를 상당히 많은부분 변경해줘야하는 OCP 위반 발생.&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;어느순간에는 성적정보를 리스트형태로 보여주다가 어떤 때에는 최소/최대값만 보여주도록 하고싶은 경우라면 ScoreRecord 코드 변경을 해줘야할 것이고, 동시에 여러 형태로 성적정보를 보여주고 싶은 경우에도 코드 변경은 불가피하다.&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;또한, 성적정보들의 평균값도 출력해보고싶어서 AverageView를 정의한 경우에도 setAverageView 필드추가해주고..&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;setAverageView 메서드 추가해주고.. 기존 ScoreRecord 클래스의 코드에 추가해줘야하는 문제가 발생한다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;새로운 형식으로 성적정보를 출력 or 기존의 형식을 다른 형식으로 바꾸어 출력 or 성적을 동시에 여러 가지 형태로 출력&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;&lt;code&gt;=&amp;gt; ScoreRecord 클래스의 변경이 요구됨&lt;/code&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;이 OCP 위반문제를 해결해보자.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설계 개선(by Strategy 패턴 응용)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ScoreRecord 클래스를 변경하지않고 성적 출력방식을 변경 및 추가하도록해보자.&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;새로운 출력형식이 추가되어도 기존의 ScoreRecord 클래스는 변경되지않도록하는 설계.&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;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;설계 단계&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;무엇이 변화가 되는가? =&amp;gt; 성적정보를 출력-표현하는 방식이 변한다, 성적 정보를 목록형식으로 출력했다가.. 최대값 최소값으로 출력했다가.. 평균값으로도 출력했다가... 즉 구체적인 View 클래스들(DataSheetView, MinMaxView...)&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; &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; &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; &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; &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; &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; &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;/li&gt;
&lt;li&gt;그 변화되는 성적정보를 출력방식들을 하위 개념으로 둔다. 그 하위 클래스들의 포괄개념은, &lt;b&gt;성적 정보를 관찰하고있다가 변경사항이 생기면 성적정보를 가져다가 현재 출력 방식에 맞게 출력하도록하는 관찰자&lt;/b&gt;, 즉 &lt;b&gt;&lt;code&gt;Observer&lt;/code&gt;&lt;/b&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;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; &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; &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; &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; &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; &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; &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; &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; &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; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/li&gt;
&lt;li&gt;관찰자 Observer가 관찰하는 대상인, 성적정보 데이터를 관리하는 SCoreRecord 클래스. &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; &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; &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; &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; &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; &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; &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; &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; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/li&gt;
&lt;li&gt;Observer는 성적 정보들을 동시에 다른 형식으로 출력해준다. so, Strategy패턴과는 다르게, 한 데이터를 여러 다양한 형식으로 출력할 수 있게끔 SCoreRecord 클래스와 Observer는 다중성 * 연관관계를 가진다. 즉, 기존처럼 구체적인 View 객체들과 직접 연관관계를 맺는것이 아닌, 포괄개념인 Observer들과 연관관계를 맺도록 변경한다. &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; &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; &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; &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; &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; &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; &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; &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; &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; &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; &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; &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; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/li&gt;
&lt;li&gt;그리고, 성적 정보들을 출력해주는 클래스들은 성적 정보가 변했는지를 SCoreRecord로부터 통지받아야하기때문에, 성적 정보의 변경을 통지해주는 update() 메서드. 성적 정보가 업데이트되었으면 해당 최신정보를 출력해야 해야하기때문이다.(자기들만의 형식으로) &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; &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; &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; &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; &amp;nbsp; &amp;nbsp; &lt;br /&gt;단, 각 출력 형식 클래스들은 SCoreRecord로부터 직접 최신 성적 데이터를 받아오기떄문에 SCoreRecord와 직접 연관관계를 맺는다. &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; &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; &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; &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; &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; &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; &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; &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; &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; &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; &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; &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; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/li&gt;
&lt;li&gt;이제 여기에 성적 정보들을 정렬하여 출력해주는 SortView 클래스를 추가해보자. 이제는 새로운 출력 방식을 추가해도 OCP 원칙에 만족하는 것을 확인해볼 수 있을 것이다.&lt;/li&gt;
&lt;/ol&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;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;lt;개선된 설계&amp;gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/a959926b-5935-4a2b-b0e9-4f469c41b2cd&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public interface Observer {
    public void update();
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.util.List;

public class DataSheetView implements Observer{
    private ScoredRecord scoredRecord;
    private int viewCount;

    public DataSheetView(ScoredRecord scoredRecord, int viewCount) {
        this.scoredRecord = scoredRecord;
        this.viewCount = viewCount;
    }

    public void update() {
        List&amp;lt;Integer&amp;gt; record=scoredRecord.getScoreRecord();
        displaySCores(record, viewCount);
    }

    private void displaySCores(List&amp;lt;Integer&amp;gt; record, int viewCount) {
        System.out.println(&quot;List of &quot;+ viewCount + &quot; entries&quot;);
        for(int i=0; i&amp;lt;viewCount &amp;amp;&amp;amp; i&amp;lt; record.size(); i++) {
            System.out.println(record.get(i));
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.util.Collections;
import java.util.List;

public class MinMaxView implements Observer{
    private  ScoredRecord scoredRecord;

    public MinMaxView(ScoredRecord scoredRecord){
        this.scoredRecord=scoredRecord;
    }

    public void update(){
        List&amp;lt;Integer&amp;gt; record=scoredRecord.getScoreRecord();
        displayScores(record);
    }

    private void displayScores(List&amp;lt;Integer&amp;gt; record) {
        int min= Collections.min(record);
        int max= Collections.max(record);

        System.out.println(&quot;Min&quot; + min + &quot; Max &quot;+max);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;import java.util.Collections;
import java.util.List;

public class SortView implements Observer{
    private  ScoredRecord scoredRecord;

    public SortView(ScoredRecord scoredRecord){
        this.scoredRecord=scoredRecord;
    }

    public void update(){
        List&amp;lt;Integer&amp;gt; record=scoredRecord.getScoreRecord();
        displayScores(record);
    }

    private void displayScores(List&amp;lt;Integer&amp;gt; record) {
        System.out.println(&quot;Sorted View&quot;);
        Collections.sort(record);

        for(Integer score: record)
            System.out.println(score);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class ScoredRecord {
    private List&amp;lt;Observer&amp;gt; observers = new ArrayList&amp;lt;Observer&amp;gt;(); //Observer 여러개와 * 연관관계.

    public void attach(Observer observer){
        observers.add(observer);
    }

    public void detach(Observer observer){
        observers.remove(observer);
    }

    private List &amp;lt;Integer&amp;gt; scores = new ArrayList&amp;lt;Integer&amp;gt;();

    public void addScore(int score) {
        scores.add(score);

        for(Observer observer: observers)
            observer.update();
    }

    public List&amp;lt;Integer&amp;gt; getScoreRecord() {
        return scores;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.util.Random;

public class Main {
    public static void main(String[] args) {
        ScoredRecord scoredRecord = new ScoredRecord();
        Observer minMaxView = new MinMaxView(scoredRecord);
        Observer dataSheetView3 = new DataSheetView(scoredRecord, 3);
        Observer dataSheetView5 = new DataSheetView(scoredRecord, 5);

        scoredRecord.attach(minMaxView);
        scoredRecord.attach(dataSheetView3);
        scoredRecord.attach(dataSheetView5);

        Observer sortedView = new SortView(scoredRecord);
        scoredRecord.attach(sortedView); //옵서버로 등록.

        Random random = new Random();

        for(int index=1; index &amp;lt;= 5; index++) {
            int score= random.nextInt(101);
            System.out.println(&quot;Adding &quot;+score);
            scoredRecord.addScore(score);
        }
    }
}&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;자 이제 동시에 여러 출력방식으로 출력해도 + 새롭게 SortView 출력방식이 추가되어도&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;code&gt;기존 ScoredRecord코드는 변경되지 않는다.&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&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;
&lt;h2 style=&quot;color: #000000; text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;lt;성적정보 프로그램 개선: 최종 설계&amp;gt;&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&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 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 ScoreRecord 클래스를 보면, ScoreRecord 클래스가 관리하는 성적정보들에 변경이 있나없나 관찰하고있는 Observer들이 있는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그 Observer들을 등록시켜주는 attach(), Observer들을 제거시켜주는 detach(), 새로운 성적정보가 추가되어 성적정보에 변경이 생겼음을 자신을 관찰하고있는 Observer들에게 알려주는 update() 호출 등등 이러한 &lt;code&gt;Observer들을 관리하는 기능들&lt;/code&gt;이 현재 ScoreRecord에 존재하고있다.&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;그런데 이러한 Observer들을 관리하는 기능들은 ScoreRecord클래스만 쓸 수 있는게 아니라, 그 다른 어떤 성적을 관리하는 클래스에서도 위와같은 기능들이 필요할 것이다.&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;so, 특정 ScoreRecord 클래스에서만 해당 기능들을 제공하는 것 보단, 성적데이터를 관리하는 다른 클래스에서도 기능들을 쓸 수 있도록 설계를 개선해보자.&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;Observer들을 관리하는 기능들을 보유하고있는 별도의 Subject 클래스를 모델링하고, 성적데이터를 관리하는 클래스들이 이 Subject클래스를 상속받아서 가져다쓰도록하면 될 것이다.&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;이제 ScoreRecord클래스가 아니라, ScoreRecord클래스가 상속받는 포괄개념인 Subject 클래스가 Observer들을 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/3c6e098e-335b-4a96-939f-64c2a070761a&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class Subject {
    private List&amp;lt;Observer&amp;gt; observers = new ArrayList&amp;lt;Observer&amp;gt;(); //Observer 여러개와 * 연관관계.

    public void attach(Observer observer){
        observers.add(observer);
    }

    public void detach(Observer observer){
        observers.remove(observer);
    }

    protected void notifyObservers(){ //Observer들에게 성적정보 변경사항을 알림.
        for(Observer observer: observers)
            observer.update();
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;import java.util.ArrayList;
import java.util.List;

public class ScoredRecord extends Subject{

    private List &amp;lt;Integer&amp;gt; scores = new ArrayList&amp;lt;Integer&amp;gt;();

    public void addScore(int score) {
        scores.add(score);
        notifyObservers();
    }

    public List&amp;lt;Integer&amp;gt; getScoreRecord() {
        return scores;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;EX)&lt;/h4&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/ef67ea5a-fc7f-4e6a-8a72-f841c0c3f9ed&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&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;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;옵서버 패턴은 통보 대상 객체의 관리를 Subject 클래스와 Observer 인터페이스로 일반화한다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그러면 데이터 변경을 통보하는 클래스(ConcreteSubject)는 통보 대상 클래스/객체(ConcreteObserver)에 대한 의존성을 제거할 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과적으로 옵서버 패턴은 통보 대상 클래스나 대상 객체의 변경에도 ConcreteSubject 클래스를 수정없이 그대로 사용 할 수 있도록한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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 data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;ConcreteSubject 클래스&lt;/code&gt;인 -&amp;gt; scoredRecord 클래스가 관리하는 성적정보에 변경이 생겼으면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상대 클래스인 DataSheetView or MinMaxView 와 같은 &lt;code&gt;ConcreteObserver 클래스&lt;/code&gt;들에게 데이터의 변경을 통지해야하는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 해당 &lt;b&gt;상대클래스에게 의존하지 않으면서 데이터의 변경을 통지하고자하는 경우 Observer(옵서버) 패턴을 사용&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;lt;커맨드 패턴의 일반적인 설계구조&amp;gt;&lt;/h2&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;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/082b2acc-6559-4dad-9f8c-8d9384266c75&quot; /&gt;&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처: Java객체지향 디자인패턴(한빛미디어)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;code&gt;Subject 클래스&lt;/code&gt;: ConcreteObserver 객체를 관리하는 클래스&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;code&gt;Observer 인터페이스&lt;/code&gt;: 데이터의 변경을 통보 받는 인터페이스&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;code&gt;ConcreteSubject 클래스&lt;/code&gt;: 변경 관리 대상이되는 데이터(ex 성적정보)가 있는 클래스&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;code&gt;ConcreteObserver 클래스&lt;/code&gt;: ConcreteSubject로부터 변경을 통보 받는 클래스&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>디자인 패턴</category>
      <category>Observer Pattern</category>
      <category>디자인 패턴</category>
      <category>옵서버 패턴</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/15</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%98%B5%EC%84%9C%EB%B2%84Observer-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry15comment</comments>
      <pubDate>Sun, 20 Oct 2024 00:56:52 +0900</pubDate>
    </item>
    <item>
      <title>[디자인 패턴] 빌더(Builder) 패턴 - 예제를 통해 알아보기</title>
      <link>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EB%B9%8C%EB%8D%94Builder-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;h1&gt;Builder Pattern&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Builder(빌더) 패턴이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;code&gt;필수적 인자&lt;/code&gt;들과 + 재공하지않아도되는 &lt;code&gt;선택적 인자&lt;/code&gt;가 혼합되어 있는 경우에 유용하게 사용되는 생성형 디자인패턴&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;Immutable 객체(변경할 수 없는 객체)를 생성하고 싶은 경우에 사용. 객체가 생성된 이후 수정이 불가능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt;책 클래스에 대한 객체생성 예제를 통해 알아보는 Builder Pattern&amp;gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Book{
    private Long id; //필수적인 속성
       private String isbn; //필수적인 속성
       private String title; //선택적인 속성
       private String author; //선택적인 속성
       private int pages; //선택적인 속성
       private String category; //선택적인 속성
}&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt;Telescoping Constructor패턴&amp;gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 점층적 생성자 패턴 ]&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Telescope= 망원경, 망원경은 렌즈를 점층적으로 쌓은 형태.&lt;br /&gt;so, 이와 비슷하게 생성자를 점점 추가하면서 속성정보를 설정하여 객체를 생성시키는 Telescoping Constructor패턴&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&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;i&gt;Telescoping&lt;/i&gt; &lt;i&gt;Constructor&lt;/i&gt; 패턴은 필수 인자를 받는 생성자를 정의한 후에 선택적 인자를 추가로 받는 생성자를 계속해서 정의하는 형식이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;코드를 통해 Telescoping Constructor패턴을 이해해보자.&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Book{
    private Long id; //필수적인 속성
    private String isbn; //필수적인 속성
    private String title; //선택적인 속성
    private String author; //선택적인 속성
    private int pages; //선택적인 속성
    private String category; //선택적인 속성

    public Book(String isbn, Long id) {
        this.isbn = isbn;
        this.id = id;
    }
}&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;위와같이 필수적인 속성인 책의 isbn과 id 값을 인자로 받는 생성자를 정의한 후에&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;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;    public Book( Long id, String isbn, String title) {
        this.id = id;
        this.isbn = isbn;
        this.title = title;
    }

    public Book(Long id, String isbn, String title, String author) {
        this.id = id;
        this.isbn = isbn;
        this.title = title;
        this.author = author;
    }

    public Book(Long id, String isbn, String title, String author, int pages) {
        this.id = id;
        this.isbn = isbn;
        this.title = title;
        this.author = author;
        this.pages = pages;
    }

    public Book(Long id, String isbn, String title, String author, int pages, String category) {
        this.id = id;
        this.isbn = isbn;
        this.title = title;
        this.author = author;
        this.pages = pages;
        this.category = category;
    }&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;필수적 정보인 id, isbn 만을 인자로받는 생성자와 더불어서, 계속해서 선택적 인자를 하나씩 추가하면서 생성자를 정의하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&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;code&gt;Telescoping Constructor패턴&lt;/code&gt; 즉, &lt;code&gt;점층적 생성자 패턴&lt;/code&gt;이라고 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Telescoping Constructor패턴의 문제점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인자의 갯수에 따라 생성자의 갯수도 많이지게 된다.&lt;/li&gt;
&lt;li&gt;인자의 갯수가 많이짐에따라 각 인자의 의미를 알기가 어려워지고 가독성이 떨어지게된다.&lt;/li&gt;
&lt;li&gt;인자가 같은 타입인 경우에는 해당 인자들을 구분하기어려워 잘못기입하는 경우도 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;title 인자 위치에 author 인자를 작성한다던지..&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또한, 사용하지않는 불필요한 인자가 있을때는 일일히 null 및 0값으로 지정해줘야하는 번거로움이있다 .&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;title 이나 author 속성은 필요없는 경우, 해당 인자들을 null로 작성해줘야함.&lt;/blockquote&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;이러한 Telescoping Constructor패턴의 문제점을 다소 해결하기위한 접근 방법으로 &lt;code&gt;JavaBeans 패턴&lt;/code&gt;이 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt;JavaBeans 패턴&amp;gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;: Setter 메서드로 각 속성의 값을 설정하는 패턴이자 방법.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 속성에 대한 setter 메서드로 각 속성값을 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;  public Book(Long id, String isbn) {this.id=id; this.isbn=isbn;}
   public void setId(Long id){this.id=id;}
   public void setIsbn(String isbn){this.isbn=isbn;}
   public void setTitle(String title){this.title=title;}
   public void setAuthor(String author){this.author=author;}
   public void setPages(int pages){this.pages=pages;}
   public void setCategory(String category){this.category=category;}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인자들이 여러개인 경우 각 인자들을 파악하기 어려웠던 Telescoping Constructor패턴과는 달리,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaBeans 패턴은 명시적으로 &lt;b&gt;&lt;code&gt;set+속성이름&lt;/code&gt;&lt;/b&gt; 의 &lt;b&gt;&lt;code&gt;Setter 메서드&lt;/code&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;허나, Setter 메서드가 있다는건 언제든지 해당 속성의 값을 변경 및 설정이 가능하다는 말이다.&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;code&gt;immutable Object를 만들 수 없게되었다는 단점&lt;/code&gt;이있다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&amp;lt;Builder 패턴&amp;gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우리가 만들고자하는 객체를 생성시킬 수 있는 기능을가진 &lt;code&gt;inner클래스&lt;/code&gt;인 &lt;code&gt;builder&lt;/code&gt;를 제공해준다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex)&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class Book{
public static class BookBuilder{
...
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&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;Builder 패턴을 적용해서 기존 Book 클래스를 개선시켜보자.&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;먼저 Book 클래스에 대한 인스턴스는 Book 클래스의 inner Class인 BookBuilder를 통해서 생성하도록한다.&lt;/li&gt;
&lt;li&gt;메서드 체이닝을 통해, 기존 Telescoping Constructor 패턴의 가독성 문제를 해결한다.&lt;/li&gt;
&lt;li&gt;기존 JavaBeans 패턴의 immutable Object 생성불가문제를 해결하기위해 Setter 메서드는 구현하지 않도록한다.&lt;/li&gt;
&lt;/ol&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;style6&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Builder 패턴을 적용시킨 코드&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Book {
    private Long id; //필수적인 속성
    private String isbn; //필수적인 속성
    private String title;
    private String author;
    private int pages;
    private String category;

    public static class BookBuilder {
        private Long id; //필수적인 속성
        private String isbn; //필수적인 속성
        private String title;
        private String author;
        private int pages;
        private String category;

        public Long getId() {
            return id;
        }

        public String getIsbn() {
            return isbn;
        }

        public String getTitle() {
            return title;
        }

        public String getAuthor() {
            return author;
        }

        public int getPages() {
            return pages;
        }

        public String getCategory() {
            return category;
        }

        //필수적인 속성들은 생성자로 설정해줌 
        public BookBuilder(Long id, String isbn) {
            this.id = id;
            this.isbn = isbn;
        }

        //보통 setter 메서드들은 반환형이 void 지만, 이 Builder는 반환형이 this로 - 자신을 반환함.
        //선택적인 속성들은 별도의 메서드로 설정해줌.메서드의 이름은 속성의 이름과 동일하게 for 가독성. 
        public BookBuilder title(String title) {this.title = title; return this;}// 메서드 체이닝을 위해 현재 객체 반환

        public BookBuilder author(String author) {this.author = author; return this;}

        public BookBuilder pages(int pages) {this.pages = pages; return this;}

        public BookBuilder category(String category) {this.category = category; return this;}

        //build 메서드는, BookBuilder 자신이 갖고있는 속성정보로 book인스턴스의 속성정보를 설정하고, 그 book인스턴스를 반환한다.
        //이 build 메서드를 가지고, BookBuilder인스턴스를 통해서 Book인스턴스를 생성&amp;amp;전달받을 수 있다.
        public Book build() {
            Book book = new Book();
            book.id = this.id;
            book.isbn = this.isbn;
            book.title = this.title;
            book.author = this.author;
            book.pages = this.pages;
            book.category = this.category;
            return book;
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {

        //BookBuilder 인스턴스의 속성을 설정함과동시에, 해당 속성값을 그대로 갖는 Book 인스턴스를 생성&amp;amp;반환받음.
        //각 메서드의 반환값이 this이므로, 반환받은 객체에 연속적으로 접근하여 메서드를 호출하는 -&amp;gt; 메서드 체이닝이 가능하다.
        Book book1 = new Book.BookBuilder(1L, &quot;isbn1234&quot;).author(&quot;WonJun Lee&quot;).build();
        Book book2 = new Book.BookBuilder(2L, &quot;isbn2345&quot;).pages(360).author(&quot;WonJun Lee&quot;).build();
        System.out.println(book2.getAuthor());
    }
}&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;이처럼 직접 Book 인스턴스를 생성하는 것이 아닌, &lt;code&gt;Book 클래스 내부의 BookBuilder 이너클래스의 build 메서드로 Book 인스턴스를 생성하는 모습&lt;/code&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;이전에 Telescoping Constructor의 경우에는 전달되는 인자의 순서가 중요했었다.&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;하지만 이 Builder 패턴을 사용하면, &lt;code&gt;메서드 체이닝 기법&lt;/code&gt;을 이용하기때문에, 어떤 속성을 어떤 순서로 전달해주던간에 상관없이 명시적으로 해당 속성에 대한 인자를 전달해 줄 수 있게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;또한, Book 인스턴스에는 별도로 Setter 메서드를 구현해놓지 않았기때문에 &lt;code&gt;immutable Object&lt;/code&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;&lt;b&gt;즉, 빌더 패턴을 사용하면 객체를 생성할 때 필요한 속성만 설정할 수 있어, 가독성과 유지보수성을 높이는 데 도움이 된다.&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;&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lombok 라이브러리 사용하여 Builder패턴 최적화&lt;/h2&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;다만 이 Builder패턴은 유용하기는 하나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Builder클래스를 내부클래스로 별도로 만들어주어야하고 +&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속성의 갯수만큼 속성설정 메서드들을 만들어주어야하며 +&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build 메서드도 만들어주어야하기때문에 &lt;b&gt;기존코드보다 코드의 양이 상당히 증가하게되는 경향이있다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 &lt;b&gt;Builder패턴을 그대로 사용하면서 코드를 단순화할 수 있는 방법&lt;/b&gt;으로 &lt;b&gt;&lt;code&gt;Lombok(롬복)&lt;/code&gt;&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;&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;Lombok 라이브러리를 사용하면 Builder 어노테이션을 사용할 수 있기때문에, Builder 어노테이션을 통해 Builder 클래스 내부의 코드를 자동으로 생성할 수 있게된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;code&gt;@Builder 어노테이션&lt;/code&gt;&lt;/b&gt; 을 사용하면, Lombok이 자동으로 내부에 빌더 inner클래스를 생성해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;또한, 빌더 클래스에서는 각 필드에 대한 설정 메서드가 생성되어있으며 이 메서드들은 this를 반환하므로 메서드 체이닝도 구현되어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;code&gt;@Getter 어노테이션&lt;/code&gt;&lt;/b&gt; 을 사용하면, getter 메서드 역시 자동으로 생성해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;code&gt;@Setter 어노테이션&lt;/code&gt;&lt;/b&gt; 도 역할은 같으나, &lt;b&gt;&lt;code&gt;immutable Object 구현을 위해&lt;/code&gt;&lt;/b&gt; 따로 적용시키지않았다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;code&gt;@NonNull 이노테이션&lt;/code&gt;&lt;/b&gt; 을 적용시키면 해당 필드는 필수적인 속성이되어 반드시 값을 할당해주어한다. 그렇지않으면 NullPointerException 예외를 발생시켜준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;즉, Lombok 라이브러리를 사용하면 Builder 패턴을 간편하게 적용시킬 수 있게된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;

@Getter // getter 메소드를 자동으로 생성
@Builder // @Builder 어노테이션을 사용하면 Lombok이 해당 클래스에 빌더 패턴을 자동으로 적용.
public class Book {
    @NonNull
    private Long id; // 필수적인 속성
    @NonNull
    private String isbn; // 필수적인 속성
    private String title;
    private String author;
    private int pages;
    private String category;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Book book1 = new Book.BookBuilder().id(1L).isbn(&quot;isbn1234&quot;).author(&quot;WonJun Lee&quot;).build();
        Book book2 = new Book.BookBuilder().id(2L).isbn(&quot;isbn2345&quot;).pages(360).author(&quot;WonJunLee&quot;).build();
        System.out.println(book2.getAuthor());
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>디자인 패턴</category>
      <category>Builder Pattern</category>
      <category>디자인 패턴</category>
      <category>빌더 패턴</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/14</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EB%B9%8C%EB%8D%94Builder-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry14comment</comments>
      <pubDate>Sun, 20 Oct 2024 00:41:25 +0900</pubDate>
    </item>
    <item>
      <title>[디자인 패턴] 커맨드(Comman) 패턴 - 예제를 통해 알아보기</title>
      <link>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%BB%A4%EB%A7%A8%EB%93%9CComman-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;h1&gt;Command Pattern&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Command(커맨드) 패턴이란?&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실행될 기능을 캡슐화(클래스화)함으로써 각 기능을 객체로 만들어 관리하기에, 주어진 여러 기능을 실행할 수 있는 재사용성이 높은 클래스를 설계하는 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;이벤트가 발생했을 때(ex 버튼 클릭), 해당 이벤트에 대해 실행될 기능을 다양하게 해주면서도 기능의 변경이 필요한 경우엔 쉽게 변경이 가능하도록해주는 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;변경 및 추가 삭제가 빈번한 경우, 이벤트를 발생시키는 클래스(ex 버튼)를 변경하지 않으면서도 기능변경이 가능하도록해주는 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;커맨드 패턴은 실행될 기능을 캡슐화함으로써 기능의 실행을 요구하는 호출자 클래스(Invoker)와 실제 기능을 실행하는 수신자 클래스(Receiver) 사이의 의존성을 제거한다 (호출자와 수신자간의 연관관계 제거).&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;따라서 실행될 기능의 변경에도 호출자 클래스를 수정없이 그대로 사용할 수 있도록 해준다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(즉 호출자 클래스를 수정없이 그대로 사용할 수 있기때문에, 실행될 기능을 캡슐화함으로써 주어진 여러 기능을 실행할 수 있는 클래스 설계가 가능하다 by 커맨드 패턴)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;만능 버튼 예제를 통해 알아보는 Command Pattern&lt;/h2&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 만능 버튼은 눌리면 특정 기능을 수행하는데, &lt;code&gt;먼저 버튼을 누르면 램프를 켜는 기능을 구현하고자 한다.&lt;/code&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;Lamp 클래스: 불을 켜는 기능을 제공하는 클래스&lt;/li&gt;
&lt;li&gt;Button 클래스: 버튼이 눌렸음을 인식하는 클래스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;이 램프를 켜는 기능을하는 버튼을 설계하면 아래와 같다.&lt;/h4&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt;기존 설계&amp;gt;&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/4ccd0c8d-7dab-4e82-ad78-f6f50ee89f16&quot; /&gt;&lt;/div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Lamp {
    public void turnOn(){
        System.out.println(&quot;Lamp on&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;public class Button {
    private Lamp theLamp;

    public Button(Lamp theLamp) {
        this.theLamp = theLamp;
    }

    public void pressed(){
        theLamp.turnOn();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Lamp lamp = new Lamp();
        Button lampButton = new Button(lamp);
        lampButton.pressed();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;문제점1&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;우리의 목표는 만능 버튼을 만드는 것이다.&lt;/p&gt;
&lt;p align=&quot;center&quot; 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;p data-ke-size=&quot;size16&quot;&gt;버튼이 눌렸을때 램프를 켜는 대신 다른 기능을(ex 알람 시작) 수행하도록 변경하려면 코드가 어떻게 변경되어야할까?&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;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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/a9e44d22-03ef-48a8-a56b-2b28dbbf5cfb&quot; /&gt;&lt;/div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Alarm {
    public void start(){System.out.println(&quot;Alarming ...&quot;);}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;public class Button {
    private Alarm theAlarm;
    public Button(Alarm theAlarm) {this.theAlarm = theAlarm;}
    public void pressed(){theAlarm.start();}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Alarm alarm = new Alarm();
        Button lampButton = new Button(alarm);
        lampButton.pressed();
    }
}&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;이때, 버튼의 기능을 알람시작이라는 새로운 기능으로 변경시키려고하면 Alarm 클래스를 새로 생성하면 되지만 Button 클래스는 기존 코드가 변경이되었다.&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;gt; 이는 OCP 원칙을 위반하는 것이다.&lt;/b&gt;&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;style6&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;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;문제점2&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;또한, 이는 만능 버튼이라고 볼 수 없다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&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;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(현재 설계=&amp;gt; 램프 기능 필요할땐 Lamp와, 알람 기능 필요할땐 Alarm과 연관관계 맺도록 기존코드 변경해야함)&lt;/p&gt;
&lt;/blockquote&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;/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;/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;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;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그렇다면 현재의 버튼이 만능버튼으로써 동작하도록하려면 어떻게 해야할까?&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;   Ex) 예를들어, 버튼이 처음 눌렸을 때는 램프를 켜고, 버튼이 두 번쨰 눌렸을 때는 알람을 동작시키려면?&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;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;버튼에 새로운 기능이 요구됐을때&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존의 코드를 변경하지않으면서&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로그램이 실행할때 버튼의 기능을 변경할 수 있도록&lt;/b&gt; &lt;span style=&quot;letter-spacing: 0px; text-align: left;&quot;&gt;구현해야 할 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;h2 data-ke-size=&quot;size26&quot;&gt;1차 설계 개선&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&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;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(버튼을 한번 눌렸을때 램프를켜고 또 한번 눌렸을때는 알람을 켜고...)&lt;/p&gt;
&lt;/blockquote&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;이를 위해선 Button 클래스가 어느하나만이 아닌,&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;Lamp와 Alarm 클래스 둘과 모두 연관관계를 맺어야할 것이다.&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;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/d0943ebd-8a3d-4c78-b7da-ab19dc293901&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Lamp {
    public void turnOn(){ System.out.println(&quot;Lamp on&quot;); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Alarm {
    public void start(){ System.out.println(&quot;Alarming ...&quot;); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;// 현재 버튼의 모드를 나타내는 Mode 열거형
// 현재 모드가 ALRAM 모드라면 알람start, LAMP 모드라면 램프on
enum Mode {LAMP, ALRAM}

public class Button {
    private Alarm theAlarm;
    private Lamp theLamp;
    // 버튼의 현재 모드를 나타내는 필드
    private Mode theMode;

    public void setTheMode(Mode theMode) {
        this.theMode = theMode;
    }

    public Button(Lamp theLamp,Alarm theAlarm) {
        this.theLamp = theLamp;
        this.theAlarm = theAlarm;
    }

    /* 현재 이 버튼이 어떤 모드인지에 따라서,
    램프를 켤 수도 있고 or 알람을 시작할 수도 있다. */
    public void pressed(){
        switch (theMode){
            case LAMP -&amp;gt; theLamp.turnOn();
            case ALRAM -&amp;gt; theAlarm.start();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Lamp lamp = new Lamp();
        Alarm alarm = new Alarm();

        //버튼은 Lamp, Alarm 둘과 연관관계을 맺음
        Button button = new Button(lamp, alarm);

        //버튼의 모드를 LAMP로 설정하여 =&amp;gt; 버튼의 기능을 램프켜기로 설정
        button.setTheMode(Mode.LAMP);
        button.pressed();

        //버튼의 모드를 ALRAM으로 설정하여 =&amp;gt; 버튼의 기능을 알람시작으로 설정
        button.setTheMode(Mode.ALRAM);
        button.pressed();
    }
}&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;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;/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;왜냐하면, 버튼에 새로운 기능추가시 Button 클래스의 pressed() 메서드에 새로운 case를 더 추가해주는 등&lt;br /&gt;기존의 코드를 계속 변경시켜줘야한다는 &lt;b&gt;OCP 위반이 발생하기때문이다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ex) 버튼에 TV 켜기 기능 추가시 열거형 Mode에 새로운 TV 모드값을 추가해줘야하고, Tv 클래스와 연관관계를 맺기위해 Button 클래스에 private tv맴버변수 추가 및 생성자 코드를 변경해줘야하며 pressed() 메서드의 switch문에 TV case도 새로 추가해줘야할 것이다.&lt;/p&gt;
&lt;/blockquote&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;/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;즉, 개선된 현재의 설계 역시 OCP를 만족하지못한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;이 OCP 위반문제를 Strategy 패턴을 응용하여 한번 해결해보자.&lt;/h4&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;h2 data-ke-size=&quot;size26&quot;&gt;2차 설계 개선(by Strategy 패턴 응용)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&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;- 기능을 갖는 주체(&lt;code&gt;Context&lt;/code&gt;) : &lt;code&gt;Button 클래스&lt;/code&gt;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 실제 변하는 것(&lt;code&gt;Concrete Strategy&lt;/code&gt;) : &lt;code&gt;AlarmStartCommmand, LampTurnOnCommand... 클래스&lt;/code&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;(만능 버튼의 기능은, 실제로 경우에 따라서 알람시작 or 램프켜기 or...로 변경된다)&lt;/blockquote&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;blockquote data-ke-style=&quot;style3&quot;&gt;즉, 실제 변하는 것은 &lt;b&gt;버튼이 수행하는 기&lt;/b&gt;능이다. 알람을 시작시키거나 램프를 키거나하는 이 버튼의 기능이자 실행동작(execute)을, &lt;b&gt;Command 구체 전략 클래스&lt;/b&gt;로 모델링해준다&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&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;code&gt;Strategy&lt;/code&gt;) : &lt;code&gt;Command 인터페이스&lt;/code&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;버튼이 수행하는 기능들을 일반화모델링한 개념&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/73841c7c-1631-4cd6-9f1f-a29602c524bd&quot; /&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Strategy 패턴과 설계구조 모양새가 비슷해보이나, 전략이 아닌, 무언가를 실행하는 명령기능들을 하위에 두었다는게 차이점이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드로 작성하면 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;public class Button {
    private Command theCommand; //버튼이 수행하는 커멘트를 레퍼런스하는 필드

    //커멘드를 설정해주는 설정자
    public void setTheCommand(Command theCommand) {
        this.theCommand = theCommand;
    }

    public void pressed(){
    theCommand.execute();
    // 버튼 입장에서는, theCommand가 어떤 커멘드인지에 구애받지않고 theCommand.execute()로 기능을 실행가능함
    // (버튼이 실행하는 기능이 숨겨져있는 캡슐화, 커멘드마다 실행되는 기능이 다르다는 다형성)
    // 알람을 시작한다던지 램프를 켠다던지와 같은 버튼의 실행기능(command)을 외부에서 설정만해주면 어떤 기능이던지 해당 기능을 execute 가능.
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public interface Command {
    public void execute();
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;//알람을 시작하도록하는 버튼의 기능이자, 실행명령인 AlarmStart Command 클래스
public class AlarmStartCommand implements Command{

    private Alarm theAlarm;//AlarmStartCommand 클래스는 &quot;알람을 시작해라&quot;는 버튼의 실행명령이자 기능이므로
                           //Alarm 과 연관관계를 맺어야한다.

    public AlarmStartCommand(Alarm theAlarm) {
        this.theAlarm = theAlarm;
    }

   @Override
    public void execute() { //버튼이 수행하는 하나의 기능이자 명령.
        theAlarm.start(); // 기능은 알람 시작하기.
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;//램프를 켜도록하는 버튼의 기능이자, 실행명령인 LampTurnOn Command 클래스

public class LampTurnOnCommand implements Command{

    private Lamp theLamp;//LampTurnOnCommand 클래스는 &quot;램프를 켜라&quot;는 버튼의 실행명령이자 기능이므로
                         //Lamp 와 연관관계를 맺어야한다.

    public LampTurnOnCommand(Lamp theLamp) {
        this.theLamp = theLamp;
    }

    @Override
    public void execute() { //버튼이 수행하는 하나의 기능이자 명령.
        theLamp.turnOn(); //그 기능은 램프 켜기.
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Alarm alarm = new Alarm();
        Lamp lamp= new Lamp();
        Button button = new Button();

        //알람을 start 시키기위해서는, 알람을 start 시키는 Command가 필요하다
        //alarm 인스턴스를 생성자에 넘겨주어, 해당 alarm 인스턴스에 대해서 start하도록 명령
        ////alarmOnCommand와 alarm이 연관관계 맺도록.
        Command alarmOnCommand = new AlarmStartCommand(alarm);

        //이 button이라는 만능버튼의 기능이자 실행명령을 alarmOnCommand, 즉 알람시작 기능으로 설정
        button.setTheCommand(alarmOnCommand);
        button.pressed(); //현재 이 버튼의 기능은 알람시작 기능이므로, 버튼을 누르면 알람이 시작됨

        Command lampOnCommand = new LampTurnOnCommand(lamp); //lampOnCommand와 lamp가 연관관계 맺도록.

        button.setTheCommand(lampOnCommand); //이번엔 만능버튼의 기능을 램프켜기로 설정.
        button.pressed(); //현재 이 버튼의 기능은 램프켜기 기능이므로, 버튼을 누르면 램프가 켜짐

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;이로써, OCP 원칙을 위반하지않으면서 버튼의 기능을 변경할 수 있게되었다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&gt;또한 Stratrgy 패턴을 응용하였기에, 버튼에 새로운 기능을 추가할때도 기존코드의 변경없이 기능추가가 가능해졌다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&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;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그렇다면, 만능 버튼에 TV를 켜는 기능을 한번 추가해보자.&lt;/b&gt;&lt;/h4&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;변화하는 것(TV켜기 기능)을 Command 인터페이스를 구현하는 하위 개념으로 모델링하고, TV 클래스와 연관관계를 맺도록 설계하면 된다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/3c9f61bc-4d54-4cbd-ba36-d4d560d77a9b&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Tv {

    public void on(){
        System.out.println(&quot;Tv on&quot;);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class TvOnCommand implements Command{
    private Tv tv;

    public TvOnCommand(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.on();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Alarm alarm = new Alarm();
        Lamp lamp= new Lamp();
        Button button = new Button();

        Command alarmOnCommand = new AlarmStartCommand(alarm);
        button.setTheCommand(alarmOnCommand);
        button.pressed(); 

        Command lampOnCommand = new LampTurnOnCommand(lamp);
        button.setTheCommand(lampOnCommand);
        button.pressed(); 

        // 버튼에 tv켜기 기능추가 
        Command tvOnCommand = new TvOnCommand(new Tv());
        button.setTheCommand(tvOnCommand); //만능버튼의 기능을 tv켜기로 설정.
        button.pressed(); //버튼을 누르면 tv가 켜짐
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div align=&quot;center&quot;&gt;위와 같이, 기존 코드의 변경없이(OCP 위반없이) 만능 버튼에 새로운 기능을 추가시켰다.&lt;/div&gt;
&lt;h4 align=&quot;center&quot; data-ke-size=&quot;size20&quot;&gt;이것이&lt;span style=&quot;background-color: #ffc9af;&quot;&gt; &lt;code&gt;Command 패턴&lt;/code&gt;&lt;/span&gt;이다.&lt;/h4&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;style6&quot; /&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/a9999342-33e4-4eeb-9312-c2c0d13d89c5&quot; /&gt;&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처: Java객체지향 디자인패턴(한빛미디어)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- &lt;code&gt;Invoker 클래스(호출자)&lt;/code&gt;: 기능의 실행을 요청하는 &lt;code&gt;호출자 클래스&lt;/code&gt;&lt;/b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;예제에서는 Button 클래스&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&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;style6&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;- &lt;code&gt;Command 인터페이스&lt;/code&gt;: 실행될 기능에 대한 인터페이스로, 실행될 기능을 execute 메서드로 선언한다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&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;style6&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;- &lt;code&gt;ConcreteCommand 클래스&lt;/code&gt;: 실제로 실행되는 기능을 나타내는 클래스.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Command 인터페이스의 execute() 메서드를 구현하여 이를통해 자신이 수행할 기능을 정의한다.&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;예제에서는 AlarmStartCommand, LampTurnOnCommand... 클래스&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&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;style6&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;- &lt;code&gt;Reciever 클래스(수신자)&lt;/code&gt;: ConcreteCommand의 기능 실행을 위해 사용되는 &lt;code&gt;수신자 클래스&lt;/code&gt;.&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;ConcreteCommand의 execute()를 통해 Receiver가 action을 취함.(ex 램프 불을켜고, 알람시작하고...)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;예제에서는 Lamp, Alarm... 클래스&lt;/blockquote&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;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;즉, 커맨드 패턴의 일반적인 구조는&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 버튼의 기능이 램프켜기인 경우,&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누군가가 버튼을 눌러서 &lt;b&gt;버튼(Invoker)&lt;/b&gt; 의 pressed가 실행이되면,&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AlarmStartCommand(ConcreteCommand)&lt;/b&gt; 가 execute해서 &lt;b&gt;Alarm(Reciever)&lt;/b&gt; 이 action하는 구조이다&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;Command 인터페이스의 하위개념으로 실행될 기능인 ConcreteCommand 클래스를 모델링해두고,

ConcreteCommand에서 execute()로 어떤 명령을 내리면,

연관관계이자 - 실제로 그 명령을 수행하는 주체인 Reciever 클래스에서 action을 수행하도록 설계하면 된다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;br /&gt;기능이 변경되거나 추가될 경우, 호출자(Invoker) 클래스를 수정하지 않고도 쉽게 기능변경 가능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;커맨드 패턴은 호출자와 수신자(Receiver) 간의 의존성을 없앤다. 호출자는 어떤 기능이 실행될지를 알 필요가 없고, 오직 커맨드 객체만 알면된다. 이를 통해 코드의 결합도를 낮추고, 유지보수가 용이해짐&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;/ul&gt;
&lt;/blockquote&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&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;b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;code&gt;커맨드 패턴은&lt;/code&gt; &lt;/span&gt;기능의 캡슐화와 호출자/수신자 간의 의존성 제거를 통해 유연하고 재사용 가능한 코드 구조를 제공하는 디자인 패턴&lt;/b&gt;&lt;/h4&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>
      <category>command pattern</category>
      <category>디자인 패턴</category>
      <category>커맨드 패턴</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/13</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%BB%A4%EB%A7%A8%EB%93%9CComman-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry13comment</comments>
      <pubDate>Mon, 7 Oct 2024 04:08:17 +0900</pubDate>
    </item>
    <item>
      <title>[디자인 패턴] OCP(개방-폐쇄원칙) - 예제를 통해 알아보기</title>
      <link>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-OCP%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84%EC%9B%90%EC%B9%99-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;h1&gt;OCP (개방-폐쇄원칙)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 소프트웨어를 위한 설계 원칙 SOLID&lt;/h2&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;이해하기 쉽고&lt;/b&gt;, &lt;b&gt;변경하기 용이하며(유지보수 용이)&lt;/b&gt;, &lt;b&gt;새로운 기능으로의 확장이 용이한 소프트웨어&lt;/b&gt;를 말한다.&lt;br /&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;SOLID&lt;/b&gt;(SRP, OCP, LSP, ISP, DIP)라고 부르며, 이 중 가장 핵심이자 디자인 패턴 이해에 필수적인 원칙이 &lt;b&gt;OCP&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OCP(개방-폐쇄 원칙)&lt;/h2&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;Open&lt;/b&gt; = 개방: 새로운 기능을 추가할 수 있도록 열려 있어야 한다.&lt;br /&gt;&lt;b&gt;Closed&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OCP 원칙은 기존 코드를 변경하지 않으면서 새로운 기능을 추가할 수 있도록 설계하는 원칙&lt;/b&gt;&lt;br /&gt;을 말한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제를 통해 OCP 원칙에 대해서 알아보자.&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;code&gt;Student&lt;/code&gt; 클래스가 있다. 이 클래스에는 이름, 중간 성적, 기말 성적, 과제 성적 정보가 있으며, 이를 통해 학점을 계산하는 &lt;code&gt;calculateGrade&lt;/code&gt; 기능과 성적 정보를 XML 형식으로 출력해주는 &lt;b&gt;&lt;code&gt;print&lt;/code&gt;&lt;/b&gt; 기능이 존재한다.&lt;br /&gt;다이어그램으로 표현해보면 아래와같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/959e302b-ab1b-4424-b6e8-5e6c403ae49e&quot; /&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 data-ke-size=&quot;size16&quot;&gt;그럼 성적 정보 출력을 담당하는 print 메서드를 코드로 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;성적 정보를 xml 형식으로만 출력해주는 print 메서드&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;     public void print(String mode) {

            try {
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                Document doc = docBuilder.newDocument();
                doc.setXmlStandalone(true);

                Element student = doc.createElement(&quot;학생성적정보&quot;);
                doc.appendChild(student);

                Element name = doc.createElement(&quot;이름&quot;);
                student.appendChild(name);
                name.appendChild(doc.createTextNode(this.name));

                Element gradeInfo = doc.createElement(&quot;성적정보&quot;);
                student.appendChild(gradeInfo);

                Element middleScore = doc.createElement(&quot;중간점수&quot;);
                gradeInfo.appendChild(middleScore);
                middleScore.appendChild(doc.createTextNode(String.valueOf(this.midScore)));

                Element finalScore = doc.createElement(&quot;기말점수&quot;);
                gradeInfo.appendChild(finalScore);
                finalScore.appendChild(doc.createTextNode(String.valueOf(this.finalScore)));
                Element hwScore = doc.createElement(&quot;과제점수&quot;);
                gradeInfo.appendChild(hwScore);
                hwScore.appendChild(doc.createTextNode(String.valueOf(this.hwScore)));


                Element grade = doc.createElement(&quot;학점&quot;);
                gradeInfo.appendChild(grade);
                grade.appendChild(doc.createTextNode(String.valueOf(calculateGrade())));

                // XML로 쓰기
                TransformerFactory transformerFactory = TransformerFactory.newInstance();

                Transformer transformer = transformerFactory.newTransformer();
                transformer.setOutputProperty(&quot;{http://xml.apache.org/xslt}indent-amount&quot;, &quot;4&quot;); //정렬 스페이스4칸
                transformer.setOutputProperty(OutputKeys.ENCODING, &quot;UTF-8&quot;);
                transformer.setOutputProperty(OutputKeys.INDENT, &quot;yes&quot;); //들여쓰기
                transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, &quot;yes&quot;); //doc.setXmlStandalone(true); 했을때 붙어서 출력되는부분 개행

                DOMSource source = new DOMSource(doc);
                StreamResult result = new StreamResult(System.out);

                transformer.transform(source, result);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }&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;br /&gt;이와 같이 print 메서드는 xml 형식으로만 성적을 출력해주는 기능을 담당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 학생의 성적 출력 형식은 xml이다. 그러나, 만약 학생의 성적을 출력하는 형식이 xml 이 아닌&lt;br /&gt;json 형식으로도 출력하고 싶어진다면 어떻게할까?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; print 메서드에 json 형식으로 출력하는 코드 구문을 추가하면 될 것이다. &lt;br /&gt;&lt;br /&gt;하지만, 이 경우 print 메서드의 코드에 json 형식으로의 출력을 구현하게되면서 기존코드인 student 클래스의 변경이 발생하게되어 OCP 원칙에 위반되어진다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xml 뿐만이 아닌 json 형식으로도 출력되도록 추가변경한 아래 코드를 한번보자.&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;h3 data-ke-size=&quot;size23&quot;&gt;xml + json 형식으로도 출력되도록 추가변경한 print 메서드&lt;/h3&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;    public void print(String mode) {
        if (mode.equals(&quot;xml&quot;)) {
            try {
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
                Document doc = docBuilder.newDocument();
                doc.setXmlStandalone(true);
                ... 

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else if (mode.equals(&quot;json&quot;)) {
            JSONObject entry = new JSONObject();

            Map item = new LinkedHashMap();
            item.put(&quot;name&quot;, this.name);
            item.put(&quot;midScore&quot;, this.midScore);
            item.put(&quot;finalScore&quot;, this.finalScore);
            item.put(&quot;hwScore&quot;, this.hwScore);
            item.put(&quot;grade&quot;, calculateGrade());

            JSONObject json = new JSONObject(item);

            System.out.println(json.toJSONString());
        }
    }&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;이처럼, 새로운 형식으로 성적을 출력하고자 할 때에는 print 메서드가 계속 변경되기때문에, &lt;b&gt;기존의 코드가 변경 =&amp;gt; OCP 원칙에 위반되어진다.&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;그렇다면 OCP를 만족하는 설계가 되기위해서는 어떻게해야할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OCP 만족을 위한 4단계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OCP를 만족하는 설계가 되기위해서는 크게 다음 4가지 단계를 거쳐야한다.&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;1. 변하는 것이 무엇인지를 식별한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 해당 변하는 부분을 클래스로 분리하여 모델링한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 변하는 부분들을 포용하는 개념을 추상 클래스나 인터페이스로 **추상화&lt;/b&gt; 모델링한다.**&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 2번 단계에서 분리해낸 클래스를 - 3번 단계에서 추상화된 개념의 자식클래스로 모델링한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&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;위의 4가지 단계를 적용하여 student 클래스를 OCP 원칙에 만족하도록 리모델링하기위한 단계는 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 변하는 것 =&amp;gt; student 클래스에서는 print 메서드의 출력형식&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 변하는 부분인 출력형식을, xml 형식으로 성적을 출력해주는 PrintInXml 클래스 + json 형식으로 성적을 출력해주는 PrintInJson 클래스로 분리&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. PrintInXml 클래스와 PrintInJson 클래스를 포용하는 개념(&quot;출력한다&quot;)을 Printer 인터페이스로 추상화한다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. PrintInXml 클래스와 PrintInJson 클래스가 Printer 인터페이스를 구현하도록 모델링한다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&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;Printer 인터페이스에는 &lt;b&gt;&quot;출력한다&quot;&lt;/b&gt; 는 기능인 print가 있고, 각 하위 클래스에서는 print메서드를 각 클래스의 출력 형식에 맞게 오버라이딩하면 될 것이다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 4가지 단계를거쳐 리모델링한 OCP를 만족하는 최종 설계는 다음과 같다.&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OCP 원칙을 만족하는 최종설계&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/421608d5-0597-4575-9ba1-931dfcddb4d4&quot; /&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;이와 같은 설계를 통해, Student 클래스는 Printer 와 연관관계를 맺고 Printer의 print 메서드를 통해서 경우에 따라 각기다른 형식으로 성적 정보 출력이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;만약 xml - json 이외에도 또 다른 형식으로 성적정보를 출력하고싶다면, 새로운 출력 형식을 표현하는 클래스를 Print 인터페이스를 구현하는 파생 클래스로 추가하면된다.&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/2ef1a7e2-5ecb-4505-a0a0-074b646a801a&quot; /&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;기존 Studnet 클래스의 print 메서드를 변경시켜서 형식 추가하는 것이 아닌, 새로운 파생 클래스를 추가하는 방식인 것이다.&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;OCP 원칙을 만족하여 =&amp;gt; 기존의 Student 클래스의 코드 변경없이, 다른 형태로 성적 정보를 출력하는 기능을 추가할 수 있게된다.&lt;/b&gt;&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예제2 - 학점 출력&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 Student 클래스에는 중간고사 점수, 기말고사 점수, 과제 점수를 넘겨받고 학점을 계산해주는 메서드 로직이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class Student{

    private int midScore;
    private int finalScore;
    private int hwScore;

    public Student(int midScore, int finalScore, int hwScore) {
        this.midScore = midScore;
        this.finalScore = finalScore;
        this.hwScore = hwScore;
    }

    public Grade calculateGrade(){
        double total= 0.35*midScore+0.35*finalScore+0.3*hwScore;

        if (total &amp;gt;= 85) return Grade.A;
        if (total &amp;gt;= 75) return Grade.B;
        if (total &amp;gt;= 65) return Grade.C;
        if (total &amp;gt;= 50) return Grade.D;
        return Grade.F;
    }
}
&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;그러나 이 코드 역시, 추후 교수님의 재량 및 학교 정책의 변경으로 인해 학점 계산방식이 변경될 경우 Student 클래스 내부의 calculateGrade 학점 계산 로직을 직접 수정해야하기에 OCP 를 위반하게된다.&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;위에서 알아본 OCP 만족을 위한 4단계를 이 경우에 적용시켜 OCP를 만족하도록 코드를 수정해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 변하는 것 =&amp;gt; 학점 계산 로직&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 변하는 부분인 학점 계산 로직을 클래스로 추출하여 모델링(GradeCalc1, GradeCalc2...)&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 변화들을 포괄하는 개념을 일반화, 실체화하여 추상클래스로 모델링 (GradeCalculator 추상클래스)&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 2단계에서 모델링한 클래스들을 실체화한 추상클래스의 하위 클래스로 설정&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&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;먼저, 변하는 부분은 학점 계산 로직이다. 각 로직들을 별도의 클래스로 모델링하고, 이 클래스들을 포괄하는 GradeCalculator 라는 추상클래스도 모델링하여 각 클래스들이 이 추상클래스를 상속받아 서로 다른 로직들을 구현하도록하면된다.&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;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;OCP 만족하도록 개선한 코드&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class Student{

    private int midScore;
    private int finalScore;
    private int hwScore;
    private GradeCalculator gradeCalculator; //연관관계를 통한 학점계산 위임.

    public void setGradeCalculator(GradeCalculator gradeCalculator) {
        this.gradeCalculator = gradeCalculator;
    }

    public Student(int midScore, int finalScore, int hwScore) {
        this.midScore = midScore;
        this.finalScore = finalScore;
        this.hwScore = hwScore;
    }

    public Grade calculateGrade(){
        return gradeCalculator.calculateGrade(midScore,finalScore,hwScore);
    }

}



/////////////////// 학점계산로직을 추상화한 추상클래스

public abstract class GradeCalculator {

    public abstract Grade calculateGrade(int midScore, int finalScore, int hwScore);
}



///////////////////추상클래스를 상속받은 학점계산로직 클래스1

public class GradeCalc1 extends GradeCalculator{
    //변화하는 것 = 학점 계산 로직. 이걸 클래스로 만들어냄.

        public Grade calculateGrade(int midScore, int finalScore, int hwScore){
            double total= 0.35*midScore+0.35*finalScore+0.3*hwScore;

            if (total &amp;gt;= 85) return Grade.A;
            if (total &amp;gt;= 75) return Grade.B;
            if (total &amp;gt;= 65) return Grade.C;
            if (total &amp;gt;= 50) return Grade.D;
            return Grade.F;
        }
    }



/////////////////// 추상클래스를 상속받은 학점계산로직 클래스2

public class GradeCalc2 extends GradeCalculator{
    public Grade calculateGrade(int midScore, int finalScore, int hwScore){
        //다른 학점 계산 로직. =&amp;gt; 중간 기말 학점 비율 조정
        double total= 0.30*midScore+0.40*finalScore+0.3*hwScore;

        if (total &amp;gt;= 85) return Grade.A;
        if (total &amp;gt;= 75) return Grade.B;
        if (total &amp;gt;= 65) return Grade.C;
        if (total &amp;gt;= 50) return Grade.D;
        return Grade.F;
    }
}



///////////////////

public class Main {
    public static void main(String[] args) {

        Student s= new Student(80,90,70);
        s.setGradeCalculator(new GradeCalc2()); //Student 클래스를 손댈필요없이 학점계산로직 클래스를 별도로 모델링-&amp;gt;객체화하여 사용. OCP 만족. 
        System.out.println(s.calculateGrade());
    }
}
&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마지막으로 알아둬야할 부분 - 클래스란&lt;/h3&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;</description>
      <category>디자인 패턴</category>
      <category>OCP</category>
      <category>개방폐쇄 원칙</category>
      <category>디자인 패턴</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/12</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-OCP%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84%EC%9B%90%EC%B9%99-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry12comment</comments>
      <pubDate>Sun, 6 Oct 2024 10:36:01 +0900</pubDate>
    </item>
    <item>
      <title>[디자인 패턴] 전략(Strategy) 패턴 - 예제를 통해 알아보기</title>
      <link>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%A0%84%EB%9E%B5Strategy-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;h1 style=&quot;text-align: center;&quot;&gt;Strategy Pattern&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Strategy(전략) 패턴이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Strategy 패턴은 실행중에 알고리즘 전략을 선택하여 해당 객체의 동작을 실시간으로 변경할 수 있게 하는 행위 디자인 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;code&gt;'전략'&lt;/code&gt;이란, 기능이나 동작이 될 수도 있는 특정한 목표를 수행하기 위한 행동 및 알고리즘을 말한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ex: 로봇 객체의 이동 및 공격 알고리즘)&lt;/p&gt;
&lt;/blockquote&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;code&gt;전략클래스&lt;/code&gt;로 미리 모델링(캡슐화)해두면, 이 모델링(캡슐화)되어진 전략클래스들을 이용하여 쉽게 전략을 교체할 수 있기때문에, 알고리즘 변경이 빈번하게 요구되는 경우나 쉽게 전략을 바꿔야 할 필요가 있는 경우에 적합한 행위 디자인 패턴이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ex: 로봇1 객체의 구체적인 이동 전략을 걷기 -&amp;gt; 뛰기로 바꿔야할 경우, 혹은 다른 기능들(공격,소리 등등)을 빈번하게 변경해야할 소지가 있는경우)&lt;/p&gt;
&lt;/blockquote&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;/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;style6&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;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;&lt;b&gt;로봇 예제를 통해 알아보는 Strategy Pattern&lt;/b&gt;&lt;/u&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;lt;기존 설계&amp;gt;&lt;/h2&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/35053918-3f6f-43f7-b9a3-41cd04ff9152&quot; /&gt;&lt;/div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public abstract class Robot {

    private String name;
    public abstract void move();
    public abstract void attack();

    public Robot(String name){this.name=name;}
    public String getName() {return name;}

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Atom extends Robot{

    public Atom(String name) {
        super(name);
    }
    public void move() {System.out.println(&quot;Can fly&quot;);}
    public void attack() {System.out.println(&quot;Can punch&quot;);}
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class TaekwonV extends Robot{

    public TaekwonV(String name) {
        super(name);
    }
    public void move() {System.out.println(&quot;can walk&quot;);}
    public void attack() {System.out.println(&quot;Missile&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;위와 같이 각 로봇종류를 일반화하여 하나의 추상클래스인 Robot을 만들어내고 이 Robot클래스를 Atom, TaekwonV가 상속받도록한 기본적인 일반화 구조이다.&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;code&gt;(※이 로봇예제에서는, 공격 및 이동 방법이 전략(strategy)이다.)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&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;style6&quot; /&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 align=&quot;center&quot; data-ke-size=&quot;size26&quot;&gt;기존 설계의 문제점&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;&amp;lt;문제점1&amp;gt;&lt;/code&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 기존 설계에서, 로봇의 공격 및 이동 방법을 수정하려면 어떻게 해야하는가?&lt;br /&gt;(ex. 태권v의 이동방법을 walk가 아닌 fly로 만들고싶다면)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우, &lt;b&gt;태권v 클래스의 move()메서드 내부의 println의 &quot;can walk&quot; 구문을 &quot;can fly&quot; 로 코드를 변경&lt;/b&gt;해줘야할 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;허나, 기능 추가 및 수정을위해 기존 코드를 변경한다? =&amp;gt; 이는 OCP 원칙을 위반하는 것이다.&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&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;style3&quot; /&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;&amp;lt;문제점2&amp;gt;&lt;/code&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존 설계에서, 아톰의 이동방법을따르고 태권v의 공격방법을 따르는 새로운 종류의 선가드로봇을 만들려고하면 어떻게 해야하는가?&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우, Robot 추상클래스를 상속하여 선가드 클래스를 생성하면 기존의 코드설계는 영향을 받지않기때문에 OCP 원칙을 지키면서 선가드를 추가할 수 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/a0366f8d-e9aa-4635-9520-5a69b8307525&quot; /&gt;&lt;/div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Sungard extends Robot{

    public Sungard(String name) {
        super(name);
    }
    public void move() {System.out.println(&quot;Can fly&quot;);} //아톰의 이동방법을 사용
    public void attack() {System.out.println(&quot;Missile&quot;);} //태권v의 공격방법을 사용
}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 새로운 종류의 로봇을 생성할경우 OCP 원칙을 준수하기에, 기존설계는 로봇을 새롭게 생성하는 부분에있어서 전혀 문제가없는 설계이다. 하지만 여기엔 문제가 하나 존재한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 &lt;code&gt;선가드 클래스는 아톰클래스의 이동방법을 따르고 태권v클래스의 공격방법을 따른다&lt;/code&gt;고 했다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;so, &lt;b&gt;선가드 클래스의 move() 코드와 attack() 코드는 아톰의 move() 코드와 중복이되고 태권v의 attack() 코드와도 중복되어진다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 아톰의 이동방법 알고리즘이나 태권v의 공격 알고리즘이 변경되어진다면, 선가드가 따르던 해당 알고리즘도 똑같이 변경해줘야한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드의 중복이 생기면 생길수록, 해당 중복되는 코드에 변경사항이 생기게되면 변경을 일관되게 동일하게 빠짐없이 변경시켜야한다. 이는 쉬운작업이 아니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;변경되는부분인 공격-이동 알고리즘이 각 클래스 내부의 메서드형태이기때문에 기존의 코드가 영향을 받을 수 밖에없는 OCP 원칙 위배가 발생한다.&lt;/b&gt; 새로운 종류의 로봇 생성시에는 문제가 없지만 공격-이동 알고리즘 변경시에는 위배된다는 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, &lt;b&gt;이 이동-공격 알고리즘 변경으로인한 OCP 원칙 위배를 어떻게 해결해야할까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변화의 단위를 클래스로 모델링해야한다. =&amp;gt; &lt;b&gt;so, 이동-공격 메서드(알고리즘)를 클래스로 모델링해야한다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&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;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: -webkit-center;&quot;&gt;문제 해결을 위한 Strategy Pattern 적용단계는 아래와 같다.&lt;/span&gt; &lt;/b&gt;&lt;/h4&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;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;lt; &lt;span style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;Strategy Pattern 적용 단계&lt;/span&gt;&amp;nbsp;&amp;gt;&lt;/h2&gt;
&lt;a id=&quot;user-content-strategy-pattern-적용-순서&quot; style=&quot;color: #000000;&quot; href=&quot;https://github.com/WJLee222/Design_Pattern/blob/main/Behavioral%20pattern/Strategy.md#strategy-pattern-%EC%A0%81%EC%9A%A9-%EC%88%9C%EC%84%9C&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 변경되는 것이 무엇인지를 식별한다.&lt;/h4&gt;
&lt;a id=&quot;user-content-1-변경되는-것이-무엇인지를-식별한다&quot; style=&quot;color: #000000;&quot; href=&quot;https://github.com/WJLee222/Design_Pattern/blob/main/Behavioral%20pattern/Strategy.md#1-%EB%B3%80%EA%B2%BD%EB%90%98%EB%8A%94-%EA%B2%83%EC%9D%B4-%EB%AC%B4%EC%97%87%EC%9D%B8%EC%A7%80%EB%A5%BC-%EC%8B%9D%EB%B3%84%ED%95%9C%EB%8B%A4&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 그 변경되는 구체적인 실제 알고리즘들을 &lt;b&gt;클래스로 모델링한다.(메서드 - &amp;gt; 클래스화)&lt;/b&gt;&lt;/h4&gt;
&lt;a id=&quot;user-content-2-그-변경되는-구체적인-실제-알고리즘들을-클래스로-모델링한다메서드---클래스화&quot; style=&quot;color: #000000;&quot; href=&quot;https://github.com/WJLee222/Design_Pattern/blob/main/Behavioral%20pattern/Strategy.md#2-%EA%B7%B8-%EB%B3%80%EA%B2%BD%EB%90%98%EB%8A%94-%EA%B5%AC%EC%B2%B4%EC%A0%81%EC%9D%B8-%EC%8B%A4%EC%A0%9C-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EB%93%A4%EC%9D%84-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-%EB%AA%A8%EB%8D%B8%EB%A7%81%ED%95%9C%EB%8B%A4%EB%A9%94%EC%84%9C%EB%93%9C---%ED%81%B4%EB%9E%98%EC%8A%A4%ED%99%94&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 2단계에서 모델링한 구체적인 클래스(구체 전략)들을 포괄하는 포괄개념을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;인터페이스 및 추상클래스로&lt;span&gt;&amp;nbsp;&lt;/span&gt;모델링&lt;/b&gt;한다.&lt;/h4&gt;
&lt;a id=&quot;user-content-3-2단계에서-모델링한-구체적인-클래스구체-전략들을-포괄하는-포괄개념을-인터페이스-및-추상클래스로-모델링한다&quot; style=&quot;color: #000000;&quot; href=&quot;https://github.com/WJLee222/Design_Pattern/blob/main/Behavioral%20pattern/Strategy.md#3-2%EB%8B%A8%EA%B3%84%EC%97%90%EC%84%9C-%EB%AA%A8%EB%8D%B8%EB%A7%81%ED%95%9C-%EA%B5%AC%EC%B2%B4%EC%A0%81%EC%9D%B8-%ED%81%B4%EB%9E%98%EC%8A%A4%EA%B5%AC%EC%B2%B4-%EC%A0%84%EB%9E%B5%EB%93%A4%EC%9D%84-%ED%8F%AC%EA%B4%84%ED%95%98%EB%8A%94-%ED%8F%AC%EA%B4%84%EA%B0%9C%EB%85%90%EC%9D%84-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%B0%8F-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C-%EB%AA%A8%EB%8D%B8%EB%A7%81%ED%95%9C%EB%8B%A4&quot;&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #1f2328; text-align: start;&quot;&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 2단계에서 모델링한 클래스들을, 포괄개념인 인터페이스를 구현하는 하위 구체전략 클래스(Concrete Strategy)로써 인터페이스와 연결한다.&lt;/h4&gt;
&lt;/div&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;style5&quot; /&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;code&gt;문제점2&lt;/code&gt; 해결법(메서드 클래스화)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 메서드로 모델링되었던 move,attack 메서드를 클래스로 모델링해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 이동하는 개개의 알고리즘 둘을 클래스로 모델링하였고, 공격하는 개개의 알고리즘 둘도 클래스로 모델링하였다.&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/37805834-56a1-4048-88d1-a25bbb46f7bf&quot; /&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;이동-공격 알고리즘(전략Strategy)들을 클래스로 모델링하였으니, 해당 클래스들을 사용할 수 있도록 기존 로봇 클래스들을 변경시키면 아래와 같다.&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;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&amp;lt;문제점들을 보완한 최종 설계&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 align=&quot;center&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;&lt;code&gt;&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/07a976f0-6d08-4ca6-a022-b343f8a71cd9&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Robot {

    private String name;
    private MovingStrategy movingStrategy;
    private AttackStrategy attackStrategy;

    public void setMovingStrategy(MovingStrategy movingStrategy) {
        this.movingStrategy = movingStrategy;
    }

    public void setAttackStrategy(AttackStrategy attackStrategy) {
        this.attackStrategy = attackStrategy;
    }

    public void move(){
        this.movingStrategy.move();
    };
    public void attack(){
        this.attackStrategy.attack();
    };

    public Robot(String name){this.name=name;}
    public String getName() {return name;}

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class TaekwonV extends Robot{
    public TaekwonV(String name) {
        super(name);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class Atom extends Robot{
    public Atom(String name) {
        super(name);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class Sungard extends Robot{
    public Sungard(String name) {
        super(name);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public interface MovingStrategy {
    public void move();
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class FlyingStrategy implements MovingStrategy{

    @Override
    public void move() {
        System.out.println(&quot;can fly&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class WalkingStrategy implements MovingStrategy{

    @Override
    public void move() {
        System.out.println(&quot;can walk&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public interface AttackStrategy {
    public void attack();
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class MissileStrategy implements AttackStrategy{
    public void attack() {
        System.out.println(&quot;Missile&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class PunchStrategy implements AttackStrategy{
    public void attack() {
        System.out.println(&quot;punch&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Robot r1=new TaekwonV(&quot;WJLee1&quot;);
        Robot r2=new Atom(&quot;WJLee2&quot;);

        System.out.println(r1.getName());
        r1.setAttackStrategy(new MissileStrategy());
        r1.setMovingStrategy(new WalkingStrategy());
        r1.move();
        r1.attack();

        System.out.println(r2.getName());
        r2.setAttackStrategy(new PunchStrategy());
        r2.setMovingStrategy(new FlyingStrategy());
        r2.move();
        r2.attack();

        Robot r3=new Sungard(&quot;WJLee3&quot;);
        r3.setAttackStrategy(new MissileStrategy());
        r3.setMovingStrategy(new FlyingStrategy());
    }
}&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;이동-공격 메서드를 클래스로 추출했기때문에, TaeKwonV 와 Atom은 내부에 move()와 attack() 메서드를 포함하지않도록 변경했다.&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;새로운 이동방법이라던지 공격방법과 같은 전략이 추가되어도 기존설계에는 영향을 주지않게되고, TaeKwonV 나 Atom이 이동 및 공격 전략을 변경하여도 기존 설계와 코드는 영향받지않기때문에 OCP 원칙을 만족하게된다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Ex) TaeKwonV의 공격방법을 Missile =&amp;gt; Punch로 변경하려고한다면&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래처럼, 기존 TaeKwonV 클래스의 코드변경없이 setter 메서드를 이용하여 TaeKwonV의 공격방법을 변경할 수 있다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;r1.setAttackStrategy(new MissileStrategy()); //공격방법 =&amp;gt; 미사일&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;r1.setAttackStrategy(new PunchStrategy()); //공격방법 =&amp;gt; 펀치&lt;/code&gt;&lt;/pre&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;so, &lt;b&gt;&lt;code&gt;&amp;lt;문제점1&amp;gt; 해결&lt;/code&gt;&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;&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;&lt;br /&gt;&lt;br /&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;또한, 새로운 로봇으로 선가드를 만들고 태권v의 미사일 공격기능과 아톰의 날기기능을 따르도록하고자 하는경우,&lt;br /&gt;기존 코드 설계에서는 코드의 중복으로인해 OCP 위반 문제가발생하였지만 - 개선된 설계에서는 아래처럼 setter 메서드를 이용하여 변경 및 추가하고자하는 이동 및 공격 알고리즘(전략) 객체를 매개변수로 넘겨주면 끝이다.&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;즉, setter 메서드를 이용하여 필요에 따라 동적으로 구체적인 전략을 바꿀 수 있게된다.&lt;br /&gt;(어느 순간에는 공격 전략이 미사일로, 어느 순간에는 펀치로..)&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;이로써, 추후 태권v 의 공격 전략이 변경되어도 선가드의 코드 또한 같이 변경해줄 필요가 없어진다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;Robot r3=new Sungard(&quot;WJLee3&quot;);
r3.setAttackStrategy(new MissileStrategy());&lt;/code&gt;&lt;/pre&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align=&quot;center&quot; data-ke-size=&quot;size16&quot;&gt;so, &lt;code&gt;&amp;lt;문제점2&amp;gt; 해결&lt;/code&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;새로운 이동전략(이동 알고리즘)을 추가하는 경우에도 기존 코드의 변경없이 가능하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JumpingStrategy를 추가해보자.&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&lt;img src=&quot;https://github.com/user-attachments/assets/a66be6b8-4442-478f-af53-c2eecd04673e&quot; /&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class JumpingStrategy implements MovingStrategy{

    @Override
    public void move() {
        System.out.println(&quot;Jumping&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        Robot r1=new TaekwonV(&quot;WJLee1&quot;);

        System.out.println(r1.getName());
        r1.setMovingStrategy(new JumpingStrategy()); //Jumping 이라는 새로운 전략을 추가하고, r1객체의 이동전략을 Jumping으로 동적 변경.  
        r1.move();


    }
}&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;위처럼, MovingStrategy 인터페이스를 구현하여 Jumping이라는 새로운 전략(이동 알고리즘)을 추가할 수 있다.&lt;br /&gt;&lt;b&gt;OCP 위반없이.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&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;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제에서, 이동 알고리즘을 추상적으로 포괄하는 개념인 MovingStrategy 인터페이스를 &lt;br /&gt;&lt;b&gt;Strategy(전략) &lt;/b&gt;인터페이스라고 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제에서, 전략 인터페이스를 구현하는 Walking - Flying 과 같은 구체적인 이동 알고리즘 클래스들을&lt;br /&gt;&lt;b&gt;Concrete Strategy(구체 전략)&lt;/b&gt;클래스라고 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제에서, 이동 전략을 사용하는 사용자 입장인 Robot클래스를 &lt;b&gt;Context &lt;/b&gt;클래스라고한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠ &lt;b&gt;Context&lt;/b&gt;는 &lt;b&gt;구체적인 전략과 연관관계를 맺는 것이 아니라&lt;/b&gt;, 구체적인 전략들을 포괄하는 추상적인 개념인 &lt;b&gt;Strategy 인터페이스와 연관관계를 맺는다.&lt;/b&gt; 그래야 프로그램 실행 중에 알고리즘(전략) 선택변경이 가능해진다&lt;/p&gt;
&lt;/blockquote&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 Strategy 디자인 패턴은, 런타임 시점에(실행 중에) 알고리즘 전략을 선택하여 객체에게 다양한 동작을 할당해주는, 객체 동작을 실시간으로 &lt;span style=&quot;background-color: #ffc9af; color: #1a1918; text-align: start;&quot;&gt;동적으로 변경할 수 있도록 해주는&lt;/span&gt;&amp;nbsp;행위 디자인 패턴인 것이다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>디자인 패턴</category>
      <category>Strategy</category>
      <category>Strategy 패턴</category>
      <category>디자인 패턴</category>
      <category>전략 패턴</category>
      <category>행위 패턴</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/11</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%A0%84%EB%9E%B5Strategy-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry11comment</comments>
      <pubDate>Sun, 29 Sep 2024 08:29:18 +0900</pubDate>
    </item>
    <item>
      <title>자바 소켓 통신</title>
      <link>https://basecoding.tistory.com/entry/%EC%9E%90%EB%B0%94-%EC%86%8C%EC%BC%93-%ED%86%B5%EC%8B%A0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;소켓 통신이란?&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TCP/IP 네트워크를 이용해 쉽게 통신 프로그램을 작성하도록 지원하는 기반 기술을 말한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;소켓(Socket)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;통신하는 두 프로세스 간의&amp;nbsp; 양방향 통신 링크의 한쪽 끝 단을 말한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;즉, 클라이언트와 서버간에 데이터를 주고받을 수 있게해주는 데이터 통로역할을 해주는 도구이다.&lt;/li&gt;
&lt;li&gt;이 소켓을 통해서 데이터를 보낼 수도있고 받을 수도있다.&lt;/li&gt;
&lt;li&gt;소켓은 특정 포트 번호와 연결되어있어서, 하나의 시스템 내에서 각각의 프로세스는 여러 개의 소켓들을 만들어 각자 자신의 통신을 처리해낼 수 있게된다.&lt;/li&gt;
&lt;li&gt;특히, 소켓은 네트워크 하부 구조와 상관없이 데이터 읽기/쓰기 인터페이스를 제공해준다. (자바에서 기본으로 제공해주는 스트림 클래스를 통해서 가능하다)&lt;/li&gt;
&lt;li&gt;&amp;nbsp;소켓으로부터 얻은 스트림을 통해서 데이터를 입출력하고, 해당 데이터는 소켓과 연결되어진 포트를 통해 다른 호스트와 통신을 할 수 있게된다.&lt;/li&gt;
&lt;/ul&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TlbI5/btsJOnJW50j/XaKBfOsAp27BBntcxhjJ61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TlbI5/btsJOnJW50j/XaKBfOsAp27BBntcxhjJ61/img.png&quot; data-alt=&quot;&amp;amp;lt;소켓 통신의 예시&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TlbI5/btsJOnJW50j/XaKBfOsAp27BBntcxhjJ61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTlbI5%2FbtsJOnJW50j%2FXaKBfOsAp27BBntcxhjJ61%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; alt=&quot;소켓 통신의 예&quot; loading=&quot;lazy&quot; width=&quot;696&quot; height=&quot;228&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;소켓 통신의 예시&amp;gt;&lt;/figcaption&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;이는 어떤 웹 브라우저가 웹서버에게 인터넷을 통해서 요청을 보내고 응답을 받는 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;현재 웹서버는 클라이언트로부터 요청을 받을 80번 포트와 연결되어진 서버 소켓을 유지하면서, 해당 서버 소켓으로 어떤 요청이 들어오는지 감지한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;한편 어떤 특정 웹 브라우저에서는, 그 자신의 고유한 3267번 포트와 연결되어진 소켓을 통해서 데이터를 보내거나 - 소켓으로부터 들어온 데이터를 읽어들일 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이러한 TCP/IP 에서 지원하는 TCP 소켓은, 보통&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;클라이언트 단의 소켓을 만들때사용해주는 Socket이라는 클래스&lt;/b&gt;와&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버 단의 소켓을 만들때사용해주는 ServerSocket&lt;/b&gt;이라는 총 2가지 클래스가 제공되어진다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;Socket 클래스&amp;nbsp;&lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&amp;nbsp;java.net.Socket&lt;/li&gt;
&lt;li&gt;서버와 TCP 연결을 위한 클라이언트 소켓&lt;/li&gt;
&lt;li&gt;객체 생성시 통신하고자하는 서버측의 주소와 port 번호를 인자로 받음 (이 서버호스트의 이 포트에 open 된 프로세스에 접속요청하겠다)&lt;/li&gt;
&lt;li&gt;※ 해당 호스트를 찾을 수 없거나 해당 port 가 미사용중인경우엔 UnknownException 예외처리가 필요함&lt;/li&gt;
&lt;li&gt;※ 네트워크 오류로 서버 접속이 불가할경우 IOExeption 예외처리가 필요함&amp;nbsp;&lt;/li&gt;
&lt;li&gt;※ 소켓 연결 종료시 close() 메서드 호출해줘야함 ( 이 경우에도 IOExeption 예외처리가 필요)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;getInputStream() &amp;amp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;getOutputStream()&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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; getInputStream() &amp;amp; getOutputStream()&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이 Socket 클래스에는 2개의 주요 메서드가 있는데, 하나는 &lt;b&gt;소켓으로부터 데이터를 읽어들일 수 있는(수신) 입력 스트림을 반환해주는 getInputStream 메서드&lt;/b&gt;이고, 다른 하나는 &lt;b&gt;현재 소켓을 통해서 서버측 호스트로 데이터를 보낼때(송신) 즉 출력할떄 사용하는 출력 스트림을 반환해주는 getOutputStream 메서드&lt;/b&gt;이다. 이 스트림은 바이트 단위로 입출력하기에 다른 스트림과 연계하여 문자 단위로 입출력하도록 확장도 가능하다.&amp;nbsp;&lt;/blockquote&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;u&gt;ServerSocket 클래스&amp;nbsp;&lt;/u&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&amp;nbsp;java.net.ServerSocket&lt;/li&gt;
&lt;li&gt;클라이언트로부터 연결 요청을 수락하고, 그에따라 실질적으로 통신을 수행하는 서버측 TCP소켓 객체를 생성해주는 역할을하는 클래스. 즉, ServerSocket&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;은 단지 서버 측에서 클라이언트의 연결 요청을 수신하기 위해서만 사용되는 클래스이므로 &lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;클라이언트와의 데이터 통신에는 사용되지 않는다. &lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;&lt;b&gt;클라이언트와의 통신을 위해선 accept() 메서드가 반환해주는 Socket 객체가 필요&lt;/b&gt;하다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ServerSocket 객체를 생성하고 해당 객체의 accept()메서드를 호출하면 클라이언트로부터의 연결요청을 대기하게된다. 대기하던 중에 클라이언트로부터 연결요청을 받게되면 accept() 메서드가 이 요청을 수락하고 Socket 객체를 반환해준다.(새로운 클라이언트 소켓 생성)&lt;br /&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;ServerSocket 객체가 아니라 반환된 이 소켓 객체가 클라이언트와의 통신을 담당한다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;즉, &lt;/b&gt;&lt;b&gt;&lt;b&gt;ServerSocket 객체는 클라이언트로부터 연결 요청을 받고 처리하는 용도이고, 한 클라이언트로부터 연결 요청을 수락하여 통신용 &lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;Socket&lt;/span&gt;&lt;span style=&quot;color: #666666; text-align: left;&quot;&gt;객체를 반환해주고나면 서버소켓은 지정된 포트에서 또 다른 클라이언트들의 연결 요청을 &lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;대기한다.&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;서버 소켓은 &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;클라이언트 소켓의 연결 요청을 받아들이는 역할만 수행할 뿐, 직접적인 데이터 송수신은 서버 소켓의 연결 요청 수락의 결과로 만들어지는 새로운 소켓을 통해 처리된다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;서버는 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;ServerSocket의&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;accept()&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;메서드를 통해 생성된&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt; 클라이언트 소켓(&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;Socket&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;객체)을 가지고 입출력 스트림을 사용하여 &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;클라이언트와 통신. &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;출력 스트림과 입력 스트림을 통해 클라이언트에게 데이터를 보내고 받을 수 있게된다 (양방향 통신).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;ServerSocket&lt;span&gt;&amp;nbsp;&lt;/span&gt;객체를 생성할 때 포트 번호만 인자로 받음(현재 이 포트로부터 클라이언트의 연결요청을 기다리겠다)&lt;/li&gt;
&lt;li&gt;만약 해당 포트가 사용중이라면 IOExeption 발생 -&amp;gt; 예외처리 필요&lt;/li&gt;
&lt;/ul&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M707a/btsJNPNVvLo/2a3vfzNk1uXcP8y9KJrStk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M707a/btsJNPNVvLo/2a3vfzNk1uXcP8y9KJrStk/img.png&quot; data-alt=&quot;&amp;amp;lt;클라이언트와 서버 연결 과정&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M707a/btsJNPNVvLo/2a3vfzNk1uXcP8y9KJrStk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM707a%2FbtsJNPNVvLo%2F2a3vfzNk1uXcP8y9KJrStk%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;1198&quot; height=&quot;431&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;431&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;클라이언트와 서버 연결 과정&amp;gt;&lt;/figcaption&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;HTTP 통신과 소켓 통신의 차이&lt;/b&gt;&lt;/h3&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;/b&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;반면 HTTP 통신은, 단순히 클라이언트에서 서버로 요청을 보내고 서버가 응답해주는 &lt;b&gt;단방향 통신&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;그렇기에 http 통신은 지속적인 유지가 필요한 실시간통신보다는 필요한 경우에만 서버로 요청보내고 응답을 받고자하는 경우에 유용하고, 소켓 통신은 실시간으로 계속 양방향으로 연결을 유지하면서 데이터를 주고받는 경우에 유용하다.&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;소켓 &amp;amp; 스트림&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;&lt;b&gt;소켓&lt;/b&gt;은 데이터 전송을 위한 연결을 설정&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;하고, &lt;b&gt;스트림&lt;/b&gt;은 이 연결을 통해 실제 &lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;데이터를 읽고 쓰는 기능을 제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉,&lt;b&gt; 소켓&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;은 네트워크 연결을 관리하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;스트림&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;은 그 연결을 통해 데이터를 송수신하는 수단인 것이다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;소켓이 없으면 데이터 전송을 위한 경로가 없고, 스트림이 없으면 데이터를 읽거나 쓸 수 없다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;이 둘은 소켓 통신에 있어서 필수적이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>네트워크프로그래밍(JAVA)</category>
      <category>네트워크프로그래밍</category>
      <category>소켓</category>
      <category>소켓통신</category>
      <category>입출력스트림</category>
      <category>자바 소켓통신</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/10</guid>
      <comments>https://basecoding.tistory.com/entry/%EC%9E%90%EB%B0%94-%EC%86%8C%EC%BC%93-%ED%86%B5%EC%8B%A0#entry10comment</comments>
      <pubDate>Fri, 27 Sep 2024 03:12:13 +0900</pubDate>
    </item>
    <item>
      <title>네트워크 통신에서 포트(Port) 란?</title>
      <link>https://basecoding.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%ED%86%B5%EC%8B%A0%EC%97%90%EC%84%9C-%ED%8F%AC%ED%8A%B8Port-%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 컴퓨터 네트워크를 접할때, 포트라는 단어를 매우 많이 접하게된다. 우리가 주로 포트를 떠올리면 랜선 포트, HDMI 포트, 공유기 포트 등등 물리적인 요소를 꽂는 곳이라는 생각을 하게되어, 자칫 이 포트를 호스트 컴퓨터에 부착되어있는 슬롯같은 물리적인 것으로 오해를 하곤한다.&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1a1918;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;현재 네트워크 상에서 클라이언트와 서버가 통신을통해 데이터를 주고받을 예정이라고 가정해보자. 이때 클라이언트는 &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1a1918;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;해당 서버의 ip주소와 MAC 주소만을 가지고 해당 서버에 요청을 보내고 데이터통신을 해나갈 수 있는 것일까?&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 불가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;여기서 잠깐! &lt;br /&gt;&lt;br /&gt;※&amp;nbsp; 클라이언트와 서버는 각각의 컴퓨터에서 실행되는 프로세스를 의미하지만, 그 프로세스가 실행되는 컴퓨터로도 혼용되어 지칭하기도 한다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;호스트는 컴퓨터 그 자체를 의미하고, 클라이언트와 서버는 그 컴퓨터에서 실행되는 프로그램(프로세스)을 의미한다.&amp;nbsp;&lt;br /&gt;클라이언트(ex 웹브라우저)를 실행중인 컴퓨터를 클라이언트 컴퓨터, 서버(ex 구글 웹서버) 를 실행중인 컴퓨터를 &lt;br /&gt;서버컴퓨터라고 분리하여 알아두면 좋을 것 같다.&lt;br /&gt;&lt;br /&gt;+ 프로세스는 프로그램이 메모리에 로딩되어 실행중인 상태를 말한다. 둘은 엄연히 다른 개념이다.&amp;nbsp;&lt;/blockquote&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;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;클라이언트는 IP 주소와 MAC 주소로 서버가 실행 중인 호스트를 찾는다하더라도, 호스트가 해당 서버 외에도 여러 다른 서버 프로세스들을 실행중인 경우라면 클라이언트가 통신하고자하는 서버를 특정하는 것은 불가능할 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;IP 주소와 MAC 주소는 호스트까지의 정보이지, 해당 서버 프로세스까지의 정보는 없기때문이다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;대부분의 컴퓨터에서는 여러 개의 프로세스들이 동시에 실행되고 있어서(ex. 한 컴퓨터에서 동시에 실행중인 카카오톡 - 인스타그램 등등), 이 여러개의 프로세스 중 어느 프로세스가 내가 통신하려는 프로세스인지를 명시해주어야 서버와의 통신이 가능해지는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot; 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;background-color: #ffffff; color: #1a1918; text-align: start;&quot;&gt;이때 프로세스 특정을 위해 필요한 것이 바로 &lt;b&gt;포트&lt;/b&gt;이다.&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;포트는 &lt;b&gt;호스트 내에서 프로세스를 식별하는 데 사용되는 번호&lt;/b&gt;로, 호스트에서 실행중인 각 프로세스는 각각 다른 포트 넘버를 할당받고있다. (카카오톡은 28000번 포트, 인스타그램은 28001번 포트..)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&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;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;각 프로세스는 각각 다른 포트 넘버를 할당받고있기때문에, 우리가 TCP 통신에서, 패킷에 통신하고자하는(요청을 보내고자하는) 서버의 포트넘버 정보를 추가하여 보내면 해당 포트넘버에 해당하는 프로세스에게 요청을 보낼 수 있게됨으로써 해당 프로세스와 통신이 가능해지는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;624&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nBgJF/btsJMzRlZen/66Xva83zA4eFzPRujwYRhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nBgJF/btsJMzRlZen/66Xva83zA4eFzPRujwYRhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nBgJF/btsJMzRlZen/66Xva83zA4eFzPRujwYRhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnBgJF%2FbtsJMzRlZen%2F66Xva83zA4eFzPRujwYRhK%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;624&quot; height=&quot;232&quot; data-origin-width=&quot;624&quot; data-origin-height=&quot;232&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;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;포트번호는 0~65,535 번까지 존재한다.&lt;/span&gt; &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;&lt;/span&gt;&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;이 여러개의 포트넘버 중에서 0~1023번까지는 &lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&lt;span&gt;주요 통신을 위해서 미리 정해져&lt;/span&gt;&lt;/span&gt;있는 &lt;b&gt;well - known 포트넘버&lt;/b&gt;로, 사용자가 임의로 사용할 수 없는 포트넘버이다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ex) http 통신은 80번 포트, ssh 통신은 22번 포트&lt;/blockquote&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;그리고 1024~49151번까지는 &lt;b&gt;Registered 포트넘버&lt;/b&gt;이며, well - known 포트넘버처럼 널리 사용되어지는 포트는 아니지만, 이 번호들도 특정 응용프로그램들을 위해 등록되어있는 번호이기에 사용자가 임의로 사용할 수 없는 포트넘버이다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ex) MySQL 통신은 3306번 포트, 윈도우 원격 접속 통신은 3389번 포트&lt;/blockquote&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;이 외에, 49152~65535번 까지는 &lt;b&gt;Dynamic 포트넘버&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;span style=&quot;background-color: #ffffff; color: #1a1918; text-align: left;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;</description>
      <category>네트워크프로그래밍(JAVA)</category>
      <category>네트워크프로그래밍</category>
      <category>데이터통신</category>
      <category>포트</category>
      <category>포트넘버</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/9</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%ED%86%B5%EC%8B%A0%EC%97%90%EC%84%9C-%ED%8F%AC%ED%8A%B8Port-%EB%9E%80#entry9comment</comments>
      <pubDate>Thu, 26 Sep 2024 02:18:23 +0900</pubDate>
    </item>
    <item>
      <title>[디자인 패턴] 싱글톤(Singleton) 패턴 - 예제를 통해 알아보기</title>
      <link>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%8B%B1%EA%B8%80%ED%86%A4Singleton-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;h1&gt;Singleton Pattern&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Ex&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;A 클래스의 객체를 하나만 생성해야 하는데 좋은 방법 없을까?&quot;&lt;br /&gt;&lt;br /&gt;=&amp;gt; Singleton 패턴을 적용시켜보자.&lt;/p&gt;
&lt;/blockquote&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;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Singleton is a creational design pattern that lets you ensure that a class has &lt;b&gt;only one instance&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;싱글톤은 &lt;code&gt;클래스당 오직 하나의 객체&lt;/code&gt; 를 생성하고 이 생성된 객체를 어디서든(타 클래스 인스턴스들) 참조할 수 있도록 하는 생성 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 단 하나의 유일한 객체를 생성해내기위한 패턴이다.&lt;/p&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메모리 절약 &amp;amp; 속도 이점 &amp;amp; 데이터 공유 용이&lt;/h3&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;br /&gt;그렇기에 리소스를 많이 차지하는 객체일경우, 싱글톤 패턴을 적용시키서 이 하나의 객체를 통해서 여러곳에서 참조한다면 메모리 절약에 매우 효과적이고, 이미 생성된 객체를 활용하는 것이니 속도면에서도 이점이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예재를 통한 Singleton 이해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;사용자의 은행 계좌를 나타내는 Account 클래스와, 해당 계좌에서의 입금/출금 발생 내역을 기록하는 로깅역할을 하는 Logger 클래스를 통해 싱글톤 패턴을 이해해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;&amp;lt;&lt;i&gt;기본 사례&lt;/i&gt;&amp;gt;&lt;/div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;  public class Account {
    private String owner;
    private int balance;
    private Logger myLogger;

    public void setLogger(Logger myLogger) {
        this.myLogger = myLogger;
    }

    public Account(String owner, int balance) {
        this.owner = owner;
        this.balance = balance;
        this.myLogger = new Logger();
    }

    public String getOwner() {
        return owner;
    }

    public int getBalance() {
        return balance;
    }

    public void deposit(int money) {
        myLogger.log(&quot;owner&quot; + &quot; : &quot; + this.getOwner() + &quot; deposit &quot; + money);
        balance += money;
    }

    public void withdraw(int money) {
        if (balance &amp;gt;= money) {
            myLogger.log(&quot;owner&quot; + &quot; : &quot; + this.getOwner() + &quot; withdraw &quot; + money);
            balance -= money;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;  public class Logger {
    private final String LOGFILE = &quot;log.txt&quot;;
    private PrintWriter writer;

    public Logger() {
        try {
            FileWriter fw = new FileWriter(LOGFILE);
            writer = new PrintWriter(fw, true);
        } catch (IOException e) {
        }
    }

    public void log(String message) {
        SimpleDateFormat formatter = new SimpleDateFormat(&quot;yyyy-MM-dd 'at' HH:mm:ss z&quot;);
        Date date = new Date(System.currentTimeMillis());
        writer.println(formatter.format(date) + &quot; : &quot; + message);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;  public class Main {
    public static void main(String[] args) {
        Account acct1 = new Account(&quot;WJLee1&quot;, 1000000);
        acct1.deposit(20000);
        Account acct2 = new Account(&quot;WJLee2&quot;, 2000000);
        acct2.withdraw(5000);
        acct2.withdraw(2000);
    }
}

&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;위 코드를보면, Account 인스턴스 하나당 새로운 Logger 인스턴스 하나를 생성해서 1대1로 대응되는 관계를 보인다.&lt;br /&gt;그래서 Logger 인스턴스가 생성될때마다 log.txt파일을 새로 오픈하고 기존의 log.txt 파일에 쓰인 내용들을&lt;br /&gt;덮어써버리는 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기위해선 하나의 Logger 인스턴스를 만들고 이를 모든 account 인스턴스가 공유하도록하면&lt;br /&gt;log.txt 파일에 다음 내용이 덮어쓰여지지않고 다음줄에 출력될 것이다.&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;div align=&quot;center&quot;&gt;&amp;lt;&lt;i&gt;1차 &lt;/i&gt;&lt;i&gt;코드 개선&lt;/i&gt;&amp;gt;&lt;/div&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt; public class Main {
    public static void main(String[] args) {
        Logger logger = new Logger(); //하나의 Logger 인스턴스 생성
        Account acct1 = new Account(&quot;WJLee1&quot;, 1000000);
        acct1.setLogger(logger);
        acct1.deposit(20000);
        Account acct2 = new Account(&quot;WJLee2&quot;, 2000000);
        acct2.setLogger(logger);
        acct2.withdraw(5000);
        acct2.withdraw(2000);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// Account 클래스의 생성자 메서드 실행시마다 Logger 인스턴스를 생성하던 구문을 제거  
     public Account(String owner, int balance) {
        this.owner = owner;
        this.balance = balance;
//        this.myLogger = new Logger();
    }
    public void setLogger(Logger myLogger) {
        this.myLogger = myLogger;
    }&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;위 코드처럼, 메인 메서드에서 하나의 로거 객체를 생성한다음 이 객체를 각 어카운트 객체의 setter 메서드를 통해&lt;br /&gt;각 어카운트 객체들이 공유하도록 세팅하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자, 현재 코드상으로는 하나의 로거 객체를 생성하고 -&amp;gt; 이 객체를 여러 어카운트 객체들이 공유하는 우리가 원하는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모습이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&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;gt; 바로, 하나의 인스턴스가 아닌 다수의 Logger 인스턴스 생성이 가능하다는 점이다.&lt;br /&gt;싱글턴 패턴의 핵심은 하나의 객체를 생성하고 이를 다른 인스턴스들이 공유하도록하는 개념이다. 위와 같은 코드로&lt;br /&gt;프로그램을 구성할 경우 싱글턴의 취지와 부합하지 않게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;그렇다면 여러 Logger 인스턴스를 생성하지 못하게하도록하는 수단을 제공해줘야할 것이다. &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;그럼 Logger 인스턴스를 단 하나만 생성할 수 있도록 제어할 수 있는 방법은 무엇이 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ef6f53;&quot;&gt;★&lt;/span&gt;&lt;span style=&quot;background-color: #ef6f53;&quot;&gt;★&lt;/span&gt;&lt;span style=&quot;background-color: #ef6f53;&quot;&gt;단일 객체 생성을 위한 싱글턴 패턴의 3가지 규칙&lt;/span&gt;&lt;span style=&quot;background-color: #ef6f53;&quot;&gt;★&lt;/span&gt;&lt;span style=&quot;background-color: #ef6f53;&quot;&gt;★&lt;/span&gt;&lt;/h3&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Logger 클래스 내에 단일 logger 객체의 레퍼런스를 저장하기 위한 &lt;code&gt;static&lt;/code&gt; 정적 참조 변수를 필드로 둔다.&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;2. Logger 인스턴스를 &lt;code&gt;new&lt;/code&gt; 연산자로 생성하려고 할 때 객체 생성을 제어하기 위해, 외부 클래스에서 Logger 클래스의 생성자 메서드에 접근하지 못하도록 생성자의 접근 지정자를 &lt;code&gt;private&lt;/code&gt;으로 설정한다.&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;3. 단일 Logger 객체를 반환해주는 역할을 하는 &lt;code&gt;getter&lt;/code&gt; 메서드를 정의한다.&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;hr data-ke-style=&quot;style1&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;위의 3가지 규칙이 지켜져야 비로소 싱글턴 패턴이다라고 할 수 있다.&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;이러한 싱글턴 패턴은 static 정적 참조 변수의 초기화 시기에따라 &lt;b&gt;Eager initialization&lt;/b&gt; (이른 초기화 방식) &amp;amp; &lt;b&gt;Lazy initialization&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Singleton 구현 &amp;lt;&lt;b&gt;Eager initialization&lt;/b&gt; &amp;amp; &lt;b&gt;Lazy initialization&lt;/b&gt;&amp;gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Eager Initialization (이른 초기화 방식)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;먼저 Eager Initialization 방식을 적용시킨 싱글턴 패턴으로 구현된 프로그램의 경우엔, static 정적 참조 변수를 선언함과 동시에 new 를 통해 단일 인스턴스를 초기화해주는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Logger {
    private final String LOGFILE = &quot;log.txt&quot;;
    private PrintWriter writer;
//static 정적 참조 변수를 선언함과 동시에 new 를 통해 단일 인스턴스를 초기화
    private static Logger instance = new Logger(); 
//생성자의 접근 지정자를 `private`으로 설정
private Logger() {
        try {
            FileWriter fw = new FileWriter(LOGFILE);
            writer = new PrintWriter(fw, true);
        } catch (IOException e) {}
    }
    public static Logger getInstance() { return instance; } //정적 필드 instance를 반환해주는 정적 메서드 getInstance
    public void log (String message) {
        SimpleDateFormat formatter= new SimpleDateFormat(&quot;yyyy-MM-dd 'at' HH:mm:ss z&quot;);
        Date date = new Date(System.currentTimeMillis());
        writer.println(formatter.format(date) + &quot; : &quot; + message);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Account {
    private String owner;
    private int balance;
    private Logger myLogger;

    public Account(String owner, int balance) {
        this.owner = owner;
        this.balance = balance;
        this.myLogger = Logger.getInstance(); //Logger 클래스의 정적 메서드 호출
    }

    public String getOwner() {
        return owner;
    }

    public int getBalance() {
        return balance;
    }

    public void deposit(int money) {
        myLogger.log(&quot;owner&quot; + &quot; : &quot; + this.getOwner() + &quot; deposit &quot; + money);
        balance += money;
    }

    public void withdraw(int money) {
        if (balance &amp;gt;= money) {
            myLogger.log(&quot;owner&quot; + &quot; : &quot; + this.getOwner() + &quot; withdraw &quot; + money);
            balance -= money;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {

        Account acct1 = new Account(&quot;WJLee1&quot;, 1000000);
        acct1.deposit(20000);
        Account acct2 = new Account(&quot;WJLee2&quot;, 2000000);
        acct2.withdraw(5000);
    }
}


&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Lazy initialization (늦은 초기화 방식)&lt;/h3&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;br /&gt;반면 Lazy initialization 방식을 적용시킨 싱글턴 패턴으로 구현된 프로그램의 경우엔, 실제 객체가 사용되는 시점까지 객체 생성을 미루다가 객체가 사용되려는 시점에 getter 메서드를 통해 객체가 null 값이면 객체를 새로 생성하고 객체가 이미 존재한다면 바로 이때 단일 객체를 생성하고 반환하도록 구현한 방식이다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;public class Logger {
    private final String LOGFILE = &quot;log.txt&quot;;
    private PrintWriter writer;
    private static Logger instance;
    private Logger() {
        try {
            FileWriter fw = new FileWriter(LOGFILE);
            writer = new PrintWriter(fw, true);
        } catch (IOException e) {}
    }
    public static Logger getInstance() {
      if(instance==null)
          instance=new Logger();
      return instance; }

    public void log (String message) {
        SimpleDateFormat formatter= new SimpleDateFormat(&quot;yyyy-MM-dd 'at' HH:mm:ss z&quot;);
        Date date = new Date(System.currentTimeMillis());
        writer.println(formatter.format(date) + &quot; : &quot; + message);
    }
}&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;이러한 이유로 Lazy initialization 방식은 싱글톤 객체가 필요할 때만 객체를 생성하기때문에 메모리 사용을 최적화할 수 있다는 장점이있다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;하지만, Lazy initialization 방식에는 중요한 단점이 하나있다. 바로 밑에서 설명할 다중 스레드(Multi-Thread) 환경에서 싱글턴의 단일 객체 원칙을 깨뜨릴 수 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Multi-Thread 환경에서의 (Lazy initialization) Singleton Pattern&lt;/h2&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;먼저 각 계좌를 소유하는 사용자 User 스레드 클래스를 정의하고 다수의 User 스레드 객체들을 생성하여 다중 스레드 환경을 조성해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public class User extends Thread{

    public User(String name){super(name);}

    @Override
    public void run() {
        Random r= new Random();
        Account acct= new Account(Thread.currentThread().getName(), r.nextInt(1000000));
        if(r.nextBoolean())
            acct.withdraw(r.nextInt(acct.getBalance()));
        else
            acct.deposit(r.nextInt(acct.getBalance()));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {

        User[] users = new User[10];
        for(int i=0; i&amp;lt;10; i++){
            users[i]= new User(&quot;insang&quot;+i);
            users[i].start();
        }
    }
}&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;다중 스레드 환경이 조성된 이후 스레드들을 동시에 실행시키게되면서, 각 User 객체가 getInstance 정적 메서드를 동시에 실행하게되는 스레드 경합이 발생하면 -&amp;gt; 해당 스레드들은 동일한 타이밍에 instance 객체가 null인 상태임을 확인하게되고, 이로인해 단일 객체가 아닌 여러개의 객체가 생성될 수 있다는 문제가 발생하게되는 것이다.&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;이러한 스레드 경합으로인한 문제를 해결하기 위해선 자바에서 제공하는 synchronized 키워드를 사용하면 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 반면 Eager Initialization의 경우엔 Logger 클래스 로딩 시점에서 이미 단일 인스턴스를 생성했기때문에 다중 스레드 환경에서 각 스레드가 동시에 메서드에 접근하여 Logger 객체를 추가로 새로 생성하게되는 - 싱글턴의 단일 객체 원칙을 깨뜨리는 일은 발생하지 않는다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스레드 경합문제 해결방법 by synchronized&lt;/h2&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;synchronized 키워드는 자바에서 제공하는 스레드 동기화를 위한 장치로, synchronized 키워드가 적용된 코드블록은 동기화가 설정된 임계영역으로 지정되어, 어떠한 스레드가 해당 코드블록에 진입할 경우 코드블록에 lock이 걸리고 해당 스레드가 코드블록을 모두 수행하고나면 자동으로 unlock 되어지면서 대기하고있던 다른 스레드 중 하나가 lock을 소유하여 실행하게하는 동기화 기법이다. 임계영역에 lock 이 걸리면 다른 스레드는 대기해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Logger 객체 생성을 담당하는 getInstance 정적 메서드에 synchronized를 적용하여 스레드들을 동기화해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;public class Logger {
    private final String LOGFILE = &quot;log.txt&quot;;
    private PrintWriter writer;
    private static Logger instance;
    private Logger() {
        try {
            FileWriter fw = new FileWriter(LOGFILE);
            writer = new PrintWriter(fw, true);
        } catch (IOException e) {}
    }
     public static synchronized Logger getInstance() { //synchronized 키워드로 getInstance메서드를 임계영역으로 설정
        if(instance==null)
            instance=new Logger();

        return instance; }
    public void log (String message) {

        SimpleDateFormat formatter= new SimpleDateFormat(&quot;yyyy-MM-dd 'at' HH:mm:ss z&quot;);
        Date date = new Date(System.currentTimeMillis());
        writer.println(formatter.format(date) + &quot; : &quot; + message);
    }
}
&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;위와 같이 getInstance 정적 메서드에 synchronized를 적용함으로써 Eager Initialization 싱글턴에서의 스레드 경합문제를 해결하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 방법마저도 문제가 하나있다. 임계영역에서의 lock 으로 인해 스레드들이 대기하면서 성능의 저하가 발생한다는 문제이다. 이 문제도 한번 해결해보자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;synchronized로 인한 성능저하문제 해결방법 by DCL&lt;/h2&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;br /&gt;getInstance 메서드에서, 만약 instance 가 null 이 아니라면, 즉 단일 객체가 생성된 상태라면 해당 객체를 반환해주기만하면 끝이다. 따라서 instance가 null이 아닌 경우까지 synchronized로 매번 스레드 동기화를 적용할 필요는 없다. 굳이 이 getInstance 메서드 전체를 locking 시켜서 다른 스레드들을 대기시킬 필요가 없다는 것. getInstance 호출시마다 매번 발생하는 synchronized로 인한 lock 과정이 바로 성능적 비효율성을 초래하는 것이다. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;=&amp;gt; getInstance 메서드 자체를 synchronized 키워드로 임계영역으로 적용을 해뒀기에 어떠한 스레드가 getInstance 메서드를
locking 하고 수행하는 동안에는 다른 스레드들은 이 메서드 자체에 진입하지 못하므로, instance 가 null 이 아닌 경우임에도
불구하고 바로바로 instance 를 리턴받지못하고 현재 getInstance 에 locking하여 사용중인 스레드가 lock을 해제할때까지
대기해야하는 성능적인 비효율이 발생한다.

lock을 기다리는 동안 스레드는 CPU 자원을 소모하며 대기하게되는데, 이는 시스템 자원의 비효율적인 사용을 초래하기 때문이다.&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;br /&gt;이러한 문제를 해결하기 위해, getInstance 메서드 전체에 synchronized를 적용하는 대신, instance가 null인 경우의 if 문 내부 블록에 또 한 번 instance가 null인지 확인하는 if 문을 감싸는 코드블럭에 synchronized를 적용하는 DCL(Double Check Locking) 기법을 사용할 수 있습니다. getInstance 메서드를 아래와 같이 바꿔주자. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;     public static Logger getInstance() {
        if(instance==null)
            synchronized (Logger.class){ //getInstance 메서드 자체가 아닌, if 문을 감싸는 코드블럭에 synchronized를 적용. 
                if(instance==null)
                    instance=new Logger();
            }

        return instance;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;synchronized (Logger.class) { ... } 블록은 일반 메서드가 아닌 임계영역을 지정하기위한 코드 블록이라고 생각하면 된다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 DLC 적용를 통해, instance가 null인 최초의 경우에만 synchronized를 적용하여 lock을 획득하고, 그 이후에는 스레드의 대기과정 없이 바로바로 인스턴스를 반환할 수 있다.&lt;br /&gt;기존의 getInstance 메서드 자체에 synchronized 를 적용시키던 방식의 성능상의 단점을 보완해낼 수 있게된 것이다.&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;자. DCL도 제대로 잘 동작하고 시스템 효율상의 문제까지도 잘 해결했다. 그러나 진짜 마지막으로, 미묘한 문제가 하나 남아있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 new 연산자로 객체를 생성하면,&lt;/p&gt;
&lt;p 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;br /&gt;&lt;b&gt;1단계: 해당 객체를 위한 메모리를 힙 영역에 할당하는 명령어&lt;/b&gt;&lt;br /&gt;&lt;b&gt;2단계: 객체의 생성자를 실행하여 초기화 작업을수행하는 명령어&lt;/b&gt;&lt;br /&gt;&lt;b&gt;3단계: 할당된 객체의 레퍼런스를 반환해주는 명령어&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서대로 순차적으로 명령어가 실행되는데, 이 순서는 컴파일러가 성능 최적화를 위해서 최적의순서대로 명령어를 reorder 하게된다(1-2-3, 1-3-2, 2-3-1 .... 등등). 이 컴파일러의 명령어 reorder로 인해 미묘한 문제가 발생하게된다.&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;만약 1-3-2 순서대로 컴파일러가 실행순서를 정했다고 가정해보자. 스레드1이 먼저 실행되면서 getInstance를 호출하여 &amp;lt;1&amp;gt;Logger 인스턴스를 생성하고 &amp;lt;3&amp;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;lt;2&amp;gt;단계 명령어인 객체초기화 과정을 거치지않은 상태에서, 그 사이에 새로운 스레드2가 실행되면서 getInstance를 호출하여 아까 생성한 초기화되지않은 객체를 반환받아서 사용하게되는 문제가 발생한다.&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;초기화되지않은 객체를 사용하는 것은 예기치 않은 동작이나 오류를 발생시키기에 NullPointerException 예외가 발생하여 프로그램에 결함이 발생하게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 최적화를 위해 컴파일러가 수행하는 명령어 reorder는 volatile 키워드를 통해서 금지시킬 수 있으니, 이 volatile 키워드를 이용하여 DLC의 문제점 해결이 가능하다.&lt;/p&gt;
&lt;/blockquote&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;br /&gt;DCL 적용시 이 점을 꼭 알고 적용하도록하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Demand(Lazy) Holder 방식&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 싱글턴 패턴을 구현하는 마지막 방식인 Demand(Lazy) Holder 방식을 알아보자.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Demand Holder 방식은 가장 많이 사용되는 싱글턴 구현 방식이다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Demand(Lazy) Holder 방식은 volatile 이나 synchronized 키워드 없이도 스레드의 동시성(경합) 문제를 해결할 수 있는 방식이다.&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class Logger {
        private final String LOGFILE = &quot;log.txt&quot;;
        private PrintWriter writer;
        private static Logger instance;
        public Logger() {
            try {
                FileWriter fw = new FileWriter(LOGFILE);
                writer = new PrintWriter(fw, true);
            } catch (IOException e) {}
        }
        public void log (String message) {
            System.out.println(this.toString());
            SimpleDateFormat formatter= new SimpleDateFormat(&quot;yyyy-MM-dd 'at' HH:mm:ss z&quot;);
            Date date = new Date(System.currentTimeMillis());
            writer.println(formatter.format(date) + &quot; : &quot; + message);
        }

        private static class LazyHolder { //정적 내부 클래스  
            public static final Logger INSTANCE = new Logger();
        }
        public static Logger getInstance() {
            return LazyHolder.INSTANCE; 
        }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;540&quot; data-origin-height=&quot;407&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/di4USA/btsJCY5587u/zVOHrK6vjZ3EhQB30X9pW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/di4USA/btsJCY5587u/zVOHrK6vjZ3EhQB30X9pW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/di4USA/btsJCY5587u/zVOHrK6vjZ3EhQB30X9pW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdi4USA%2FbtsJCY5587u%2FzVOHrK6vjZ3EhQB30X9pW1%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;540&quot; height=&quot;407&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;407&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;Logger 클래스 내부에 LazyHolder 내부클래스를 만들어두고, LazyHolder 클래스에 정적 상수 변수인 INSTANCE 를 선언함과동시에 Logger 객체를 생성하여 변수를 초기화시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;이제 외부에서 Logger 클래스의 getInstance 메서드를 호출하면 LazyHolder 클래스의 INSTANCE 값을 반환받는다.&lt;br /&gt;프로그램 시작시 Logger 클래스가 로딩이되어도, 외부에서 LazyHolder 클래스의 INSTANCE에 직접 접근할때까지는 내부클래스인 LazyHolder의 INSTANCE 값은 Logger 객체로 초기화되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Demand Holder 방식과 eager Initialization 방식은 유사해보이지만, eager Initialization의 경우엔 클래스 로딩할때 instance 객체를 미리만들어두고 그 하나를 공유해서 사용하는 방식이고, Demand Holder 방식은 단일 객체를 미리 만들어둔게 아니라 외부객체에서 getInstance 메서드를 호출할때 그때서야 객체를 생성한다는 점이 차이점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;상당히 간단하면서도 다중 스레드 환경에서 사용할 수 있다는 점이 Demand Holder 방식이 많이 쓰이는 이유이다.&lt;/p&gt;</description>
      <category>디자인 패턴</category>
      <category>디자인 패턴</category>
      <category>생성 패턴</category>
      <category>설계패턴</category>
      <category>싱글톤</category>
      <category>싱글톤 패턴</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/8</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-%EC%8B%B1%EA%B8%80%ED%86%A4Singleton-%ED%8C%A8%ED%84%B4-%EC%98%88%EC%A0%9C%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0#entry8comment</comments>
      <pubDate>Sun, 15 Sep 2024 07:19:36 +0900</pubDate>
    </item>
    <item>
      <title>객체 지향 프로그래밍과 절차 지향 프로그래밍 비교 분석</title>
      <link>https://basecoding.tistory.com/entry/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-%EC%A0%88%EC%B0%A8-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B9%84%EA%B5%90-%EB%B6%84%EC%84%9D</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;객체 지향 프로그래밍이란&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;여러 객체들의 &lt;b&gt;상호작용&lt;/b&gt;을 통해 SW 프로그램을&amp;nbsp;구현하는 프로그래밍 패러다임&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4EVOf/btsJzRsCnNZ/UOpLEGrpjKOU5VdsxLWDh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4EVOf/btsJzRsCnNZ/UOpLEGrpjKOU5VdsxLWDh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4EVOf/btsJzRsCnNZ/UOpLEGrpjKOU5VdsxLWDh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4EVOf%2FbtsJzRsCnNZ%2FUOpLEGrpjKOU5VdsxLWDh1%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;637&quot; height=&quot;360&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍은 SW 의 생산성을 향상시킴과 동시에 + 실세계의 일들을 객체들의 집합으로 보다 쉽게 표현하기위해 등장한 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;프로그래밍 페러다임입니다. &lt;u&gt;&lt;i&gt;대표적인 객체 지향 프로그래밍 언어 = JAVA&amp;nbsp;&lt;/i&gt;&lt;/u&gt;&lt;/span&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;/b&gt; 자동차 - 사람 - TV 등 우리 실생활 내에 존재하는 모든 것을 일컫는데, 예를 들어 사람은 이름 - 나이 - 신장 - 몸무게 등 다양한 특성들을 가진채 태어난 하나의 객체이며 이 각 인간이라는 객체는 &quot;말한다&quot; - &quot;먹는다&quot; - &quot;걷는다&quot; 등과 같은 다양한 행동 및 기능들을 가지고 있습니다. 여기서 인간의 특성들을 객체의 필드(맴버 변수) - 인간의 행동 및 기능들이 메서드(맴버 함수)가 됩니다. 즉, 하나의 객체안에 데이터와 함수를 캡슐처럼 묶어서 표현이 가능해진 겁니다.&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;&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;/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;b&gt;코드의 재사용성 &amp;amp; SW의 생산성 높이고 - 서로 다른 객체들이 서로 상호작용해나가면서 하나의 프로그램을 구성하는 프로그래밍 형식이 바로 객체 지향 프로그래밍인 것입니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;절차 지향 프로그래밍이란&lt;/b&gt;&lt;/h3&gt;
&lt;p 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;&amp;nbsp;실행하고자 하는 절차를 정하고, 이 일련의 절차에 따라 순차적으로 프로그래밍하는 패러다임&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;391&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d0t3lG/btsJz0QxfMw/R5b1r24OKkNYWzBZaUoULK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d0t3lG/btsJz0QxfMw/R5b1r24OKkNYWzBZaUoULK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d0t3lG/btsJz0QxfMw/R5b1r24OKkNYWzBZaUoULK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd0t3lG%2FbtsJz0QxfMw%2FR5b1r24OKkNYWzBZaUoULK%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;391&quot; height=&quot;293&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;293&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;u&gt;&lt;i&gt;대표적인 절차 지향 프로그래밍 언어 = C&amp;nbsp;&lt;/i&gt;&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;size16&quot;&gt;C언어의 프로그래밍처럼, 구상하고자하는 프로그램의 실행 절차-흐름을 정해두고 -&amp;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;반면, 프로그램이 함수들을 통해 유기적으로 연결되어있기에 추후 코드가 변경될 경우 이 변경이 그 뒤의 코드에도 영향을 미치기에 절차 지향 프로그래밍은 변경 및 유지보수성이 낮다는 단점이 있습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;둘의 차이점&lt;/h3&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터와 함수의 관계&amp;nbsp;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 지향 프로그래밍의 경우 하나의 객체 안에 데이터와 함수가 같이 캡슐처럼 묶어서 관리되는 반면, 절차 지향 프로그래밍의 경우 데이터를 전역으로 두거나 함수 내에 지역적으로 두거나하여 함수와 데이터를 별개의 관계로 따로 분리하여 관리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드의 재사용성 및 유지보수&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 지향 언어의 경우 캡슐화, 상속, 다형성을 통해 코드를 쉽게 재사용이 가능하고 유지보수도 매우 용이하여 대규모 프로그래밍에서도 빠르게 진행이 가능하다는 장점이 있습니다. 하지만 절차 지향 프로그래밍의 경우, 코드의 재사용이 빈약하고 유지보수성도 낮아서 코드가 길어질수록 프로그래밍이 객체 지향 언어에 비해 복잡하고 느려기에 대규모 프로그래밍에서는 관리가 어렵다는 단점이 있습니다.&amp;nbsp; &amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실행 속도&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그렇다고 객체 지향 프로그래밍이 절차 지향 프로그래밍에 비해 무조건 장점만 있는 것은 아닙니다. 객체 지향 프로그래밍의 경우, 어느 하나의 기능 사용을 위해 해당 기능이 포함된 거대 모듈을 통째로 import 하여 가져와야하는 경우가 있기에 프로그램의 크기가 증가하여 속도 측면에서는 절차 지향 프로그래밍이 더 유리합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>CS 지식</category>
      <category>객체 지향 언어</category>
      <category>객체 지향 언어 vs 절차 지향 언어 차이점</category>
      <category>절차 지향 언어</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/7</guid>
      <comments>https://basecoding.tistory.com/entry/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EA%B3%BC-%EC%A0%88%EC%B0%A8-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EB%B9%84%EA%B5%90-%EB%B6%84%EC%84%9D#entry7comment</comments>
      <pubDate>Thu, 12 Sep 2024 23:22:46 +0900</pubDate>
    </item>
    <item>
      <title>명품 웹프로그래밍 12장 4번 문제</title>
      <link>https://basecoding.tistory.com/entry/%EB%AA%85%ED%92%88-%EC%9B%B9%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-12%EC%9E%A5-4%EB%B2%88-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;pre id=&quot;code_1693804801012&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
	&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;
	&amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&amp;gt;
	&amp;lt;title&amp;gt;일기 보기&amp;lt;/title&amp;gt;
    &amp;lt;style&amp;gt;
        #a{font-weight: bold; text-align: center; width: 100px;}
        #b{width: 300px;overflow-wrap: break-word; }
        td {margin-left: 10px;border-bottom: 1px solid black;}
       
    &amp;lt;/style&amp;gt;
	&amp;lt;script&amp;gt;
	
	&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	&amp;lt;h3&amp;gt;일기 보기&amp;lt;/h3&amp;gt;
	&amp;lt;hr&amp;gt;
	
    &amp;lt;script&amp;gt;
        	document.write(&quot;&amp;lt;table style='background: aliceblue'&amp;gt;&quot;);
                for(var i=0; i&amp;lt;localStorage.length; i++)
                {
                    document.write(&quot;&amp;lt;tr&amp;gt;&amp;lt;td style='border: 1px solid green'&amp;gt;&quot;+(i+1)); 
                        document.write(&quot;&amp;lt;/td&amp;gt;&quot;);
                        document.write(&quot;&amp;lt;td id='a'&amp;gt;&quot;+localStorage.key(i)+&quot;&amp;lt;/td&amp;gt;&quot;);
                        document.write(&quot;&amp;lt;td&amp;gt;&amp;lt;div id='b'&amp;gt;&quot; + localStorage.getItem(localStorage.key(i)) + &quot;&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&quot;);
                }
    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;​&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1693804786555&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
	&amp;lt;meta charset=&quot;utf-8&quot;&amp;gt;
	&amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&amp;gt;
	&amp;lt;title&amp;gt;일기 쓰기&amp;lt;/title&amp;gt;
	&amp;lt;script&amp;gt;
        var date=new Date(2016,11,30);
        var year=date.getFullYear();
        var mon=date.getMonth();
        var dat=date.getDate();
        document.write(&quot;&amp;lt;h3&amp;gt;일기쓰기&amp;lt;/h3&amp;gt;&amp;lt;hr&amp;gt;&quot;);
		document.write(&quot;&amp;lt;span&amp;gt;&amp;lt;strong&amp;gt;오늘&amp;lt;span id='ti'&amp;gt;&quot;+year+'.'+mon+'.'+dat+&quot;&amp;lt;/span&amp;gt;&quot;);
            document.write(&quot;&amp;lt;/strong&amp;gt;&amp;lt;/span&amp;gt;&quot;);
	&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
	
    
    
    &amp;lt;br&amp;gt;
    &amp;lt;textarea name=&quot;&quot; id=&quot;ta&quot; cols=&quot;30&quot; rows=&quot;10&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
    &amp;lt;br&amp;gt;
    &amp;lt;button onclick=&quot;store()&quot;&amp;gt;저장&amp;lt;/button&amp;gt;
    &amp;lt;button onclick=&quot;look()&quot;&amp;gt;보기&amp;lt;/button&amp;gt;
&amp;lt;script&amp;gt;
        
		var ta = document.getElementById(&quot;ta&quot;);

		function store(){
			if(!window.localStorage){
				alert(&quot;로컬 스토리지를 지원하지 않습니다.&quot;);
				return;
			}
			localStorage.setItem(ti.innerHTML,ta.value);
		}
        function look()
        {
            window.open(&quot;file:///C:/web/good/good.html&quot;,&quot;_blank&quot;);

        }
    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로컬 스토리지에 저장해두기때문에, 오늘 날짜를 수정해서 로컬 스토리지에 저장해두면 각기 다른 날짜로 일기를 쓸 수 있다.&lt;/p&gt;</description>
      <category>웹프로그래밍</category>
      <category>CSS</category>
      <category>HTML</category>
      <category>JavaScript</category>
      <category>웹프로그래밍</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/6</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%AA%85%ED%92%88-%EC%9B%B9%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-12%EC%9E%A5-4%EB%B2%88-%EB%AC%B8%EC%A0%9C#entry6comment</comments>
      <pubDate>Mon, 4 Sep 2023 14:21:51 +0900</pubDate>
    </item>
    <item>
      <title>명품 웹프로그래밍 11장 8번 문제</title>
      <link>https://basecoding.tistory.com/entry/%EB%AA%85%ED%92%88-%EC%9B%B9%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-11%EC%9E%A5-8%EB%B2%88-%EB%AC%B8%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;선의 굵기와 선 색을 선택하고 마우스 드래깅으로 캔버스에 그림을 그릴 수 있는 웹 페이지를 작성해보자&lt;/p&gt;
&lt;pre id=&quot;code_1693734139328&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;en&quot;&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;h2&amp;gt;마우스를 누른 채 드래깅하여 그림을 그려 보세요&amp;lt;/h2&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;canvas id=&quot;can&quot; width=&quot;500&quot; height=&quot;400&quot; style=&quot;background-color: aquamarine;&quot;&amp;gt;&amp;lt;/canvas&amp;gt;
    &amp;lt;br&amp;gt;
    선굵기: &amp;lt;input type=&quot;text&quot; style=&quot;width: 3em;&quot; id=&quot;wid&quot;&amp;gt; 선색: &amp;lt;input type=&quot;color&quot; id=&quot;color&quot;&amp;gt;
    지우기 : &amp;lt;button onclick=&quot;earase()&quot;&amp;gt;지우기&amp;lt;/button&amp;gt;

    &amp;lt;script&amp;gt;
        var wid = document.getElementById('wid');
        
        var can=document.getElementById(&quot;can&quot;);
        var con=can.getContext(&quot;2d&quot;);

        function earase()
        {
            con.clearRect(0,0,can.width,can.height);
        }
        
        var x;
        var y;
        var a=false;
        can.onmousedown=function(e){
            a=true;
            con.strokeStyle=document.getElementById('color').value;
            con.lineWidth=document.getElementById('wid').value;
            x=e.offsetX;
            y=e.offsetY;
            con.beginPath();
            con.moveTo(x,y);
           

        };
        can.onmousemove=function(e){

            if(a)
            {
            con.lineTo(e.offsetX,e.offsetY);
            con.stroke();
            }
        };
        can.onmouseup=function(e){
            a=false;
        };


    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 문제인 9번 문제의 경우, 8번 문제의 onmousedown 리스너를 onmouseover 로, onmouseup 리스너를 onmouseout 으로 변경해주면 된다.&lt;/p&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h2&gt;마우스를 누른 채 드래깅하여 그림을 그려 보세요&lt;/h2&gt;
    &lt;hr&gt;
    &lt;canvas id=&quot;can&quot; width=&quot;500&quot; height=&quot;400&quot; style=&quot;background-color: aquamarine;&quot;&gt;&lt;/canvas&gt;
    &lt;br&gt;
    선굵기: &lt;input type=&quot;text&quot; style=&quot;width: 3em;&quot; id=&quot;wid&quot;&gt; 선색: &lt;input type=&quot;color&quot; id=&quot;color&quot;&gt;
    지우기 : &lt;button onclick=&quot;earase()&quot;&gt;지우기&lt;/button&gt;

    &lt;script&gt;
        var wid = document.getElementById('wid');
        
        var can=document.getElementById(&quot;can&quot;);
        var con=can.getContext(&quot;2d&quot;);

        function earase()
        {
            con.clearRect(0,0,can.width,can.height);
        }
        
        var x;
        var y;
        var a=false;
        can.onmousedown=function(e){
            a=true;
            con.strokeStyle=document.getElementById('color').value;
            con.lineWidth=document.getElementById('wid').value;
            x=e.offsetX;
            y=e.offsetY;
            con.beginPath();
            con.moveTo(x,y);
           

        };
        can.onmousemove=function(e){

            if(a)
            {
            con.lineTo(e.offsetX,e.offsetY);
            con.stroke();
            }
        };
        can.onmouseup=function(e){
            a=false;
        };


    &lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;</description>
      <category>웹프로그래밍</category>
      <category>웹프로그래밍 #html #css3 #javascript</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/5</guid>
      <comments>https://basecoding.tistory.com/entry/%EB%AA%85%ED%92%88-%EC%9B%B9%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-11%EC%9E%A5-8%EB%B2%88-%EB%AC%B8%EC%A0%9C#entry5comment</comments>
      <pubDate>Sun, 3 Sep 2023 18:41:48 +0900</pubDate>
    </item>
    <item>
      <title>01. 데이터통신 입문 (네트워크 상에서의 데이터 이동)</title>
      <link>https://basecoding.tistory.com/entry/01-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%86%B5%EC%8B%A0-%EC%9E%85%EB%AC%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%81%EC%97%90%EC%84%9C%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9D%B4%EB%8F%99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 말했듯이 네트워크는 서로다른 기기들이 연결되어 데이터를 서로 전달 및 공유할 수 있는 일종의 연결망입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;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;background-color: #000000; color: #ffffff;&quot;&gt;1. 패킷&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;span style=&quot;background-color: #000000; color: #ffffff;&quot;&gt;2. 라우터&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;span style=&quot;background-color: #000000; color: #ffffff;&quot;&gt;3. 통신 링크&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;통신 링크에는 물리적인 케이블,광섬유 및 무선 링크 등등이 있으며 이러한 통신 링크를 통해 라우터와 라우터간의 패킷의 이동이 가능한 것이며 패킷의 원활한 이동을 가능하게 해줍니다. 통신 링크는 데이터 패킷의 빠른 이동과 효율적인 전송에 연관되어 있기에 네트워크 전체의 성능과 속도에 매우 중요한 역할을 합니다.&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;위 3가지 구성요소로 간단히 네트워크 상의 데이터의 이동을 요약해보자면,&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;할 수 있겠네요.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>데이터통신</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/3</guid>
      <comments>https://basecoding.tistory.com/entry/01-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%86%B5%EC%8B%A0-%EC%9E%85%EB%AC%B8-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%83%81%EC%97%90%EC%84%9C%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9D%B4%EB%8F%99#entry3comment</comments>
      <pubDate>Fri, 1 Sep 2023 07:47:50 +0900</pubDate>
    </item>
    <item>
      <title>01. 데이터통신 입문 (네트워크와 인터넷)</title>
      <link>https://basecoding.tistory.com/entry/01-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%86%B5%EC%8B%A0-%EC%9E%85%EB%AC%B8</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ffffff; background-color: #000000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;※&quot;네트워크&quot;란? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;오늘은 네트워크에 대한 개념과 인터넷에 대한 기본적인 개념들을 서술해보겠습니다.&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;네트워크란,&amp;nbsp;Net&amp;nbsp;+&amp;nbsp;Work&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;말합니다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;어느&amp;nbsp;나라,&amp;nbsp;어느&amp;nbsp;지역에&amp;nbsp;거주하고있던&amp;nbsp;네트워크를&amp;nbsp;통해&amp;nbsp;sns&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;네트워크&amp;nbsp;기술의&amp;nbsp;향상으로&amp;nbsp;인한&amp;nbsp;결과물입니다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;네트워크는&amp;nbsp;일종의&amp;nbsp;구조&amp;nbsp;또는&amp;nbsp;형태입니다.&amp;nbsp;네트워크는&amp;nbsp;여러&amp;nbsp;노드(pc,서버ㅡlap&amp;nbsp;top)들이&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;전송하고,&amp;nbsp;데이터&amp;nbsp;교환을&amp;nbsp;위한&amp;nbsp;규칙인&amp;nbsp;프로토콜을&amp;nbsp;가지고&amp;nbsp;있습니다.&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;u&gt;&lt;i&gt;※프로토콜: 데이터 전송-전달 받는 방법, 데이터의 규격, 통신 규칙 등등을 정의하는 일종의 규약-규칙. 통신은 혼자서만 하는게 아니기때문에 서로간의 규칙이 있어야한다. 그래야 서로간에 제대로 데이터 전달이 이루어짐.&lt;/i&gt;&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;size16&quot;&gt;&lt;i&gt;&lt;/i&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;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;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;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;통한&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;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;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;전송과&amp;nbsp;커뮤니케이션이&amp;nbsp;이루어집니다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;네트워크에 대한 기본적인 개념 및 이론은 위와 같으나, 실제 적용되는 예시를 보자면,&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 경우는 소수의 회사 구성원들만 해당 사설 네트워크에 접속하여 한정된 정보만을 서로 공유하겠지요? 그렇기에 나아가 더욱 다양하고 한정되지 않은 무한한 정보를 얻고 공유하기 위해서는 다중 네트워크, 즉 수 많은 네트워크들이 서로 연결되어 있는 거대 네트워크 공간인 인터넷이 요구되어 진 것입니다.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&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;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;거대한&amp;nbsp;네트워크&amp;nbsp;인&amp;nbsp;것&amp;nbsp;입니다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;i&gt;※인터넷: inter + net 의 약자.&amp;nbsp; 말 그대로 네트워크 사이의 연결을 의미.&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;결론적으로, &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;네트워크&lt;/span&gt;는 &quot;여러 디지털 장치들이 서로 연결되어 데이터를 교환하고 통신할 수 있도록 만들어진 구조이자 시스템&quot;이며, &lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;인터넷&lt;/span&gt;은 &quot;컴퓨터 네트워크들이 전 세계적으로 연결된 하나의 거대한 네트워크로, 다양한 서비스와 기능을 제공하는 중요한 네트워크 중 하나의 종류&quot;인 것 입니다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>데이터통신</category>
      <category>데이터통신 #네트워크 #인터넷</category>
      <author>base_coding</author>
      <guid isPermaLink="true">https://basecoding.tistory.com/2</guid>
      <comments>https://basecoding.tistory.com/entry/01-%EB%8D%B0%EC%9D%B4%ED%84%B0%ED%86%B5%EC%8B%A0-%EC%9E%85%EB%AC%B8#entry2comment</comments>
      <pubDate>Fri, 1 Sep 2023 05:43:09 +0900</pubDate>
    </item>
  </channel>
</rss>