<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
	<channel>
		<title><![CDATA[멀티플랫폼 게임개발]]></title>
		<link>https://www.stechstar.com/user/zbxe/MultiFGame</link>
		<description><![CDATA[]]></description>
		<language>ko</language>
		<pubDate>Sun, 13 Sep 2026 16:45:46 +0900</pubDate>
		<lastBuildDate>Sun, 13 Sep 2026 16:45:46 +0900</lastBuildDate>
		<generator>XpressEngine</generator>
				<copyright><![CDATA[comphy]]></copyright>
								<item>
			<title><![CDATA[[react native] 2025년 리액트 네이티브로 프로젝트 시작하기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/112612</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/112612</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/112612#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[react native] 2025년 리액트 네이티브로 프로젝트 시작하기&lt;/h1&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h1 style=&quot;box-sizing: inherit; font-size: 2rem; margin: 2.4375rem 0px 1.21875rem; padding: 0px 0px calc(-1px + 0.40625rem); color: rgba(0, 0, 0, 0.8); font-family: Catamaran; text-rendering: optimizelegibility; line-height: 1.2; border-bottom: 1px solid rgba(0, 0, 0, 0.07); background-color: rgb(255, 255, 255);&quot;&gt;2025년 리액트 네이티브로 프로젝트 시작하기&lt;/h1&gt;

&lt;div style=&quot;box-sizing: inherit; color: rgba(0, 0, 0, 0.8); font-family: &quot;Noto Sans KR&quot;, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255); display: flex; justify-content: space-between;&quot;&gt;
&lt;p class=&quot;post-date&quot; style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px; text-align: right; font-size: 12px; font-style: italic;&quot;&gt;February 02, 2025&lt;/p&gt;
&lt;/div&gt;

&lt;div style=&quot;box-sizing: inherit; color: rgba(0, 0, 0, 0.8); font-family: &quot;Noto Sans KR&quot;, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;
&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;이 글은 사이드 프로젝트를 진행하기에 앞서 RN을 선택한 이유와 21년까지 경험했던 RN 이후 현재까지의 변경된 내용들에 대한 팔로업에 초점이 맞추어져 있다. 따라서 리액트 웹 개발자가 RN으로 앱 개발을 시작하려 할 때 참고할 수 있다면 좋을 것 같다.&lt;/p&gt;

&lt;h2 id=&quot;배경&quot; style=&quot;box-sizing: inherit; margin: 56px 0px 20px; padding: 0px 0px calc(-1px + 0.40625rem); color: inherit; font-family: Catamaran; text-rendering: optimizelegibility; font-size: 1.51572rem; line-height: 1.2; border-bottom: 1px solid rgba(0, 0, 0, 0.07); position: relative;&quot;&gt;&lt;a aria-label=&quot;배경 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EB%B0%B0%EA%B2%BD&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;배경&lt;/h2&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;올해 목표 중 하나는 오랫동안 미뤄왔던 사이드 프로젝트를 시작하는 것이었다. 물론 완성까지 하면 너무 좋겠지만, 시작이 반이라는 생각으로 프로젝트 시작부터 해보려고 한다. 그렇기에 가장 먼저 해야 할 것은 기술 스택을 선정하는 것이었는데, 사실 후보군은 많이 있었다. 먼저 내가 만들고자 하는 사이드 프로젝트는 웹 서비스보다는 모바일 앱에 더 잘 어울리기 때문에 앱으로 개발해야겠다고 생각했고, 그렇게 했을 때 선택지는 세 가지 정도로 압축되었다.&lt;/p&gt;

&lt;ol style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;안드로이드 또는 iOS 네이티브 앱 개발&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;하이브리드 앱 개발 - 네이티브 앱에 웹뷰를 통합하여 웹 기술로 대부분의 기능을 구현하는 방법&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;플러터, RN을 통한 크로스 플랫폼 앱 개발&lt;/li&gt;
&lt;/ol&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;위의 선택지에서 1번의 경우, kotlin이나 swift와 같은 네이티브 언어 학습이 필요하고, 2번의 경우 네이티브 기능을 자유롭게 활용해야 하는 경우 한계점이 존재하고, 결국에는 네이티브 코드가 필요할 수 있게 된다. 사이드 프로젝트라는 특성을 생각하면 시작하는 데까지 많은 학습과 준비 과정이 필요하다면 프로젝트가 진척되기 힘들 것 같아 개발 경험이 있어 진입 장벽이 비교적 낮은 3번 방법을 선택했다.&lt;/p&gt;

&lt;h2 id=&quot;react-native를-선택한-이유&quot; style=&quot;box-sizing: inherit; margin: 56px 0px 20px; padding: 0px 0px calc(-1px + 0.40625rem); color: inherit; font-family: Catamaran; text-rendering: optimizelegibility; font-size: 1.51572rem; line-height: 1.2; border-bottom: 1px solid rgba(0, 0, 0, 0.07); position: relative;&quot;&gt;&lt;a aria-label=&quot;react native를 선택한 이유 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#react-native%EB%A5%BC-%EC%84%A0%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;React Native를 선택한 이유&lt;/h2&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;플러터와 RN은 예전에 앱 개발을 했을 때도 많이 비교되는 프레임워크였고, 지금까지도 경쟁을 통해 서로 발전하고 있는 관계이기도 하다. 사실 현시점에서는 플러터와 RN 중 어떤 프레임워크를 사용하더라도 사이드 프로젝트를 진행하는 데 이슈가 없지만 다음과 같은 이유로 React Native를 선택했다.&lt;/p&gt;

&lt;h3 id=&quot;1-비교적-낮은-러닝커브&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;1 비교적 낮은 러닝커브 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#1-%EB%B9%84%EA%B5%90%EC%A0%81-%EB%82%AE%EC%9D%80-%EB%9F%AC%EB%8B%9D%EC%BB%A4%EB%B8%8C&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;1. 비교적 낮은 러닝커브&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;현재 프런트엔드 개발을 하고 있기 때문에 리액트는 나에게 제일 익숙한 스택이라고 할 수 있는데, 러닝 커브 면에서는 React Native는 리액트 개발자가 선택할 수 있는 가장 최고의 선택이라고 하고 싶다. 물론 플러터도 과거에 경험해 봤지만, 대부분의 기억이 휘발되었고 Dart 언어를 다시금 학습해야 한다는 부담이 있었기 때문에 웹 FE 개발자로서 기존의 리액트와 Javascript/Typescript를 활용할 수 있고, 플러터보다는 낮은 진입장벽을 가진 React Native를 선택했다.&lt;/p&gt;

&lt;h3 id=&quot;2-새로운-아키텍처와-함께-개선된-성능&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;2 새로운 아키텍처와 함께 개선된 성능 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#2-%EC%83%88%EB%A1%9C%EC%9A%B4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EC%99%80-%ED%95%A8%EA%BB%98-%EA%B0%9C%EC%84%A0%EB%90%9C-%EC%84%B1%EB%8A%A5&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;2. 새로운 아키텍처와 함께 개선된 성능&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;플러터와 RN은 경쟁 초기부터 계속하여 성능 비교 대상이었다. 그러나 빌드 성능 면이나 복잡한 UI, 애니메이션 렌더링에서는 플러터가 꾸준하게 더 앞선다는 평가가 많았다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;내가 RN을 경험했던 2022년에는 새로운 아키텍처가 베타 단계였으나, 25년 현재에는 새로운 아키텍처가 안정화되어 대부분의 라이브러리가 이를 지원하고 있다. 새로운 네이티브 모듈 시스템이 도입되었고, 다중 스레드에서 동시 업데이트 처리가 가능한 새로운 렌더러가 도입되었다. 그뿐만 아니라 Javascript와 네이티브 런타임 사이에 존재했던 브릿지가 제거되어, 새로운 아키텍처 도입으로 성능이 크게 개선되었다. 특히 UI 렌더링과 브릿지 통신 오버헤드가 대폭 감소했다. 이외에도 여러 가지 최적화를 통해 성능 개선이 이루어졌고, 리액트 18을 완벽하게 지원하게 되었다. 이번 React Native의 혁신적인 개선 사항은&nbsp;&lt;a href=&quot;https://ykss.netlify.app/translation/new_architecture_is_here/&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; margin-bottom: 0px;&quot;&gt;&lt;리액트 네이티브의 새로운 아키텍처가 출시되었습니다&gt;&lt;/a&gt;를 통해 좀 더 상세하게 확인할 수 있다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;결과적으로 RN의 성능이 우수하기 때문이 아니라, 성능 문제 때문에 꼭 플러터를 선택할 필요는 없다고 판단되어 RN을 선택한 것이다. 사실 플러터와 RN의 선택에 있어서는 이러한 성능 차이보다는 어떤 프레임워크를 더 숙련도 있게 활용할 수 있느냐가 포인트라고 생각한다.&lt;/p&gt;

&lt;h3 id=&quot;3-expo-프레임워크를-통해-얻을-수-있는-이점&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;3 expo 프레임워크를 통해 얻을 수 있는 이점 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#3-expo-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%96%BB%EC%9D%84-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%9D%B4%EC%A0%90&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;3. Expo 프레임워크를 통해 얻을 수 있는 이점&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;Expo는 React Native 개발을 더욱 쉽게 만들어주는 프레임워크다. Expo를 사용하면 네이티브 코드를 전혀 사용하지 않아도 간단하고 여러 가지 장점을 얻을 수 있다는 점도 RN을 선택하게 된 이유 중 하나이다.&lt;/p&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;네이티브 빌드 환경 설정 없이 바로 개발 시작 가능&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;OTA(Over-the-Air) 업데이트를 통한 즉각적인 앱 업데이트&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;푸시 알림, 카메라 등 다양한 네이티브 기능을 JavaScript API로 제공&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;개발 환경에서 QR코드로 즉시 테스트 가능(Expo Go)&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;이전에 Expo를 사용했을 때는 Expo에서 지원하는 네이티브 모듈이 제한적이었기 때문에, 뭔가 더 세밀한 제어나 특수한 네이티브 기능이 필요할 경우에는 Expo를 사용하다가 eject를 통하여 Expo를 걷어낸 순수한 RN 프로젝트로의 복잡한 전환이 필요했는데, 현재는 Expo가 많이 발전되어 사실 Expo를 사용하여 웬만한 네이티브 기능을 모두 사용할 수 있게 되었다. 이번에 알게 된 부분은 2025년 기준으로는 Expo의 개발 방식이 변화(EAS Build의 도입)되어 eject는 더 이상 사용되지 않으며 deprecated 되었다고 한다.&lt;/p&gt;

&lt;h2 id=&quot;expo를-통한-rn-프로젝트-시작하기&quot; style=&quot;box-sizing: inherit; margin: 56px 0px 20px; padding: 0px 0px calc(-1px + 0.40625rem); color: inherit; font-family: Catamaran; text-rendering: optimizelegibility; font-size: 1.51572rem; line-height: 1.2; border-bottom: 1px solid rgba(0, 0, 0, 0.07); position: relative;&quot;&gt;&lt;a aria-label=&quot;expo를 통한 rn 프로젝트 시작하기 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#expo%EB%A5%BC-%ED%86%B5%ED%95%9C-rn-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Expo를 통한 RN 프로젝트 시작하기&lt;/h2&gt;

&lt;h3 id=&quot;개발-환경-설정&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;개발 환경 설정 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;개발 환경 설정&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;React Native 개발을 시작하기 전에 필요한 기본적인 개발 환경을 구축해야 한다. 먼저 Node.js는 LTS 버전을 설치하는 것을 권장한다. Expo를 사용하면 네이티브 개발 환경(Xcode, Android Studio) 없이도 개발을 시작할 수 있다는 장점이 있다. 다만, 네이티브 기능 개발을 위해 Xcode나 Android Studio 설치가 더 일반적으로 권장된다.&lt;/p&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# Expo CLI로 프로젝트 생성 및 개발 시작&lt;/span&gt;
npx create-expo-app my-app
&lt;span class=&quot;token builtin class-name&quot; style=&quot;box-sizing: inherit; color: rgb(179, 136, 255);&quot;&gt;cd&lt;/span&gt; my-app
npx expo start&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;expo-cli-vs-rn-cli-선택-가이드&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;expo cli vs rn cli 선택 가이드 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#expo-cli-vs-rn-cli-%EC%84%A0%ED%83%9D-%EA%B0%80%EC%9D%B4%EB%93%9C&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Expo CLI vs RN CLI 선택 가이드&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;과거에는 React Native로 프로젝트를 시작할 때 가장 먼저 고민하게 되었던 것이 Expo CLI와 React Native CLI 중 어떤 것을 선택할지였다. 이전에는 Expo가 제한적인 기능만 제공하고 네이티브 모듈 사용에 제약이 많아 실제 프로덕션 앱 개발에는 RN CLI를 선호하는 경향이 있었다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;하지만 2025년 현재는 상황이 많이 달라졌다. Expo는 &lsquo;Development Builds&rsquo;와 &lsquo;Config Plugins&rsquo; 기능을 통해 네이티브 모듈도 자유롭게 사용할 수 있게 되었고, EAS(Expo Application Services)를 통한 빌드/배포 자동화, OTA 업데이트 등 다양한 기능을 제공하고 있다. 이러한 발전으로 인해 React Native 공식 문서에서도 Expo를 권장하고 있으며, 대부분의 앱 개발 요구사항을 Expo로 충분히 커버할 수 있게 되었다. 때문에 Expo와 React Native CLI 사이의 선택은 더 이상 큰 고민거리가 아니게 되었다.&lt;/p&gt;

&lt;h4 id=&quot;expo-cli의-장점&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;expo cli의 장점 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#expo-cli%EC%9D%98-%EC%9E%A5%EC%A0%90&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Expo CLI의 장점&lt;/h4&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;빠른 프로젝트 설정과 개발 시작&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;간편한 빌드 및 배포 프로세스&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;풍부한 내장 API와 컴포넌트&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;OTA 업데이트 지원&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;Config Plugins를 통한 네이티브 모듈 통합 가능&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;자동화된 빌드 인프라 제공&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;react-native-cli의-장점&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;react native cli의 장점 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#react-native-cli%EC%9D%98-%EC%9E%A5%EC%A0%90&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;React Native CLI의 장점&lt;/h4&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;네이티브 모듈에 대한 완전한 제어&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;커스텀 네이티브 코드 작성 가능&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;더 작은 앱 크기&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;네이티브 빌드 프로세스에 대한 완전한 통제&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;이러한 장단점을 고려했을 때, 특별히 네이티브 레벨의 깊은 커스터마이징이 필요하지 않은 대부분의 프로젝트에서는 Expo CLI를 선택하는 것이 개발 생산성과 유지보수 측면에서 더 유리하다. 실제로 많은 프로덕션 앱이 Expo를 사용하여 성공적으로 서비스되고 있다.&lt;/p&gt;

&lt;h3 id=&quot;프로젝트-생성-및-구조&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;프로젝트 생성 및 구조 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1-%EB%B0%8F-%EA%B5%AC%EC%A1%B0&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;프로젝트 생성 및 구조&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;2025년 현재 Expo는 더 현대적이고 유연한 프로젝트 구조를 제공하는 Expo Router를 권장한다.&lt;/p&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 새 프로젝트 생성 (Expo Router + TypeScript)&lt;/span&gt;
npx create-expo-app --template&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;위 명령어를 실행하면 사용자에게 여러 옵션(Blank, Blank (TypeScript), Navigation (TypeScript) 등)을 제공하며, 그중에서 선택할 수 있다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;이 중&nbsp;&lt;code class=&quot;language-text&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; line-height: 1.6; margin-bottom: 0px; color: rgb(75, 32, 67); background: rgb(236, 229, 241); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; padding: 0.1em 0.6em; border-radius: 0.2em;&quot;&gt;Navigation (TypeScript)&lt;/code&gt;를 선택하면 Next.js의 App Router와 유사한 파일 기반 라우팅을 지원하는 Expo Router를 포함한 템플릿의 프로젝트를 생성할 수 있다. Expo Router는 React Navigation을 기반으로 하되, 파일 시스템 기반의 더 직관적인 라우팅을 제공한다. 프로젝트 구조는 다음과 같다.&lt;/p&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;my-app/
├── app/               &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# Expo Router 기반 페이지&lt;/span&gt;
│   ├── &lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;(&lt;/span&gt;tabs&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;)&lt;/span&gt;/       &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 탭 네비게이션 그룹&lt;/span&gt;
│   ├── modal/        &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 모달 스택&lt;/span&gt;
│   └── &lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;[&lt;/span&gt;dynamic&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;]&lt;/span&gt;/    &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 동적 라우트&lt;/span&gt;
│
├── components/        &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 재사용 컴포넌트&lt;/span&gt;
├── hooks/            &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 커스텀 훅&lt;/span&gt;
├── providers/        &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 컨텍스트 프로바이더&lt;/span&gt;
├── services/         &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# API 및 외부 서비스&lt;/span&gt;
├── stores/           &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 상태 관리&lt;/span&gt;
├── types/            &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# TypeScript 타입&lt;/span&gt;
├── utils/            &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 유틸리티 함수&lt;/span&gt;
├── assets/           &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 이미지, 폰트 등&lt;/span&gt;
└── app.json          &lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# Expo 설정&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h4 id=&quot;주요-특징&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;주요 특징 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;주요 특징&lt;/h4&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;파일 시스템 기반 라우팅으로 직관적인 네비게이션 구조&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;Expo Router의 lazy loading 활용으로 초기 로딩 성능 최적화&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;TypeScript와 ESLint 설정 내장&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;테스트 환경 사전 구성&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;필수-라이브러리-설정&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1.31951rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;필수 라이브러리 설정 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%ED%95%84%EC%88%98-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%84%A4%EC%A0%95&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;필수 라이브러리 설정&lt;/h3&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;React Native 프로젝트를 시작할 때 필수적으로 고려해야 할 라이브러리들이 있다. 2025년 기준으로 가장 많이 사용되는 조합은 다음과 같다.&lt;/p&gt;

&lt;h4 id=&quot;네비게이션&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;네비게이션 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EB%84%A4%EB%B9%84%EA%B2%8C%EC%9D%B4%EC%85%98&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;네비게이션&lt;/h4&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;&lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; @react-navigation/native @react-navigation/stack
npx expo &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; react-native-screens react-native-safe-area-context&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;React Navigation은 React Native에서 사실상의 표준 네비게이션 라이브러리다. 특히 v7부터는 새로운 아키텍처와 호환되며, 성능이 크게 개선되었다. Expo를 사용하는 경우 Expo Router가 기본적으로 세팅되어 있어 별도로 React Navigation을 설치하고 구성할 필요가 없다. 위에서 잠시 언급한 것과 같이 Expo Router는 React Navigation을 기반으로 만들어졌으며, 파일 시스템 기반의 라우팅을 제공하여 더 직관적이고 간편한 네비게이션 구조를 만들 수 있다&lt;/p&gt;

&lt;h4 id=&quot;상태-관리&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;상태 관리 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;상태 관리&lt;/h4&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# Zustand (가장 널리 사용되는 선택)&lt;/span&gt;
&lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; zustand

&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# 또는 Jotai (더 작은 규모의 상태 관리에 적합)&lt;/span&gt;
&lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; jotai

&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# persist 미들웨어 (필요한 경우)&lt;/span&gt;
&lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; @zustand/persist-async&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;상태 관리는 리액트 웹 개발 환경과 비슷하다. 2025년 현재 React Native를 통한 모바일 앱 개발에서는 Zustand는 널리 사용되는 상태 관리 라이브러리 중 하나다. Redux는 보일러플레이트가 많고 복잡성이 높다는 이유로 새로운 프로젝트에서는 잘 사용되지 않는다. Zustand는 간단한 API와 높은 성능, 작은 번들 사이즈를 제공하며, React Native 환경에서도 최적화되어 있다. 추가로, 서버 상태 관리를 위해 TanStack Query (구 React Query)의 사용이 증가하고 있다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;더 작은 규모의 상태 관리가 필요한 경우 Jotai를 고려할 수 있으며, 매우 간단한 상태 관리의 경우 리액트의 Context API로도 충분할 수 있다. 상태 유지가 필요한 경우 Zustand의 persist 미들웨어를 사용하면 앱을 재시작해도 상태를 유지할 수 있다.&lt;/p&gt;

&lt;h4 id=&quot;스타일링&quot; style=&quot;box-sizing: inherit; margin: 1.625rem 0px 0.8125rem; padding: 0px; color: inherit; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; text-rendering: optimizelegibility; font-size: 1rem; line-height: 1.1; position: relative;&quot;&gt;&lt;a aria-label=&quot;스타일링 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EC%8A%A4%ED%83%80%EC%9D%BC%EB%A7%81&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;스타일링&lt;/h4&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;React Native에서는 여러 가지 스타일링 방식을 사용할 수 있다. 이전에 경험했을 때는 기본 제공되는 StyleSheet와 styled-components를 사용했었지만, 요즘 웹 개발 트렌드와 일치하게 NativeWind를 통해 Tailwind CSS도 지원되어 트렌드로 자리 잡아가고 있다. 나는 요즘 웹에서도 Tailwind CSS를 주로 사용하고 있기 때문에 NativeWind를 사용하기로 했다.&lt;/p&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;Nativewind (2025년 현재 가장 추천되는 방식)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-bash&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# Nativewind 설치&lt;/span&gt;
&lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; nativewind
&lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;install&lt;/span&gt; -D tailwindcss

&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;# tailwind.config.js 생성&lt;/span&gt;
npx tailwindcss init&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;tsx&quot; style=&quot;box-sizing: inherit;&quot;&gt;
&lt;pre class=&quot;language-tsx&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; font-size: 13px; margin: 1.5em 0px; padding: 1.2em; line-height: 1.6; color: rgb(224, 224, 224); background: rgb(33, 33, 33); word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none; overflow: auto; border-radius: 0.6em;&quot;&gt;
&lt;code class=&quot;language-tsx&quot; style=&quot;box-sizing: inherit; font-family: &quot;Fira Code&quot;, Consolas, Monaco, &quot;Andale Mono&quot;, &quot;Ubuntu Mono&quot;, monospace; line-height: 1.6; background: none; word-spacing: normal; word-break: normal; overflow-wrap: normal; tab-size: 2; hyphens: none;&quot;&gt;&lt;span class=&quot;token comment&quot; style=&quot;box-sizing: inherit; color: rgb(97, 97, 97);&quot;&gt;// 사용 예시&lt;/span&gt;
&lt;span class=&quot;token keyword&quot; style=&quot;box-sizing: inherit; color: rgb(179, 136, 255);&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot; style=&quot;box-sizing: inherit; color: rgb(179, 136, 255);&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot; style=&quot;box-sizing: inherit; color: rgb(255, 145, 0);&quot;&gt;MyComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot; style=&quot;box-sizing: inherit; color: rgb(179, 136, 255);&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit; color: rgb(226, 119, 122);&quot;&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit;&quot;&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot; style=&quot;box-sizing: inherit; color: rgb(255, 255, 0);&quot;&gt;View&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot; style=&quot;box-sizing: inherit;&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot; style=&quot;box-sizing: inherit; color: rgb(0, 230, 118);&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&quot;&lt;/span&gt;flex-1 items-center justify-center&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot; style=&quot;box-sizing: inherit;&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit; color: rgb(226, 119, 122);&quot;&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit;&quot;&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot; style=&quot;box-sizing: inherit; color: rgb(255, 255, 0);&quot;&gt;Text&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot; style=&quot;box-sizing: inherit;&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;token attr-value&quot; style=&quot;box-sizing: inherit; color: rgb(0, 230, 118);&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&quot;&lt;/span&gt;text-xl font-bold&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot; style=&quot;box-sizing: inherit;&quot;&gt;Hello, Nativewind!&lt;/span&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit; color: rgb(226, 119, 122);&quot;&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit;&quot;&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot; style=&quot;box-sizing: inherit; color: rgb(255, 255, 0);&quot;&gt;Text&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token plain-text&quot; style=&quot;box-sizing: inherit;&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit; color: rgb(226, 119, 122);&quot;&gt;&lt;span class=&quot;token tag&quot; style=&quot;box-sizing: inherit;&quot;&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&lt;/&lt;/span&gt;&lt;span class=&quot;token class-name&quot; style=&quot;box-sizing: inherit; color: rgb(255, 255, 0);&quot;&gt;View&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit; color: rgb(224, 224, 224);&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot; style=&quot;box-sizing: inherit;&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;2025년 기준으로 Nativewind가 가장 추천되는 스타일링 방식이다. 그 이유는 다음과 같다.&lt;/p&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;웹 개발자에게 친숙한 Tailwind CSS 문법 사용 가능&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;컴파일 타임에 최적화되어 런타임 성능 영향 없음&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;다크 모드 등 테마 관리가 용이&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;반응형 디자인 구현이 쉬움&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;TypeScript와의 완벽한 통합&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;기본 제공되는 StyleSheet API는 간단한 스타일링에 적합하며, styled-components는 동적 스타일링이 많이 필요한 경우에 고려할 수 있다. 하지만 대부분의 경우 NativeWind를 사용하는 것이 생산성과 유지보수 측면에서 가장 좋은 선택이 될 것으로 생각한다. 하지만 스타일링 방식은 개인의 취향이 많이 반영되는 영역이기도 하므로 각자 선호하는 방식을 사용하는 것이 좋다.&lt;/p&gt;

&lt;h2 id=&quot;결론&quot; style=&quot;box-sizing: inherit; margin: 56px 0px 20px; padding: 0px 0px calc(-1px + 0.40625rem); color: inherit; font-family: Catamaran; text-rendering: optimizelegibility; font-size: 1.51572rem; line-height: 1.2; border-bottom: 1px solid rgba(0, 0, 0, 0.07); position: relative;&quot;&gt;&lt;a aria-label=&quot;결론 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EA%B2%B0%EB%A1%A0&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;결론&lt;/h2&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;2025년 현재 React Native는 새로운 아키텍처와 Expo의 발전으로 더욱 성숙한 개발 환경을 제공하고 있다. 특히 Expo를 활용하면 웹 개발자도 쉽게 앱 개발을 시작할 수 있으며, 개발부터 배포까지 효율적으로 진행할 수 있다. 실제로 Instagram, Discord, Shopify와 같은 대규모 서비스들이 React Native를 성공적으로 도입하여 사용하고 있으며, 특히 Expo를 활용한 개발 사례도 늘어나고 있다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;물론 React Native가 완벽한 솔루션은 아니다. 복잡한 애니메이션이나 고성능이 요구되는 기능 구현에서는 여전히 네이티브 개발 대비 제약이 있을 수 있고, 앱 크기가 더 커질 수 있다는 단점도 존재한다. 하지만 대부분의 일반적인 앱 개발 시나리오에서는 충분한 성능과 개발 생산성을 제공하며, 특히 웹 개발 경험이 있는 개발자에게는 매력적인 선택지가 될 수 있다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px;&quot;&gt;올해 RN 개발을 해보면서 느끼거나 새로 배우는 것들도 정리해 가려고 하는데, 사이드 프로젝트를 진행하며 겪는 어려움이나 고민 등 유의미한 과정을 남길 수 있다면 좋을 것 같다.&lt;/p&gt;

&lt;h2 id=&quot;참고할만한-리소스&quot; style=&quot;box-sizing: inherit; margin: 56px 0px 20px; padding: 0px 0px calc(-1px + 0.40625rem); color: inherit; font-family: Catamaran; text-rendering: optimizelegibility; font-size: 1.51572rem; line-height: 1.2; border-bottom: 1px solid rgba(0, 0, 0, 0.07); position: relative;&quot;&gt;&lt;a aria-label=&quot;참고할만한 리소스 permalink&quot; class=&quot;anchor before&quot; href=&quot;https://ykss.netlify.app/devlog/start_with_RN/#%EC%B0%B8%EA%B3%A0%ED%95%A0%EB%A7%8C%ED%95%9C-%EB%A6%AC%EC%86%8C%EC%8A%A4&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; position: absolute; top: 0px; left: 0px; transform: translateX(-100%); padding-right: 4px;&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewbox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot; fill-rule=&quot;evenodd&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;참고할만한 리소스&lt;/h2&gt;

&lt;ul style=&quot;box-sizing: inherit; margin: 0px 0px 6px 2.03125rem; padding: 0px; list-style-position: outside; list-style-image: none;&quot;&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;&lt;a href=&quot;https://reactnative.dev/&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; margin-bottom: 0px;&quot;&gt;React Native 공식 문서&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;&lt;a href=&quot;https://docs.expo.dev/&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; margin-bottom: 0px;&quot;&gt;Expo 공식 문서&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;&lt;a href=&quot;https://reactnative.dev/docs/new-architecture-intro&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; margin-bottom: 0px;&quot;&gt;React Native 새 아키텍처 마이그레이션 가이드&lt;/a&gt;&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;&lt;a href=&quot;https://github.com/jondot/awesome-react-native&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; margin-bottom: 0px;&quot;&gt;Awesome React Native&lt;/a&gt;&nbsp;- RN 관련 유용한 라이브러리 및 도구 모음&lt;/li&gt;
	&lt;li style=&quot;box-sizing: inherit; margin-bottom: 2px; padding-left: 0px;&quot;&gt;&lt;a href=&quot;https://github.com/react-native-community&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: rgb(6, 135, 240); text-decoration-line: none; box-shadow: none; margin-bottom: 0px;&quot;&gt;React Native 커뮤니티&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr style=&quot;box-sizing: content-box; height: 1px; overflow: visible; margin: 0px 0px calc(-1px + 0.8125rem); padding: 0px; background: rgba(0, 0, 0, 0.2); border: none;&quot; /&gt;
&lt;blockquote style=&quot;box-sizing: inherit; margin: 0px 0px 0.8125rem; padding: 0px 0px 0px calc(-1px + 0.8125rem); border-left: 4px solid rgba(0, 0, 0, 0.13); color: rgb(153, 153, 153);&quot;&gt;
&lt;p style=&quot;box-sizing: inherit; margin: 0px; padding: 0px;&quot;&gt;전적으로 제 이해의 기준으로 작성했기 때문에 잘못된 내용이 있을 수 있습니다. 제가 잘못 알고 있는 내용이 있다면 댓글로 남겨주시면 확인하도록 하겠습니다!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;

&lt;hr class=&quot;custom-hr&quot; style=&quot;box-sizing: content-box; height: 2px; overflow: visible; margin: 64px; padding: 0px; background: linear-gradient(72deg, rgb(41, 30, 149), rgb(0, 163, 204)) rgb(255, 255, 255); border: none; color: rgba(0, 0, 0, 0.8); font-family: &quot;Noto Sans KR&quot;, sans-serif; font-size: 16px;&quot; /&gt;
&lt;div class=&quot;bio&quot; style=&quot;box-sizing: inherit; margin-bottom: 24px; color: rgba(0, 0, 0, 0.8); font-family: &quot;Noto Sans KR&quot;, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255); height: auto !important;&quot;&gt;
&lt;div class=&quot;author&quot; style=&quot;box-sizing: inherit; height: auto !important;&quot;&gt;
&lt;div class=&quot;author-description&quot; style=&quot;box-sizing: inherit; display: flex;&quot;&gt;
&lt;div class=&quot;author-image gatsby-image-wrapper&quot; style=&quot;box-sizing: inherit; margin-top: 12px; margin-right: 12px; margin-bottom: 0px; min-width: 72px; position: relative; overflow: hidden; display: inline-block; width: 72px; height: 72px; border-radius: 100%;&quot;&gt;&lt;img alt=&quot;[Ykss]&quot; aria-hidden=&quot;true&quot; src=&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAARlAAAEZQAGA43XUAAAD0ElEQVQ4y0WSW4gbVRzG81QQ+lCoL4LdSl21ii6oa0W8gL4oqOCjKOyTD4pPooIgRRDrkw9VS3FRkIq1db0UZVsKuybb3U02ySazm2RuyUwym5nJ5jKZzO2cuZzJxf9JVhy+OZyH8+P7X74E10S8igXd5zUfLnByus+pXt0Yae5EtSdNa1LrRLzmiS1f0DEVvG9i7gAlABY1X9R9QZvyVKhujFfX8ufPX/j68k9/3NwsVntyL+ZVj9ewqONaCwsa4poehVkVc1OBc+UAPCfLP1x76PTcyeN3zd194tTJEy8++9x6mpV7Q8rr9BmvIr45deaghiZmmwjIWidez/CLD5999alH3n3thQfuveex+TOP3ndq6a0lqRtDUbPKoQS+iRPAzDA4Sw1b7o2vXL95/Nixlc/eu/T+mw/OnT63sLAwf//zi09uFWXKq0jQprAK8AFiDzyAy4q7L1usTn65kXz9ibO3v/zgx4/fefvll155+vGF+TPPLJ5L7ylSh1BzDVOpKFGZkqBSw2GkQbbmZtKVwjefHP79nbG63Fj5Niqufrr0xucffUhnpiH+aOAI7hQuz2zrdqFmbvMWky2TrV/93b/GwsZIKkzqWXPte69WEtsERk09pyc/cwaypDhM3cpX+2neSu9w+u8XuyuXot1bowZDSretzJ8NdcC3ArE1JWkopgM7gutOUbJyYj9TMZK7avnni/1rl0MmNZYzQfZ6eY/j20NBR8L/OUEQlf/gBoWzopkudZJMZ+ufzGDrt7C8FuRuhPu3Gi1HoLZATmENTVc9gxtHzllxkN7vpJh2akcuLn9hr1+J2NTY63cdAkGqzmzpnmhCaMJKlIQlOQXJzomDDaadFfq1fFG6+lXMp2LHGE0mhJBDM4A+Obqho3hBuhJ7ks1IdlG28pK1I5gVXjPaHV+VreRV3KoPR+PhMI6CkESR44ZSC0MugARBOhIFydqtDfK1QUYcVOtdt33YrctmXQrMvtszfdshEQn8IAzCmJAwjICvKFNngPNVMyeYGc5k+M5A1z3T8vqmZ5oRGQWeH2CKhUEAziSOR8M4CKKqhljFozB0mOWMzf2OyCm2rmLbdY2+73kB9pHtBhhHYQSCtmP6DUdD0jNxueGxipvYqXR3Su2NQpPN5S1dx7aDbNvH2Hc9EPUkJIKWKQ8sTCD2UMAqDuwosb2nbzJqMiez25t9RUG243sIWkUDGy7QJJQLfxhEJJqxsY8DrmEzspO4U1A2dpVUVmI372jlfbtr+B52uoZrmNBzGJLQj6BzEIlmlccYhWXZLtbsfwGShe4mzftLrAAAAABJRU5ErkJggg==&quot; style=&quot;box-sizing: inherit; border-style: none; margin: 0px 0px 0.8125rem; padding: 0px; position: absolute; top: 0px; left: 0px; width: 72px; height: 72px; object-fit: cover; object-position: center center; opacity: 0; transition-delay: 500ms;&quot; /&gt;&lt;picture style=&quot;box-sizing: inherit;&quot;&gt;&lt;source srcset=&quot;/static/e1b6058af380e8a00f152aefa04db768/e5b88/profile.png 1x,
/static/e1b6058af380e8a00f152aefa04db768/e7bd6/profile.png 1.5x,
/static/e1b6058af380e8a00f152aefa04db768/a12fc/profile.png 2x&quot; style=&quot;box-sizing: inherit;&quot; /&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;[Ykss]&quot; height=&quot;72&quot; loading=&quot;lazy&quot; src=&quot;./files/attach/images/17429/612/112/7ce51c5124e352067d3fc255a194a291.png&quot; srcset=&quot;/static/e1b6058af380e8a00f152aefa04db768/e5b88/profile.png 1x,
/static/e1b6058af380e8a00f152aefa04db768/e7bd6/profile.png 1.5x,
/static/e1b6058af380e8a00f152aefa04db768/a12fc/profile.png 2x&quot; style=&quot;box-sizing: inherit; border-style: none; margin: 0px 0px 0.8125rem; padding: 0px; position: absolute; top: 0px; left: 0px; width: 72px; height: 72px; object-fit: cover; object-position: center center; opacity: 1; transition: opacity 500ms;&quot; width=&quot;72&quot; /&gt;&lt;/picture&gt;&lt;/div&gt;

&lt;div class=&quot;author-name&quot; style=&quot;box-sizing: inherit;&quot;&gt;&lt;span class=&quot;author-name-prefix&quot; style=&quot;box-sizing: inherit; font-size: 14.4px; margin-right: 4px;&quot;&gt;Written by&lt;/span&gt;&lt;a class=&quot;author-name-content&quot; href=&quot;https://ykss.notion.site/Kyeongsang-Yu-a4ddc1935ee74a0aafbb311aa7f675e7&quot; style=&quot;box-sizing: inherit; background-color: rgb(236, 240, 242); color: navy; text-decoration-line: none; box-shadow: none; margin-right: 8px; font-size: 15.2px; display: inline-block; padding: 2px 6px; font-weight: bolder; border-radius: 8px; transform-origin: center center; animation: 2s linear 0s infinite normal none running flutter;&quot;&gt;&lt;span style=&quot;box-sizing: inherit;&quot;&gt;@[Ykss]&lt;/span&gt;&lt;/a&gt;

&lt;div class=&quot;author-introduction&quot; style=&quot;box-sizing: inherit; margin-top: 4px; font-size: 12.8px; line-height: 1.4; color: rgb(125, 125, 125);&quot;&gt;고이게 두지 않고 흘려보내는 개발자가 되자.&lt;/div&gt;

&lt;p class=&quot;author-socials&quot; style=&quot;box-sizing: inherit; margin: 4px 0px 0.8125rem; padding: 0px;&quot;&gt;&lt;a href=&quot;https://github.com/ykss&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: navy; text-decoration-line: none; box-shadow: none; margin-right: 8px; font-size: 12.8px;&quot;&gt;GitHub&lt;/a&gt;&lt;a href=&quot;https://www.instagram.com/kyeongsangyu&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: navy; text-decoration-line: none; box-shadow: none; margin-right: 8px; font-size: 12.8px;&quot;&gt;Instagram&lt;/a&gt;&lt;a href=&quot;https://www.linkedin.com/in/kyeongsangyu/&quot; style=&quot;box-sizing: inherit; background-color: transparent; color: navy; text-decoration-line: none; box-shadow: none; margin-bottom: 0px; margin-right: 8px; font-size: 12.8px;&quot;&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;author-socials&quot; style=&quot;box-sizing: inherit; margin: 4px 0px 0.8125rem; padding: 0px;&quot;&gt;&nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;[출처]&nbsp;https://ykss.netlify.app/devlog/start_with_RN/&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Fri, 15 Aug 2025 16:09:34 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[no code 게임개발] PlayMaker 요약]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/111732</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/111732</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/111732#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[no code 게임개발] PlayMaker 요약&lt;/h1&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;
&nbsp;&lt;/pre&gt;

&lt;p&gt;PlayMaker 의 시작은 GameObject 에 PlayMakerFSM 컴포넌트를 추가하는 것이다. 인스펙터에서 직접 추가해도 되고 PlayMaker Editor 창을 이용해도 된다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;GameObject 에 추가된 PlayMakerFSM 컴포넌트가 바로 하나의 FSM 객체가 된다. 같은 게임 오브젝트에 여러 PlayMakerFSM 컴포넌트를 추가하는 것으로 여러 FSM 객체를 만들 수 있다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 630px;  height: auto; max-width: 100%;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; data-phocus-index=&quot;0&quot; filemime=&quot;image/jpeg&quot; filename=&quot;1.png&quot; height=&quot;433&quot; src=&quot;./files/attach/images/17429/732/111/ea3d0d903e796e7cd03f01268363e614.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F276DDF3456927F5B15&quot; style=&quot;height: auto;&quot; width=&quot;630&quot; /&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;PlayMaker Editor 창에서 하나의 FSM 을 편집할 수 있다. FSM 은 반드시 하나의 Start State 를 가지며 위 그림처럼 &quot;START&quot; 가 연결되어 있다. 또한 단 하나의 State 만이 FSM 에서의 Active State 가 될 수 있다. PlayMakerFSM 컴포넌트가 enable 되었을 때 Start State 가 Active 된다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;State 는 FSM 에서 하나의 상태를 표현하는 객체이며 여러 Action, Transition 들로 구성된다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;Action 은 State 에서 수행할 하나의 작업을 표현하는 객체이며 게임 오브젝트의 이동, 회전에서부터 수많은 Action 들이 기본적으로 제공된다. 또한 직접 구현할 수도 있다. State 의 Action 들은 에디터에서 배치한 순서대로 수행된다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 630px;  height: auto; max-width: 100%;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; data-phocus-index=&quot;1&quot; filemime=&quot;image/jpeg&quot; filename=&quot;2.png&quot; height=&quot;433&quot; src=&quot;./files/attach/images/17429/732/111/a10c1d0aa59b9326bd298f344a6cdda3.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F21292F495692864E0C&quot; style=&quot;height: auto;&quot; width=&quot;630&quot; /&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;Transition 은 State 에서 다른 State 로의 전이를 표현하는 객체이며 Transition 에 지정된&nbsp;Event 가 발생했을 때 현재 State 는 비활성화되고 연결된 State 가 활성화된다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;Event 는 MOUSE DOWN 과 같은 PlayMaker 에서 제공하는 것들이 있고 사용자가 직접 추가할 수도 있다. 가장 자주 사용하는 Event&nbsp;로 State 의 모든 Action 들이 수행을 종료했을 때 발생하는 FINISHED Event 가 있다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;Variable 은 FSM 내에서 하나의 변수를 표현하는 객체이다. 따라서 특정 Action 의 결과를 Variable 에 저장해두고 다른 Action 에서 이를 사용할 수 있다. 또한 PlayMakerFSM 이 아닌 다른 컴포넌트에서도 이 객체를 참조하여 값을 얻거나 변경할 수 있다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;Global Variable 은 모든 FSM 들이 접근할 수 있다.&lt;/p&gt;

&lt;p&gt;출처: &lt;a href=&quot;https://cacodemon.tistory.com/entry/PlayMaker-%EC%9A%94%EC%95%BD&quot;&gt;https://cacodemon.tistory.com/entry/PlayMaker-요약&lt;/a&gt; [카코데몬의 잡동사니:티스토리]&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Wed, 05 Mar 2025 03:18:58 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[Ren&amp;apos;py] 렌파이로 육성 시뮬레이션 게임 만들기 (4) DSE 를 이용해 이벤트 만들기 (2) : 미연시 만들기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/111678</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/111678</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/111678#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[Ren&#39;py] 렌파이로 육성 시뮬레이션 게임 만들기 (4) DSE 를 이용해 이벤트 만들기 (2) : 미연시 만들기&lt;/h1&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;
&nbsp;&lt;/pre&gt;

&lt;h2 class=&quot;toc&quot;&gt;event.어쩌구() 함수 이용하기&lt;/h2&gt;

&lt;p&gt;이제 특별한 형태로 &amp; 특별한 조건에서 발생하는 이벤트를 만들어보도록 합시다.&lt;br /&gt;
&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/678/111/f26ae085d3920a3402bb14e1729bf766.png&quot; alt=&quot;2025-02-21-01 미소녀 연애 시뮬레이션을 만들기 01 - A stunning anime-style girl standing in a cozy school library, surrounded by bookshelves filled with books. She has a sweet and charming expression, w.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;
 

&nbsp;&lt;/pre&gt;

&lt;h3 class=&quot;toc&quot;&gt;event.once()&lt;/h3&gt;

&lt;p&gt;* 스트레스가 일정 수치에 도달하면, 좀 쉬어가면서 하라는 식의 &lt;span style=&quot;font-weight: bold;&quot;&gt;안내&lt;/span&gt; 이벤트가 튀어나오도록 해봅시다.&lt;br /&gt;
&lt;br /&gt;
* 이 이벤트는 한 번만 나타나면 충분할 겁니다.&lt;br /&gt;
&lt;br /&gt;
* 일단은 스트레스가 5 이상이 되었을 때 이벤트가 등장해야겠고.. 이벤트가 한 번만 나타나도록 하는 조건은..&lt;br /&gt;
&lt;br /&gt;
*&lt;span style=&quot;font-weight: bold;&quot;&gt; event.once()&lt;/span&gt; 함수를 사용하면 됩니다. event.once()는 항상 참값을 반환하다가, event.once()가 적힌 이벤트가 실행되고 나면 그 이벤트에 적인 event.once() 는 거짓값을 반환하기 때문에, 한 번만 나타나면 이벤트의 조건으로 사용하면 좋습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 725px; height: 357px;&quot;&gt;init:
    event(&#39;rest_notice&#39;, &#39;stress &gt;=5 &#39;, event.once(), priority = 90 )

label rest_notice:
    &#39;아..... 졸려&#39;
    &#39;과도하게 경기 준비를 했더니 몸이 피로해졌나보다. 쉬어가면서 해야지&#39;
    return&lt;/textarea&gt;&lt;br /&gt;
&nbsp;&lt;/p&gt;

&lt;h3 class=&quot;toc&quot;&gt;event.solo()&lt;/h3&gt;

&lt;p&gt;* 정신력이 3 미만인 상태에서 휴식 중에 TV를 보다, 우연히 라이벌의 경기를 보고 &lt;span style=&quot;font-weight: bold;&quot;&gt;자극&lt;/span&gt;을 받았다.. 는 내용의 이벤트를 만들어보겠습니다.&lt;br /&gt;
&lt;br /&gt;
* 이 이벤트는 휴식 스케쥴이 실행됐을 때, 일반 휴식 이벤트 (rest) 를 대신해서 실행되도록 만들겠습니다.&lt;br /&gt;
&lt;br /&gt;
* 일단 priority 값을 낮게 줘서 이 이벤트의 실행 조건이 먼저 판별되게 한 다음,&lt;br /&gt;
&lt;br /&gt;
* &#39;act == &quot;휴식&quot; and mental &lt; 3&#39; 이라는 조건에서 실행되도록 적습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy; gutter:false&quot; style=&quot;height: 270px; width: 722px;&quot;&gt;event(&#39;steampack&#39;, &#39;act == &quot;휴식&quot; and mental &lt; 3&#39;, priority = 90)
&lt;/textarea&gt;&lt;br /&gt;
* 이걸로 자극 이벤트의 설정은 완료입니다. 손 볼 곳은 rest 이벤트쪽입니다.&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy; highlight:[2]; gutter:false&quot; style=&quot;width: 717px; height: 197px;&quot;&gt;event(&#39;rest&#39;, &#39;act == &quot;휴식&quot;&#39;, priority=  100
         , event.solo()
        )
&lt;/textarea&gt;&lt;br /&gt;
이 &lt;span style=&quot;font-weight: bold;&quot;&gt;event.solo()&lt;/span&gt;를 사용한 이벤트는, 이벤트 실행 조건을 충족하였으며 event.solo()를 사용한 이벤트보다 우선도가 높은, 즉, priority 값이 작은 이벤트가 없는 경우에만 실행됩니다. 예제를 이용해서 설명을 하자면 다음과 같습니다.&lt;br /&gt;
&lt;br /&gt;
자극 이벤트는 휴식 이벤트와 실행 조건이 같지만, 자극 이벤트 쪽이 우선도가 높으므로, 자극 이벤트가 실행될 때는 휴식 이벤트가 실행되지 않습니다.&lt;br /&gt;
&lt;br /&gt;
event.solo() 함수는 비슷한 상황에서 실행되는 이벤트 중에 우선도가 높은 이벤트가 있다면 실행되지 말아야 할 이벤트에 사용하면 좋습니다.&lt;br /&gt;
&lt;br /&gt;
&nbsp;&lt;/p&gt;

&lt;h3 class=&quot;toc&quot;&gt;event.only()&lt;/h3&gt;

&lt;p&gt;* 이제 주인공이 스트레스가 높아 &lt;span style=&quot;font-weight: bold;&quot;&gt;병&lt;/span&gt;에 걸리는 이벤트를 만들어봅시다.&lt;br /&gt;
&lt;br /&gt;
* 일단 우선도를 가장 높게, 그러니까 priority = 0 값을 가장 낮게 줍니다.&lt;br /&gt;
&lt;br /&gt;
* 그리고 스트레스가 3 * 플레이 일 수보다 높으면 병 이벤트를 발생시키도록 하겠습니다(기존에 적었던 병 상태 발병 공식은 무시하기로 했습니다.. -.-;).&lt;br /&gt;
&lt;br /&gt;
* 남은 건 이 이벤트보다 우선도가 낮은(priority 값이 높은) 다른 이벤트는 모두 발생하지 않도록 설정하는 겁니다. &lt;span style=&quot;font-weight: bold;&quot;&gt;event.only()&lt;/span&gt;를 적어줍시다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;height: 236px; width: 734px;&quot;&gt;event(&#39;sick&#39;, &#39;stress&gt; 3*day&#39;, event.only(), priority = 0)&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
오로지 이 상황에서는 이 이벤트만 튀어나와야 한다! 하는 이벤트에 사용해주도록 합시다.&lt;br /&gt;
&lt;br /&gt;
&nbsp;&lt;/p&gt;

&lt;h3 class=&quot;toc&quot;&gt;event.happened(*이벤트) 와 event.depends(*이벤트) 그리고 call events_end_day&lt;/h3&gt;

&lt;p&gt;&lt;br /&gt;
* 이번에 만들어볼 이벤트는 릴뤡스 입니다. 이 이벤트는 병 걸린 이벤트를 반드시 봐야지만 다음날 발생하도록 만들어줘야 합니다.&lt;br /&gt;
event.depends(*이벤트) 함수를 사용하면 이것을 가능하게 할 수 있습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;height: 278px; width: 738px;&quot;&gt;event(&#39;relax&#39;, event.depends(&#39;sick&#39;))
&lt;/textarea&gt;&lt;br /&gt;
그 전에, 이 event.depends()를 사용하면서 특정 이벤트가 하루 전에 발생했다는 걸 인식시키려면 하루 단위의 스케쥴이 모두 완료된 지점에 다음과 같은 명령어를 적어줘야 합니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy; highlight:[5]&quot; style=&quot;height: 258px; width: 732px;&quot;&gt;label afternoon:
    $ act = afternoon
    
    call events_run_period
    call events_end_day
    
    $ day +=1
    if day == 8:
#.......&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-weight: bold;&quot;&gt;call events_end_day&lt;/span&gt; 를 사용하면, 예를 들면 첫째 날에 a 라는 이벤트가 발생한 경우 events_excuted_yesterday 라는 변수에 이 이벤트가 실행되었다는 것을 저장하고, 둘째날 진행으로 넘어가게 됩니다.&lt;br /&gt;
&lt;br /&gt;
그러니까 &lt;span style=&quot;font-weight: bold;&quot;&gt;event.depends(&lt;/span&gt;&lt;span style=&quot;font-style: italic; font-weight: bold;&quot;&gt;*이벤트&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;)&lt;/span&gt; 를 사용하게 되면, 이 함수는 &lt;span style=&quot;font-style: italic;&quot;&gt;이벤트&lt;/span&gt;에 적은 이벤트를 events_excuted_yesterday 에서 검색할 수 있게 되는 겁니다. 이벤트를 발견했다면 event.denpends()가 사용된 이벤트를 실행시키게 됩니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-weight: bold;&quot;&gt;event.happened(*&lt;span style=&quot;font-style: italic;&quot;&gt;이벤트&lt;/span&gt;)&lt;/span&gt; event.depends()와 비슷하지만 이는 게임 중에 &lt;span style=&quot;text-decoration-line: underline;&quot;&gt;어느 때라도&lt;/span&gt; &lt;span style=&quot;font-style: italic;&quot;&gt;이벤트&lt;/span&gt;가 발생했다면 event.happened() 가 적힌 이벤트를 실행한다는 것이 다른 점입니다.&lt;/p&gt;

&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;h3 class=&quot;toc&quot;&gt;event.random(확률)&lt;/h3&gt;
&nbsp;* 일정한 확률에 따라 이벤트를 발생시킬 수 있도록 해주는 함수입니다. 입력하는 값은 부동소수점값(소수점 찍힌 숫자)이어야 합니다. 어려운 점은 없다고 생각해서 자세한 예는 생략하겠습니다.&lt;br /&gt;
&lt;br /&gt;
* 이 함수를 이용하면 능력치값을 계산해서 일반 스탯 획득의 성공/실패를 가를 수 있을 겁니다. 프린세스 메이커에서 능력치에 따라 알바/학습의 성공/실패가 갈라졌었죠. 그런 걸 얘기하는 겁니다.&lt;/p&gt;
&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;h3 class=&quot;toc&quot;&gt;event.choose_one(group, group_count = 1)&lt;/h3&gt;
&lt;br /&gt;
* 이번에는 마인드 컨트롤을 하면 등장하는 이벤트 두 가지를 만들어보겠습니다.&lt;br /&gt;
&lt;br /&gt;
* 한 이벤트는 보통의 이벤트이지만, 낮은 확률로 마인드 컨트롤을 하다가 잠을 자버리는 -0- 이벤트가 발생하도록 만들겁니다.&lt;br /&gt;
&lt;br /&gt;
* 일단 새 이벤트를 하나 더 만듭니다.&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 713px; height: 344px;&quot;&gt;event(&#39;m_control&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;, priority = 100 )
event(&#39;m_control_sleep&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;, priority = 100 )
&lt;/textarea&gt;&lt;br /&gt;
* 그 다음 이 두 이벤트를 하나의 그룹으로 묶어줍니다. 이 그룹으로 묶는 작업을 위해 &lt;span style=&quot;font-weight: bold;&quot;&gt;event.choose_one()&lt;/span&gt;을 사용합시다.&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;height: 318px; width: 733px;&quot;&gt;event(&#39;m_control&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;, event.choose_one(&quot;마컨&quot;), priority = 100 )
event(&#39;m_control_sleep&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;, event.choose_one(&quot;마컨&quot;), priority = 100 )&lt;/textarea&gt;&lt;br /&gt;
이렇게 하면 두 이벤트가 &quot;마컨&quot; 이라는 하나의 그룹으로 묶이게 된 겁니다. 이제 마인드 컨트롤 스케쥴을 실행할 때마다 자동으로 저 두 이벤트 중 하나가 선택되어 실행될 겁니다.&lt;br /&gt;
&lt;br /&gt;
마인드 컨트롤을 하다가 낮잠을 자는 이벤트는 확률이 일반 마컨 스케쥴보다 낮아야 합니다. group_count 로 잠 자는 이벤트에 낮은 숫자를, 일반 이벤트에는 높은 숫자를 지정해줍시다.&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 815px; height: 343px;&quot;&gt;event(&#39;m_control&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;, event.choose_one(&quot;마컨&quot;, group_count = 10), priority = 100 )
event(&#39;m_control_sleep&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;, event.choose_one(&quot;마컨&quot;, group_count = 5), priority = 100 )&lt;/textarea&gt;&lt;br /&gt;
(위의 스크립트에서는 확인용으로 m_control_sleep 이벤트의 group_count 를 높게 줬습니다)&lt;br /&gt;
&lt;br /&gt;
group_count 는 큰 값이 확률이 높고 적은 값이 확률이 적습니다.&lt;br /&gt;
&lt;br /&gt;
이전 글에서도 적었지만, event()에는 위에 열거한 event.어쩌구 들을 전부 혼합해서 사용할 수도 있습니다. 이벤트의 성격에 맞게 각각 조합해서 사용한다면 보다 복잡한 조건에서 발생하는 이벤트도 만들 수 있습니다.&lt;/p&gt;
&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;h2 class=&quot;toc&quot;&gt;끝&lt;/h2&gt;
네 끝입니다..) 렌파이로 육성 시뮬레이션을 만들 때 필요한 지식은 설명해드린 것이 전부이고, 앞으론 알게 된 기능을 응용해 만드는 일만 남았습니다. 모쪼록 재미나게 게임 만드시길.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/678/111/dd925645c966603019c502114bebc054.png&quot; alt=&quot;2025-02-21-02 미소녀 연애 시뮬레이션을 만들기 02 - A stunning anime-style girl standing in a cozy school library, surrounded by bookshelves filled with books. She has a sweet and charming expression, w.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;출처: &lt;a href=&quot;https://askance.tistory.com/45&quot;&gt;https://askance.tistory.com/45&lt;/a&gt; [백안시의 공방 - 소설형 게임 제작실:티스토리]&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Fri, 21 Feb 2025 20:55:35 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[Ren&amp;apos;py] 렌파이로 육성 시뮬레이션 게임 만들기 (3) DSE 를 이용해 이벤트 만들기 (1)]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/111652</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/111652</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/111652#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[Ren&#39;py] 렌파이로 육성 시뮬레이션 게임 만들기 (3) DSE 를 이용해 이벤트 만들기 (1)&nbsp;&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/652/111/015eac250d7ee86e1ab691ad575d513d.png&quot; alt=&quot;2025-02-18-01 미연시 게임 여주 01 2025-02-18 00.12.02 - A beautiful anime-style girl standing in a school library, with bookshelves filled with books in the background. She has a charming and sweet expressi.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;
이제 연습 게임에 이벤트를 채워봅시다. event_dispatcher.rpy 를 본격적으로 사용할 시간입니다.


그 전에 DSE 엔진의 events.rpy 파일을 확인해서, 이벤트는 어떤 식으로 스크립트를 써야 만들어지는지 살펴봅시다.&lt;textarea class=&quot;brush:rpy; toolbar:true&quot; style=&quot;width: 611px; height: 310px;&quot;&gt;#events.rpy 의 스크립트 일부
init:
    $ event(&quot;class&quot;, &quot;act == &#39;class&#39;&quot;, event.only(), priority=200)
    $ event(&quot;class_bad&quot;, &quot;act == &#39;class&#39;&quot;, priority=210)
    $ event(&quot;cut1&quot;, &quot;act == &#39;cut&#39;&quot;, event.choose_one(&#39;cut&#39;), priority=200)
    $ event(&quot;cut2&quot;, &quot;act == &#39;cut&#39;&quot;, event.choose_one(&#39;cut&#39;), priority=200)
&lt;/textarea&gt;





&lt;/pre&gt;

&lt;h2 class=&quot;toc&quot;&gt;event() 해석&lt;/h2&gt;

&lt;p&gt;이벤트를 만드려면 파이썬 블록에 event(&lt;span style=&quot;font-style: italic;&quot;&gt;어쩌구&lt;/span&gt;) 라고 적어야 합니다. &lt;span style=&quot;font-style: italic;&quot;&gt;어쩌구&lt;/span&gt;에 있는 내용을 간단히 해석하자면 다음과 같습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-weight: bold;&quot;&gt;event&lt;/span&gt;(&lt;span style=&quot;font-style: italic;&quot;&gt;&#39;레이블 이름&#39;&lt;/span&gt;, &lt;span style=&quot;font-style: italic;&quot;&gt;priority&lt;/span&gt; = 우선도, 나머지는 전부 &lt;span style=&quot;font-style: italic;&quot;&gt;이벤트 실행 조건&lt;/span&gt;)&lt;br /&gt;
&lt;br /&gt;
- 레이블 이름&lt;/p&gt;

&lt;div style=&quot;margin-left: 4em;&quot;&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;이벤트 실행 조건&lt;/span&gt;이 참일 때 불러올 레이블 블럭의 이름입니다.&lt;/div&gt;

&lt;div&gt;&lt;br /&gt;
- 이벤트 실행 조건&lt;/div&gt;

&lt;div style=&quot;margin-left: 4em;&quot;&gt;말 그대로입니다. 파이썬 표현식을 문자열 형태로 적거나 (ex &#39;act == &quot;class&quot;&#39;), 아니면 위의 예제에서 보이는 event.어쩌구 와 같은, DSE 를 이용할 때만 사용 가능한 함수를 적어야 합니다. 이 함수에 대해서는 다음 글에서 다시 설명하겠습니다.&lt;br /&gt;
&lt;br /&gt;
어쨌든 이 실행 조건들 간에는 파이썬 표현식에서 사용할 수 있는 and 나 or, not 같은 연산자를 사용할 수 있습니다.&lt;br /&gt;
event(&#39;marry&#39;, event.depends(&#39;engage_1&#39;) or event.depends(&#39;engage_2&#39;)) 나,&lt;br /&gt;
event(&#39;sub_lesson&#39;, event.depends(&#39;get_Fail&#39;) and &#39;intelligence == 0&#39;) 처럼 쓸 수 있다는 얘기입니다.&lt;/div&gt;

&lt;div&gt;&lt;br /&gt;
- priority&lt;/div&gt;

&lt;div style=&quot;margin-left: 4em;&quot;&gt;단어 뜻 그대로 해당 이벤트의 우선도를 나타냅니다. 기본값은 100 이며 이 값이 낮을 수록 해당 이벤트의 실행 조건이 먼저 고려됩니다. 여기서 조심하실 게 하나 있습니다. 만일 &lt;span style=&quot;font-weight: bold;&quot;&gt;이벤트 실행 조건이 똑같은 2 개의 이벤트&lt;/span&gt;가 있다고 가정했을 때, 한 쪽의 priority 가 10 이고 다른 이벤트는 priority 가 200 이라고 해서 &lt;span style=&quot;font-weight: bold;&quot;&gt;우선도가 더 높은 쪽의 이벤트가 실행이 안 되는 것이 아닙니다&lt;/span&gt;. &lt;span style=&quot;text-decoration-line: underline;&quot;&gt;priority 가 1000짜리라도 실행 조건만 충족되면 발생합니다&lt;/span&gt;. 아까도 적었지만, priority 는 해당 이벤트의 실행 조건을 먼저 따질 때 사용하는 수치인 것이지, 우선도가 낮은 다른 이벤트를 배제하고 실행하지 않는다는 의미가 아닙니다.&lt;/div&gt;

&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
* 아까 이벤트 실행 조건 설명할 때 넘어갔던 event.어쩌구 함수들..은 직접 이벤트를 만들면서 설명드리겠습니다.&lt;br /&gt;
&lt;br /&gt;
&nbsp;
&lt;h2 class=&quot;toc&quot;&gt;이벤트 만들기&lt;/h2&gt;

&lt;p&gt;프로젝트/game 폴더에 event_dispatcher.rpy 들어있는 것 확인하시고, 이제 이벤트를 만들어보도록 합시다.&lt;br /&gt;
&lt;br /&gt;
* 이벤트에는 여러가지 내용이 들어가니까 관리하기 쉽게 스크립트 파일을 새로 만듭시다. 전 events.rpy 라는 새 파일을 만들었습니다.&lt;br /&gt;
&lt;br /&gt;
* 이제 어떤 이벤트가 필요할지 생각해봅시다.&lt;br /&gt;
&lt;br /&gt;
* 일정 조건을 달성하면 뿅 하고 등장하는 그런 것 외에도, 일반적인 상황에서 발생하는 스케쥴 실행 화면도 이벤트로 칩시다. 여러 게임에서는 기본 스케쥴을 실행할 때도 특정 조건에 따라 성공/실패 여부가 갈려서 스탯을 획득하거나 하니까요(예제 게임에선 그런 식으로 만들지는 않을 겁니다만 참고하시라는 의미에서 적어둡니다).&lt;br /&gt;
&lt;br /&gt;
* 기초 설정 잡았을 때, 스케쥴 종류가 휴식, 전략 구상, 마인드 컨트롤, 연습 이렇게 네 가지 있었습니다.&lt;br /&gt;
&lt;br /&gt;
휴식: 스트레스 4 감소, 정신력 1 증가,&lt;br /&gt;
연습: 상황 판단력 1 증가, 반응 속도 3 증가, 스트레스 3 증가.&lt;br /&gt;
전략 구상: 상황 판단력 2 증가, 정신력 1 증가, 스트레스 2 증가&lt;br /&gt;
마인드 컨트롤: 정신력 2 증가&lt;br /&gt;
&lt;br /&gt;
(스트레스는 stress, 정신력은 mental, 상황 판단력은 judge, 반응 속도는 react 라는 변수명을 정해주었죠)&lt;br /&gt;
&lt;br /&gt;
* 일단 각 스케쥴이 실행되면, 발생할 이벤트의 내용이 적인 레이블을 만들어줍니다. 이벤트로 쓰이는 각 레이블은 호출(call)되는 형식이기 때문에 레이블마다 끝에 return 을 적어주어서 원래 진행 흐름으로 돌아갈 수 있도록 해야 합니다. 진행상황을 확인할 수 있도록 한마디도 써줍시다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;height: 571px; width: 703px;&quot;&gt;label rest:
    
    $ stress = max(stress - 4, 0)
    $ mental += 1
    &#39;얌전히 쉬었다.&#39;
    return
    
label practice:
    
    $ judge += 1
    $ react += 3
    $ stress += 3
    &#39;연습했다&#39;
    return
    
label strategy:
    
    $ judge += 2
    $ mental += 1
    $ stress += 2
    &#39;전략을 구상했다&#39;
    return
    
label m_control:
    
    $ mental += 2
    &#39;마인드 컨트롤을 했다&#39;
    return
&lt;/textarea&gt;&lt;br /&gt;
# 여기서 stress =&nbsp; max(stress -4, 0) 는&lt;br /&gt;
stress 에서 - 4 하되 만일 이 결과값이 0보다 작으면 0을 stress 변수에 배정한단 의미입니다. 스탯 수치가 0 이하로 내려가지 않도록 하기 위해 사용한 함수입니다.&lt;br /&gt;
&lt;br /&gt;
* 그리고 event() 함수를 이용해서 각 레이블이 실행될 수 있도록 이벤트들을 만들어줍니다. 우선도는 적지 않았으니, 기본값인 100이 적용될 겁니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 659px; height: 172px;&quot;&gt;init python:
   
    event(&#39;rest&#39;)
    event(&#39;practice&#39;)
    event(&#39;strategy&#39;)
    event(&#39;m_control&#39;)
&lt;/textarea&gt;&lt;br /&gt;
이제 실행 조건을 적을 차례입니다. 사용자가 정한 스케쥴만 제 때 실행되도록 조건을...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
어떻게 적어야 할까여....-.-&lt;br /&gt;
&lt;br /&gt;
지금 스케쥴이&lt;br /&gt;
&lt;br /&gt;
$ morning = &#39;휴식&#39;&lt;br /&gt;
$ free = &#39;마인드 컨트롤&#39;&lt;br /&gt;
&lt;br /&gt;
같은 식으로 저장되어 있고 스크립트는&lt;br /&gt;
&lt;br /&gt;
label morning:&lt;br /&gt;
label free:&lt;br /&gt;
label afternoon:&lt;br /&gt;
&lt;br /&gt;
이런 식으로 작성되어있죠.&lt;br /&gt;
&lt;br /&gt;
그럼 변수를 하나 만들어서 그 변수에 morning, free, afternoon 에 저장된 값을 옮기고, 각 레이블 끝마다 이벤트를 불러오도록 하면 되겠네요.&lt;br /&gt;
&lt;br /&gt;
급하게 act 라는 변수를 하나 만듭시다.&lt;br /&gt;
&lt;br /&gt;
act = &#39;&#39;&lt;br /&gt;
&lt;br /&gt;
그리고 각 레이블에마다 act 를 적고 해당 시기에 실행할 스케쥴의 정보를 또 저장하도록 해줍니다.&lt;br /&gt;
&lt;br /&gt;
label morning:&lt;br /&gt;
&nbsp;&nbsp;&nbsp; $ act = morning&lt;br /&gt;
&nbsp;&nbsp;&nbsp;&lt;br /&gt;
이제 이벤트를 호출할 수 있도록 명령어를 하나 더 적어줍니다.&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;height: 189px; width: 527px;&quot;&gt;label morning:
    $ act = morning
    call events_run_period
# 나머지 라벨도 같은 식으로.. 
&lt;/textarea&gt;&lt;br /&gt;
call events_run_period 를 사용하면 event() 로 만들어진 이벤트들 중에서 현재 조건에 맞는 이벤트를 실행시킬겁니다.&lt;br /&gt;
이제 다시 events.rpy 로 돌아가서 event() 함수들을 마저 작성합시다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 334px; height: 210px;&quot;&gt;init python:
    
    event(&#39;rest&#39;, &#39;act == &quot;휴식&quot;&#39;)
    event(&#39;practice&#39;, &#39;act ==&quot;연습&quot;&#39;)
    event(&#39;strategy&#39;, &#39;act == &quot;전략 구상&quot;&#39;)
    event(&#39;m_control&#39;, &#39;act == &quot;마인드 컨트롤&quot;&#39;)&lt;/textarea&gt;&lt;br /&gt;
여기까지 완성한 게임의 스크립트를 확인하시고, 게임을 테스트해보시면서 잘못된 부분이 있나 확인합시다.&lt;br /&gt;
&lt;br /&gt;
저는 7일째를 판정하는 if 문이랑 day 변수를 잘못 써서 6일 째에 게임이 끝나게 되더군요.. 그 부분을 수정했습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy; highlight: [5, 6]&quot; style=&quot;width: 426px; height: 256px;&quot;&gt;label afternoon:
    $ act = afternoon
    call events_run_period
    
    $ day +=1
    if day == 8:
        jump ending
    else:
        jump schedule_set&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
다음 글은 특별한 조건에서 실행되는 이벤트를 만드는 방법입니다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/652/111/54cc94508c1b067403658bfc56020ee4.png&quot; alt=&quot;2025-02-18-01 미연시 게임 여주 02  2025-02-18 00.12.51 - A beautiful anime-style girl standing in a school library, with bookshelves filled with books in the background. She has a charming and sweet expressi.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;출처: &lt;a href=&quot;https://askance.tistory.com/44&quot;&gt;https://askance.tistory.com/44&lt;/a&gt; [백안시의 공방 - 소설형 게임 제작실:티스토리]&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Tue, 18 Feb 2025 00:24:50 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[Ren&amp;apos;py] 렌파이로 육성 시뮬레이션 게임 만들기 (2) 스크린 언어로 스케쥴 화면 만들기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/106044</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/106044</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/106044#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[Ren&#39;py] 렌파이로 육성 시뮬레이션 게임 만들기 (2) 스크린 언어로 스케쥴 화면 만들기&lt;/h1&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;
&nbsp;&lt;/pre&gt;

&lt;h2 class=&quot;toc&quot;&gt;필요한 게 뭘까&lt;/h2&gt;

&lt;h2 class=&quot;toc&quot;&gt;&nbsp;&lt;/h2&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;

구조는 잡았으니 이제 다음으로 필요한 게 뭔지 생각해봅시다. 렌파이의 기본 UI를 (귀찮으므로) 그냥 사용하기로 했다 치면, 그 외에 필요한 건 아래와 같습니다.



- 스탯을 표시하는 화면

- 플레이어가 스케쥴을 정할 수있게 해주는 화면

- 플레이어가 정한 스케쥴을 확인할 수 있게 해주는 화면



&lt;/pre&gt;

&lt;h2 class=&quot;toc&quot;&gt;스탯창&lt;/h2&gt;

&lt;h2 class=&quot;toc&quot;&gt;&nbsp;&lt;/h2&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;

일단 스탯창은 쉽게 만들 수 있습니다. 스크린 언어를 이용해서 만들어보도록 합시다.&lt;textarea class=&quot;brush:rpy; toobar:true&quot; style=&quot;width: 587px; height: 331px;&quot;&gt;init:
    screen stat: # 스탯창
        frame:
            align (0.0 , 0.7)  # 스탯창의 위치
            grid 4 2:  # text 정렬용 박스. 4열 2행짜리 정렬용 박스를 만든다.
                text &#39;정신력&#39;
                text &#39;판단력&#39;
                text &#39;민첩성&#39;
                text &#39;스트레스&#39;
                
                text str(mental)  # 해당 변수의 수치 표시.
                text str(judge)
                text str(react)
                text str(stress)&lt;/textarea&gt;



text 가 문자열만을 받아서 화면에 표시하기 때문에, str(&lt;span style=&quot;font-style: italic;&quot;&gt;변수&lt;/span&gt;)로  &lt;span style=&quot;font-style: italic;&quot;&gt;변수&lt;/span&gt;에 저장된 정수값을 문자열로 바꾸는 역할을 해 주는 겁니다(&#39;0&#39; 과 0 은 전혀 다른 종류의 값으로, 각각 문자열과 정수값입니다).



종전에 ui 문에서 그랬던 것처럼

text (&#39;%s&#39; %mental) 

이라고 적어도 됩니다만 저는 % 기호를 적는 게 귀찮아서; str 함수를 이용했습니다.



&lt;/pre&gt;

&lt;h2 class=&quot;toc&quot;&gt;스케쥴 설정 화면&lt;/h2&gt;

&lt;h2 class=&quot;toc&quot;&gt;&nbsp;&lt;/h2&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;

그 다음은 스케쥴 설정 화면입니다. 제가 만드려는 방식은 



&lt;/pre&gt;

&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 599px;  height: auto; max-width: 100%;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; data-phocus-index=&quot;0&quot; filemime=&quot;image/jpeg&quot; filename=&quot;제목 없음.jpg&quot; height=&quot;250&quot; src=&quot;./files/attach/images/17429/044/106/36516f55b47ce9224ca4adf6f5f7484a.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F1209BC334D30623625&quot; style=&quot;height: auto;&quot; width=&quot;599&quot; /&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;
&lt;p&gt;&lt;br /&gt;
이런 식입니다. 렌파이 튜토리얼 게임에서 ui 항목에 나와있는 예제랑 비슷한 방식입니다. 그림을 이해하기 힘드신 분들은 튜토리얼 게임에서 작동을 확인해보세요.&lt;br /&gt;
&lt;br /&gt;
튜토리얼 게임에 나온 스케쥴러는, 스크립트를 확인해보시면 아시겠지만 ui 문과 파이톰이 자작한 함수 몇가지로 만들어졌습니다. 저는 스크린 언어로 한번 작성해보도록 하겠습니다.&lt;br /&gt;
&lt;br /&gt;
우선 오전, 자유, 오후 시간에 어떤 스케쥴이 정해졌는지 이에 관한 정보를 담은 변수를 하나씩 만들어줍시다. 초기값은 무조건 휴식이 되도록 줬습니다.&lt;br /&gt;
&lt;br /&gt;
morning = free = afternoon = &#39;휴식&#39;&lt;br /&gt;
&lt;br /&gt;
그럼 이제 위의 그림에서 1 이라고 표시한 UI 먼저 만들어봅시다. 감이 안 오더라도 그냥 막히는 데까지만 적으면 됩니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 786px; height: 352px;&quot;&gt;    screen planner: # 스크린 문은 init 블록 안에서 작성하는 게 좋습니다.
        vbox: # 정렬을 위한 vbox
            align (.5, .5)  # vbox 의 위치
            grid 3 2:  # 정렬을 위한 3x2 의 grid
                text &#39;오전 연습 시간&#39; #해당 스케쥴을 실행할 시기를 글로 표시.
                text &#39;자유 시간&#39;
                text &#39;오후 연습 시간&#39;
                
                textbutton morning # morning 변수에 저장된 글자가 표시될 텍스트버튼
                textbutton free # 같은식
                textbutton afternoon 
                
            textbutton &#39;완료&#39; action Return() align (.5, .5) # 스케쥴을 완료했을 때 누르면 됨.&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
이제 이 화면에 있는 텍스트 버튼을 눌렀을 때, 그 시기에 실행할 스케쥴을 정하는 스케쥴 선택지를 표시하도록 해야 합니다(그림에서 2라고 표시한 부분). 이것도 막히는 데까지 적어봅시다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush: rpy&quot; style=&quot;width: 801px; height: 280px;&quot;&gt;    screen schedule:
        frame: # 구색맞추기용 frame
            
            align (.5, .8) # frame 의 위치
            vbox: # 정렬용 vbox
                text &#39;실행할 스케쥴을 선택하세요&#39; # 안내 문구
                textbutton &#39;휴식&#39; 
                textbutton &#39;연습&#39; 
                textbutton &#39;전략 구상&#39; 
                textbutton &#39;마인드 컨트롤&#39;&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
이제 그림에서 1이라고 표시한.. 그러니까 planner 스크린 문으로 다시 돌아가서, 각 텍스트버튼을 클릭했을 때 schedule 스크린이 표시되도록 만들어줍니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush: rpy; highlight: [9, 10, 11]&quot; style=&quot;width: 853px; height: 297px;&quot;&gt;    screen planner: # 스크린 문은 init 블록 안에서 작성하는 게 좋습니다.
        vbox: # 정렬을 위한 vbox
            align (.5, .5)  # vbox 의 위치
            grid 3 2:  # 정렬을 위한 3x2 의 grid
                text &#39;오전 연습 시간&#39; #해당 스케쥴을 실행할 시기를 글로 표시.
                text &#39;자유 시간&#39;
                text &#39;오후 연습 시간&#39;
                
                textbutton morning action Show(&#39;schedule&#39;) 
                textbutton free action Show(&#39;schedule&#39;) 
                textbutton afternoon action Show(&#39;schedule&#39;)
                
            textbutton &#39;완료&#39; action Return() align (.5, .5) # 스케쥴을 완료했을 때 누르면 됨.&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
한층 자연스러워졌군요.. 는 구라고. 이쯤에서는 의문점을 가지셔야 합니다.&lt;br /&gt;
&lt;br /&gt;
&quot;세 개의 버튼이 모두 schedule 이라는 똑같은 스크린을 표시하는데, 어떻게 스케쥴 정보를 morning, free, afternoon 변수에 따로따로 저장을 할 수 있지?&quot;&lt;br /&gt;
&lt;br /&gt;
라고요.&lt;br /&gt;
&lt;br /&gt;
다시 schedule 스크린의 스크립트를 살펴봅시다. &#39;휴식&#39;, &#39;연습&#39; ... 등의 텍스트버튼이 제 구실을 하도록 action 속성을 입력해줘야할 필요성이 느껴집니다. Return(&lt;span style=&quot;font-style: italic;&quot;&gt;value&lt;/span&gt;) 액션은 그냥 텍스트버튼을 클릭하면 _return 이라는 변수에 &lt;span style=&quot;font-style: italic;&quot;&gt;value&lt;/span&gt; 를 저장하기 때문에 이 경우에는 그닥 적절해보이지는 않습니다. 우리가 지정한 변수에 특정한 값을 설정하도록 하는 액션으로는 SetVariable 이 더 적당합니다.&lt;br /&gt;
&lt;br /&gt;
SetVariable(variable, value)&lt;br /&gt;
&nbsp;&nbsp;&nbsp; value 를 variable 에 설정한다.&lt;br /&gt;
&lt;br /&gt;
여기서 주의할 점은 variable 자리에 변수 이름이 적힌 문자열이 와야 한다는 겁니다. 이 값을 어떻게 줘야 할지 의문입니다. 어떤 변수에 &quot;morning&quot; 이나 &quot;free&quot; 같은 문자열이 planner의 텍스트 버튼들을 누를 때마다 바뀌어서 저장된다면 가능할 것같긴 합니다. 임의로 period 라는 변수와 함께 SetVariable 을 각 텍스트버튼에 적어줍시다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 670px; height: 244px;&quot;&gt;    screen schedule:
    # ...
        textbutton &#39;휴식&#39; action SetVariable (period, &#39;휴식&#39;)
        # 다른 버튼들도 비슷한 식으로..
&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
흠. 그렇다면, planner 스크린에서 오전/자유/오후 텍스트버튼을 클릭할 때마다 각 시기에 해당하는 변수를, schedule 스크린으로 넘겨줘서, SetVariable 액션에 적을 variable 이 각 상황에 따라 바뀌도록 할 수 있다면 되겠군요. 알기 쉽게 그림으로 설명하자면 이런 느낌입니다.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 683px;  height: auto; max-width: 100%;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; data-phocus-index=&quot;1&quot; filemime=&quot;image/jpeg&quot; filename=&quot;cfile5.uf@183617334D307A5A128C5B.png&quot; height=&quot;337&quot; src=&quot;./files/attach/images/17429/044/106/203cfd7fbf9e9b0dcddc80a15f1a2d36.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F183617334D307A5A12&quot; style=&quot;height: auto;&quot; width=&quot;683&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;br /&gt;
쨌든 쉽게 설명하자면, schedule 이라는 스크린에서 사용할 변수를 planner에서 지정해주어야 한다는 이야기입니다.&lt;br /&gt;
&lt;br /&gt;
다행이도 이건 스크린 문에서 간단히 해결할 수 있습니다(그렇지 않다면 제가 이와 관련한 글을 쓰지도 않았을 겁니다^*^)&lt;br /&gt;
&lt;br /&gt;
아까 planner 스크린에 텍스트버튼마다 Show(&#39;schedule&#39;)이라고 적었죠. 그 옆에 약간만 뭔가를 추가해주면 됩니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;height: 169px; width: 648px;&quot;&gt;    screen planner: 
        # ....
             textbutton morning action Show(&#39;schedule&#39;, period = &#39;morning&#39;)
             # 다른 버튼들에도 각각 이런 식으로 추가해줘야함.&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
이렇게 하면 planner 에서 버튼을 누를 때마다 period 변수의 값이 따로 지정되어서 schedule 스크린을 불러오고, schedule 의 SetVariable 에 적힌 period 에는 해당 문자열값이 대체되기 때문에, 제대로 작동이 되는 겁니다.&lt;br /&gt;
&lt;br /&gt;
자 이제 완성.. 이면 좋겠지만 문제가 남아있습니다. schedule 스크린을 불러와서 텍스트 버튼을 클릭해줬는데, schedule 스크린이 사라지질 않아서 약간 거치적거립니다. SetVariable 액션이 실행되고 나면 schedule 스크린이 사라지도록 해야겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy; highlight:[3]&quot; style=&quot;width: 646px; height: 226px;&quot;&gt;    screen schedule:
    # ...
        textbutton &#39;휴식&#39; action [SetVariable(period, &#39;휴식&#39;), Hide(&#39;schedule&#39;) ]&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
예전에도 적었지만, 스크린 언어의 action 속성에는 액션의 리스트를 입력할 수도 있습니다. 이 때는 적힌 순서대로 해당 액션이 실행됩니다.&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;&nbsp;
&lt;p&gt;&nbsp;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 683px;  height: auto; max-width: 100%;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; data-phocus-index=&quot;2&quot; filemime=&quot;image/jpeg&quot; filename=&quot;2.jpg&quot; height=&quot;534&quot; src=&quot;./files/attach/images/17429/044/106/84c1f042c815c30fc1b5b6c2891b54ef.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F1452E2434D319C5B27&quot; style=&quot;height: auto;&quot; width=&quot;683&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;br /&gt;
(위치나 모양은 좀 엉성하지만) 이제 나름의 스케쥴 설정 화면이 완성되었을 겁니다(완성된 스크립트는 각자 알맞게 만들어 보세요). 스탯창과 함께 이 화면을 게임에서 띄우면 되겠군요. 지난번에 적었던 기초 스크립트에 schedule_set 라벨이 있었는데, 그 라벨 안에 적절히 호출하면 되겠습니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy&quot; style=&quot;width: 549px; height: 270px;&quot;&gt;init python:
    stress = mental = judge = react = 0
    hp = 20
    day = 1
    morning = free = afternoon = &#39;휴식&#39;

label start:
     
label scredule_set:
     show screen stat
     call screen planner
#.....
&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
스탯창은 그냥 화면상에 표시해야하는 거니 show screen 으로, 스케쥴 화면은 인터렉션이 필요하므로 call screen 으로 띄웁시다. show screen의 경우는 나중에 hide screen 으로 해당 스크린을 숨길 수 있습니다.출처: &lt;a href=&quot;https://askance.tistory.com/43&quot;&gt;https://askance.tistory.com/43&lt;/a&gt; [백안시의 공방 - 소설형 게임 제작실:티스토리]&lt;/p&gt;
&lt;/p&gt;

&lt;p&gt;출처: &lt;a href=&quot;https://askance.tistory.com/43&quot;&gt;https://askance.tistory.com/43&lt;/a&gt; [백안시의 공방 - 소설형 게임 제작실:티스토리]&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Mon, 17 Feb 2025 00:53:05 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[ren&amp;apos;py] 렌파이로 육성 시뮬레이션 게임 만들기 (1) 기초 스크립트 작성]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/106037</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/106037</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/106037#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[ren&#39;py] 렌파이로 육성 시뮬레이션 게임 만들기 (1) 기초 스크립트 작성&nbsp;&lt;/h1&gt;

&lt;pre data-ke-type=&quot;codeblock&quot;&gt;
&nbsp;&lt;/pre&gt;

&lt;h2 class=&quot;toc&quot;&gt;준비물&lt;/h2&gt;

&lt;p&gt;- 렌파이&lt;br /&gt;
- DSE (&lt;a href=&quot;http://www.renpy.org/wiki/renpy/Frameworks&quot; target=&quot;_blank&quot; title=&quot;[http://www.renpy.org/wiki/renpy/Frameworks]로 이동합니다.&quot;&gt;여기&lt;/a&gt;서 다운로드 가능)&lt;/p&gt;

&lt;div style=&quot;margin-left: 4em;&quot;&gt;
&lt;p&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block;   height: auto; max-width: 100%;&quot;&gt;&lt;a href=&quot;https://t1.daumcdn.net/cfile/tistory/253BF33D5395B45223&quot;&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;&quot; src=&quot;./files/attach/images/17429/037/106/f13f6f13ac327c2edfb4bfcc6f9f79dd.gif&quot; style=&quot;vertical-align: middle;&quot; /&gt;dse2-20080829.zip&lt;/a&gt; &lt;/span&gt;&lt;a data-file-srl=&quot;106038&quot; href=&quot;https://www.stechstar.com/user/zbxe/?module=file&amp;act=procFileDownload&amp;file_srl=106038&amp;sid=154dcf3af3406940ee0e39622e6bd503&amp;module_srl=17429&quot;&gt;dse2-20080829.zip&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(혹시라도 자료를 구할 수 없을 경우를 대비해 이곳에도 업로드합니다.)&lt;/p&gt;
필요한 파일은 event_dispatcher.rpy / events.rpy 뿐입니다. 그것만 프로젝트/game 폴더 안에 넣으세요. events.rpy 파일은 예제가 들어있는 파일이니 확인 한 번 하면 나중에 지워도 됩니다.&lt;br /&gt;
&nbsp;&lt;/div&gt;

&lt;div&gt;- 게임에 쓸 그림&lt;/div&gt;

&lt;div style=&quot;margin-left: 4em;&quot;&gt;원하시는 분에 한해서. 전 귀찮아서 글로만 작성하렵니다&lt;/div&gt;

&lt;div&gt;- 지식&lt;/div&gt;

&lt;div style=&quot;margin-left: 4em;&quot;&gt;블로그 우측의 비주얼노벨-텍스트어드벤처 카테고리 글 전부 / 모양내기 - Character의 이용, 대사꾸미기 / 고급 기능 카테고리의 스크린 언어 글 전부에 관해서는 반드시 알아야 합니다.&lt;/div&gt;

&lt;div&gt;&lt;br /&gt;
&lt;h2 class=&quot;toc&quot;&gt;예제 게임 기초 설정&lt;/h2&gt;

&lt;div class=&quot;txc-textbox&quot; style=&quot;border: 1px solid rgb(203, 203, 203); background-color: rgb(255, 255, 255); padding: 10px;&quot;&gt;제목: 프로게이머 키우기&lt;br /&gt;
게임 목적: 1주일 동안 빡세게 연습해서 스타크래프트 메이저 대회 결승전에서 우승하기!&lt;br /&gt;
게임 방식: 프린세스 메이커와 비슷한 방식. 스케쥴은 하루 단위로 짠다.&lt;/div&gt;
&lt;br /&gt;
재미로 편하게 설정한 것들이니 위의 내용이 안 내키시면 다른 거로 바꾸셔도 됩니다.&lt;br /&gt;
오타쿠 키우기라던가.. 뭐 어차피 강의에서 중요한 건 DSE 에 대한 설명이랑 스크립트 구조 정도니까여.&lt;br /&gt;
&lt;br /&gt;
&nbsp;
&lt;h2 class=&quot;toc&quot;&gt;세부사항 정하기&lt;/h2&gt;
그럼, 아래는 게임에 대한 세부(라고 부르기는 약간 창피한..) 설정입니다.&lt;br /&gt;
강의는 아래에 적힌 내용에 따라서 작성되니 쭉 한번 훑어보세요.&lt;br /&gt;
&lt;br /&gt;
&lt;button class=&quot;btn_more&quot; data-id=&quot;42_0&quot; id=&quot;more42_0&quot; style=&quot;display: none;&quot; type=&quot;button&quot;&gt;더보기&lt;/button&gt;

&lt;div class=&quot;moreless_content&quot; id=&quot;content42_0&quot;&gt;&lt;button class=&quot;btn_less&quot; data-id=&quot;42_0&quot; id=&quot;less42_0&quot; type=&quot;button&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;접기&lt;/span&gt;&lt;/button&gt;

&lt;p class=&quot;txt_view&quot;&gt;- 게임 진행 기간&lt;br /&gt;
7일&lt;br /&gt;
(토요일부터 시작, 그 다음 주 토요일이 결승전-엔딩 분기)&lt;br /&gt;
(토, 일, 월, 화, 수, 목, 금 )&lt;br /&gt;
&lt;br /&gt;
- 스케쥴&lt;br /&gt;
종류: 휴식. 연습. 전략 구상. 마인드 컨트롤.&lt;br /&gt;
기간: 오전 연습시간,&nbsp; 자유시간, 오후 연습시간&lt;br /&gt;
&lt;br /&gt;
휴식: 스트레스 4 감소, 정신력 1 증가,&lt;br /&gt;
연습: 상황 판단력 1 증가, 반응 속도 3 증가, 스트레스 3 증가.&lt;br /&gt;
전략 구상: 상황 판단력 2 증가, 정신력 1 증가, 스트레스 2 증가&lt;br /&gt;
마인드 컨트롤: 정신력 2 증가,&lt;br /&gt;
&lt;br /&gt;
- 스탯&lt;br /&gt;
스트레스 - 일정 수치 이상이 되면 병 상태가 된다.&lt;br /&gt;
정신력 - 말 그대로. 불굴의 의지, 기.&lt;br /&gt;
상황판단력 - 수치가 높을 수록 상황판단이 정확하다&lt;br /&gt;
민첩성 - 수치가 높을 수록 판단을 수행하는 속도가 증가한다&lt;br /&gt;
체력 - 값은 20으로 고정&lt;br /&gt;
&lt;br /&gt;
* 체력 제외한 모든 스탯의 초기값은 0&lt;br /&gt;
* 스트레스가 (체력 + (정신력/2)) / 2 보다 크면 다음 날 병 상태 판정. 하루는 무조건 휴식.&lt;br /&gt;
* 스탯 옆에 적힌 부연 설명에 따라 특정 스탯의 수치가 높을 경우 엔딩 대사에 변화를 준다.&lt;br /&gt;
&lt;br /&gt;
- 엔딩&lt;br /&gt;
* 우승 / 준우승&lt;br /&gt;
* 상황 판단력과 민첩성, 정신력 스탯이 10 이상이고 (정신력 + 상황판단력 + 민첩성) - 스트레스가 25 보다 크면 우승.&lt;br /&gt;
* 만일 병 상태로 결승전에 출전하면 무조건 준우승 엔딩.&lt;br /&gt;
* 플레이어 이름이 홍진호라면 준우승 엔딩밖에 못 본다.&lt;br /&gt;
&lt;br /&gt;
- 기타&lt;br /&gt;
* 연습용 예제게임이다보니 필요한 스탯은 최소화했습니다.&lt;br /&gt;
* 스탯에 관한 모든 임시로 정한 것으로 추후 변동해야할듯요.&lt;/p&gt;
&lt;button class=&quot;btn_less&quot; data-id=&quot;42_0&quot; id=&quot;less42_0&quot; type=&quot;button&quot;&gt;&lt;span class=&quot;txt_fold&quot;&gt;접기&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
그러니까 이 게임은 하루에 3 개의 스케쥴을 실행하며, 이것이 일곱 번 반복되는 동안 얻은 스탯에 따라서 엔딩이 갈라지게 됩니다. 게임 흐름을 알아보기 쉽게 그려보면 다음과 같습니다.&lt;br /&gt;
&nbsp;
&lt;p style=&quot;text-align: center;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 298px;  height: auto; max-width: 100%;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; data-phocus-index=&quot;0&quot; filemime=&quot;image/jpeg&quot; filename=&quot;tnstjeh.jpg&quot; height=&quot;1177&quot; src=&quot;./files/attach/images/17429/037/106/f7358004fae0ff174c09d033a9d4502c.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F1116BD424D2EAF421B&quot; style=&quot;height: auto;&quot; width=&quot;298&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;br /&gt;
많은 부분이 생략되긴 했지만 게임 진행은 대략 이런 식으로 됩니다. 이 순서도에 따라 스크립트를 작성해봅시다. 첨부터 완벽하게 쓰려고 하지 마시고 그냥 생각을 정리하는 차원에서 적어보기로 합니다.&lt;br /&gt;
&nbsp;
&lt;h2 class=&quot;toc&quot;&gt;스크립트 대충 적기&lt;/h2&gt;
게임에서 쓰일 변수로는 우선 스탯에 관한 것들이 있을 겁니다. 적당한 영문명으로 알아보기 쉽게 적어줍시다.&lt;br /&gt;
&lt;br /&gt;
init python:&lt;br /&gt;
&nbsp;&nbsp;&nbsp; stress = mental = judge = react = 0&lt;br /&gt;
&nbsp;&nbsp;&nbsp; hp = 20&lt;br /&gt;
&lt;br /&gt;
그리고 게임 시작 버튼을 누르면 실행될 스타트 라벨을 적어놓습니다.&lt;br /&gt;
&lt;br /&gt;
label start:&lt;br /&gt;
&lt;br /&gt;
그 다음은 플레이어가 스케쥴을 설정할 때 실행될 라벨을 적습니다.&lt;br /&gt;
&lt;br /&gt;
label schedule_set:&lt;br /&gt;
&lt;br /&gt;
이제 schedule_set 라벨에서 설정한 스케쥴이 실행될 라벨을 적습니다. 하루 중 오전/자유/오후 시간에 각각 스케쥴을 설정했으니 이를 실행할 라벨도 각기 따로 만들어줍시다.&lt;br /&gt;
&lt;br /&gt;
label morning:&lt;br /&gt;
label free:&lt;br /&gt;
label afternoon:&lt;br /&gt;
&lt;br /&gt;
오후 스케쥴까지 실행했으면 7일이 모두 지났는지 확인해야하며, 7일이 경과했다면 엔딩으로, 아니라면 다시 스케쥴 설정 화면으로 돌아가야 합니다. if 문으로 간단하게 처리합시다.&lt;br /&gt;
&lt;br /&gt;
if day == 7:&lt;br /&gt;
&nbsp;&nbsp;&nbsp; jump ending&lt;br /&gt;
else:&lt;br /&gt;
&nbsp;&nbsp;&nbsp; jump schedule_set&lt;br /&gt;
&lt;br /&gt;
이렇게 적고 보니 init 블록에 day 변수도 넣어야 할 것 같네요. 초기값은 첫째날을 뜻하는 1로 적어줍니다.&lt;br /&gt;
&lt;br /&gt;
day = 1&lt;br /&gt;
&lt;br /&gt;
다음은 if 문에서 썼던 ending 라벨을 적도록 합시다. 이 라벨에서는 조건에 따라 엔딩이 굿/배드로 갈려야 합니다. 이것도 if문으로 해결해줍시다.&lt;br /&gt;
&lt;br /&gt;
label ending:&lt;br /&gt;
&nbsp;&nbsp;&nbsp; if 굳엔딩 조건 == True :&lt;br /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 굳 엔딩 내용&lt;br /&gt;
&nbsp;&nbsp;&nbsp; else:&lt;br /&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # 배드 엔딩 내용&lt;br /&gt;
&lt;br /&gt;
예제 게임은 내용이 짧아서 그냥 ending 라벨에 모든 엔딩을 적습니다만, 엔딩에서 표시할 내용이 길다면 여기서도 각각 다른 라벨에 적어주는게 좋을 겁니다.&lt;br /&gt;
&lt;br /&gt;
여기까지 적었으면 스크립트가 다음과 같은 식으로 적혀있을 겁니다.&lt;br /&gt;
&lt;br /&gt;
&lt;textarea class=&quot;brush:rpy; toolbar: true&quot;&gt;init python:
    stress = mental = judge = react = 0
    hp = 20
    day = 1

label start:
    
label scredule_set:
    
label morning:
label free:
label afternoon:

    if day == 7:
        jump ending
    else:
        jump schedule_set
    
label ending:
    if 굳엔딩 조건 == True:
        # 굳 엔딩 내용
    else:
        # 배드 엔딩 내용
&lt;/textarea&gt;&lt;br /&gt;
&lt;br /&gt;
약소하게나마 적힌 스크립트를 보니 벌써 반은 완성된 기분이네요! 물론 기분만 그런 거고 실제론 실행조차 안 됩니다. 다음 글에선 dse &amp; 스크린 언어를 통해 게임을 좀 더 완성에 가깝게 만들어보도록 하겠습니다.&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;출처: &lt;a href=&quot;https://askance.tistory.com/42&quot;&gt;https://askance.tistory.com/42&lt;/a&gt; [백안시의 공방 - 소설형 게임 제작실:티스토리]&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Mon, 17 Feb 2025 00:48:14 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Dart와 Flutter를 ChatGPT에게 배우다.]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105926</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105926</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105926#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Dart와 Flutter를 ChatGPT에게 배우다.&lt;/h1&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/926/105/75137100456f2050208a82e89c52db0c.png&quot; alt=&quot;2025-02-03-02 Dart와 Flutter를 ChatGPT에게 배우다..png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/926/105/f0979fba5f413bbd154ea733bfea9b9d.png&quot; alt=&quot;2025-02-03-01 Dart와 Flutter를 ChatGPT에게 배우다.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;11&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 설치 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;162&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flutter 개발을 위해서 Visual Studio Code를 사용하려면 다음과 같은 단계를 수행하면 됩니다:&lt;/p&gt;

&lt;ol class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;478&quot; data-ke-list-type=&quot;disc&quot; style=&quot;margin: 0px auto 32px; padding: 0px 0px 0px 10px; list-style: disc; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; font-size: 18px; background-color: rgb(255, 255, 255);&quot;&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;479&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;Flutter SDK 설치: Flutter SDK를 설치하여 개발 환경을 구축합니다.&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;480&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;Visual Studio Code 확장 플러그인 설치: Visual Studio Code에서 Flutter 개발을 위해서 필요한 확장 플러그인을 설치합니다. (Flutter, Dart 확장 플러그인)&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;481&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;프로젝트 생성: Visual Studio Code에서 새 프로젝트를 생성하고, Flutter 구조를 유지하며 개발을 시작합니다.&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;482&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;코딩 및 디버깅: Visual Studio Code에서 Flutter 앱을 개발하고, 디버깅 도구를 사용하여 코드를 검증합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;163&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;164&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;macOS에서 Flutter SDK 설치하는 방법은 다음과 같습니다:&lt;/p&gt;

&lt;ol class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;483&quot; data-ke-list-type=&quot;disc&quot; style=&quot;margin: 0px auto 32px; padding: 0px 0px 0px 10px; list-style: disc; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; font-size: 18px; background-color: rgb(255, 255, 255);&quot;&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;484&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;Flutter 공식 웹사이트에서 Flutter SDK 다운로드:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;724&quot; href=&quot;https://flutter.dev/docs/get-started/install/macos&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://flutter.dev/docs/get-started/install/macos&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;485&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;다운로드한 파일을 압축 해제: 다운로드한 .zip 파일을 압축 해제합니다.&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;486&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;Terminal에서 Flutter 디렉토리로 이동: Terminal에서 Flutter SDK 디렉토리로 이동합니다.&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;487&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;Flutter SDK 경로 추가: 터미널에서 export PATH=&quot;$PATH:[Flutter SDK 경로]/flutter/bin&quot; 명령어를 입력하여 Flutter SDK 경로를 PATH에 추가합니다.&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;488&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: decimal;&quot;&gt;Flutter CLI 설치 확인: 터미널에서 flutter doctor 명령어를 입력하여 Flutter CLI 설치 상태를 확인합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;165&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;이제 Visual Studio Code를 사용하여 Flutter 개발을 시작할 수 있습니다!&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;166&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;167&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;12&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 변수 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;168&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Dart에서&nbsp;변수를&nbsp;사용하는&nbsp;방법에&nbsp;대한&nbsp;예제는&nbsp;다음과&nbsp;같습니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;77&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675552616171&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;489&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1120&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1077&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;main&lt;/span&gt;()&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;870&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 변수 선언&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;899&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; name = &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;988&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;John Doe&#39;&lt;/span&gt;;
  int age = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;989&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;30&lt;/span&gt;;
  double height = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;990&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;5.9&lt;/span&gt;;
  bool isMarried = &lt;span class=&quot;hljs-literal js-evernote-checked&quot; data-evernote-id=&quot;1118&quot; style=&quot;color: rgb(120, 169, 96);&quot;&gt;true&lt;/span&gt;;

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;871&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 변수 값 출력&lt;/span&gt;
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;991&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Name: $name&#39;&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;992&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Age: $age&#39;&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;993&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Height: $height&#39;&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;994&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Married: $isMarried&#39;&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;169&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위&nbsp;예제에서&nbsp;var&nbsp;키워드를&nbsp;사용하여&nbsp;변수를&nbsp;선언할&nbsp;수&nbsp;있습니다.&nbsp;var&nbsp;키워드를&nbsp;사용하면&nbsp;Dart&nbsp;컴파일러가&nbsp;변수의&nbsp;타입을&nbsp;자동으로&nbsp;결정합니다.&nbsp;또한&nbsp;타입을&nbsp;명시적으로&nbsp;지정하여&nbsp;변수를&nbsp;선언할&nbsp;수도&nbsp;있습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;170&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;78&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675552658037&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;490&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1121&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1078&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;main&lt;/span&gt;()&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;872&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 변수 선언&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1122&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;String&lt;/span&gt; name = &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;995&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;John Doe&#39;&lt;/span&gt;;
  int age = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;996&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;30&lt;/span&gt;;
  double height = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;997&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;5.9&lt;/span&gt;;
  bool isMarried = &lt;span class=&quot;hljs-literal js-evernote-checked&quot; data-evernote-id=&quot;1119&quot; style=&quot;color: rgb(120, 169, 96);&quot;&gt;true&lt;/span&gt;;

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;873&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 변수 값 출력&lt;/span&gt;
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;998&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Name: $name&#39;&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;999&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Age: $age&#39;&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1000&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Height: $height&#39;&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1001&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Married: $isMarried&#39;&lt;/span&gt;);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;171&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위&nbsp;예제에서는&nbsp;타입을&nbsp;명시적으로&nbsp;지정하여&nbsp;변수를&nbsp;선언하였습니다.&nbsp;이처럼&nbsp;변수를&nbsp;선언하면&nbsp;Dart&nbsp;컴파일러가&nbsp;값이&nbsp;해당&nbsp;타입으로&nbsp;결정되어야&nbsp;함을&nbsp;강제하게&nbsp;됩니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;172&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;13&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 조건문/반복문 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;173&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Dart에서&nbsp;조건문과&nbsp;반복문을&nbsp;사용하는&nbsp;방법에&nbsp;대한&nbsp;예제는&nbsp;다음과&nbsp;같습니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;79&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675552741469&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;491&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1123&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1079&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;main&lt;/span&gt;()&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;874&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 조건문&lt;/span&gt;
  int score = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1002&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;80&lt;/span&gt;;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;900&quot; style=&quot;font-weight: 700;&quot;&gt;if&lt;/span&gt; (score &gt;= &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1003&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;90&lt;/span&gt;) {
    print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1004&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;A&#39;&lt;/span&gt;);
  } &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;901&quot; style=&quot;font-weight: 700;&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;902&quot; style=&quot;font-weight: 700;&quot;&gt;if&lt;/span&gt; (score &gt;= &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1005&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;80&lt;/span&gt;) {
    print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1006&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;B&#39;&lt;/span&gt;);
  } &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;903&quot; style=&quot;font-weight: 700;&quot;&gt;else&lt;/span&gt; {
    print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1007&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;C&#39;&lt;/span&gt;);
  }

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;875&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 반복문&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;904&quot; style=&quot;font-weight: 700;&quot;&gt;for&lt;/span&gt; (int i = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1008&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0&lt;/span&gt;; i &lt; &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1009&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;5&lt;/span&gt;; i++) {
    print(i);
  }

  int j = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1010&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0&lt;/span&gt;;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;905&quot; style=&quot;font-weight: 700;&quot;&gt;while&lt;/span&gt; (j &lt; &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1011&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;5&lt;/span&gt;) {
    print(j);
    j++;
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;174&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위&nbsp;예제에서는&nbsp;if&nbsp;문,&nbsp;for&nbsp;문,&nbsp;while&nbsp;문을&nbsp;사용하여&nbsp;조건문과&nbsp;반복문을&nbsp;구현하였습니다.&lt;br /&gt;
&lt;br /&gt;
if&nbsp;문에서는&nbsp;주어진&nbsp;조건에&nbsp;따라&nbsp;다른&nbsp;코드&nbsp;블록이&nbsp;실행됩니다.&nbsp;for&nbsp;문에서는&nbsp;주어진&nbsp;조건에&nbsp;따라&nbsp;반복적으로&nbsp;코드&nbsp;블록이&nbsp;실행됩니다.&nbsp;while&nbsp;문에서는&nbsp;주어진&nbsp;조건이&nbsp;참인&nbsp;경우&nbsp;반복적으로&nbsp;코드&nbsp;블록이&nbsp;실행됩니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;175&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;176&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;14&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 함수 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;177&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Dart에서&nbsp;함수를&nbsp;정의하고&nbsp;호출하는&nbsp;방법에&nbsp;대한&nbsp;예제는&nbsp;다음과&nbsp;같습니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;80&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675552834271&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;492&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1124&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1080&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;main&lt;/span&gt;()&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;876&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 함수 정의&lt;/span&gt;
  int &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1081&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;add&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;int a, int b&lt;/span&gt;)&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;906&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; a + b;
  }

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;877&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 함수 호출&lt;/span&gt;
  int result = add(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1012&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1013&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;4&lt;/span&gt;);
  print(result);

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;878&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 다른 함수에 함수를 넘기는 것&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1125&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1082&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;printResult&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1126&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;Function&lt;/span&gt; func&lt;/span&gt;)&lt;/span&gt; {
    print(func(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1014&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1015&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;4&lt;/span&gt;));
  }

  printResult(add);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;178&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위&nbsp;예제에서는&nbsp;add&nbsp;함수를&nbsp;정의하고,&nbsp;함수를&nbsp;호출하여&nbsp;결과를&nbsp;출력하였습니다.&nbsp;또한&nbsp;printResult&nbsp;함수에&nbsp;add&nbsp;함수를&nbsp;넘겨서&nbsp;호출하여&nbsp;결과를&nbsp;출력하였습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;179&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;180&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;15&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 클래스/인터페이스 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;181&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Dart에서 클래스와 인터페이스의 정의 및 사용에 대한 예제는 다음과 같습니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;81&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675552915274&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;493&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;879&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 인터페이스 정의&lt;/span&gt;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;907&quot; style=&quot;font-weight: 700;&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;908&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1083&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Shape&lt;/span&gt; &lt;/span&gt;{
  double getArea();
}

&lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;880&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 클래스 정의&lt;/span&gt;
&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;909&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1084&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Circle&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1085&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1086&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Shape&lt;/span&gt; &lt;/span&gt;{
  double radius;

  Circle(&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1127&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;this&lt;/span&gt;.radius);

  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1145&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  double &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1087&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;getArea&lt;/span&gt;()&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;910&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1016&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;3.14&lt;/span&gt; * radius * radius;
  }
}

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;911&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1088&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Rectangle&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1089&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1090&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Shape&lt;/span&gt; &lt;/span&gt;{
  double width;
  double height;

  Rectangle(&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1128&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;this&lt;/span&gt;.width, &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1129&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;this&lt;/span&gt;.height);

  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1146&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  double &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1091&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;getArea&lt;/span&gt;()&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;912&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; width * height;
  }
}

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1130&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1092&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;main&lt;/span&gt;()&lt;/span&gt; {
  Shape circle = Circle(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1017&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;5&lt;/span&gt;);
  Shape rectangle = Rectangle(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1018&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;5&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1019&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;7&lt;/span&gt;);

  print(circle.getArea());
  print(rectangle.getArea());
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;182&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위 예제에서는 Shape 인터페이스를 정의하고, Circle과 Rectangle 클래스를 정의하였습니다. Circle과 Rectangle 클래스는 Shape 인터페이스를 구현(implement)하고 있습니다. getArea 메서드는 Shape 인터페이스에 정의된 추상 메서드를 구현하였습니다. main 함수에서는 Circle과 Rectangle 객체를 생성하고 getArea 메서드를 호출하여 결과를 출력하였습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;183&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;184&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;16&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 네트워킹 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;185&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flutter에서 네트워크 통신을 하는 예제는 다음과 같습니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;82&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675553092870&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;494&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;913&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1020&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;dart:convert&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;914&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1021&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flutter/material.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;915&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1022&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:http/http.dart&#39;&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;916&quot; style=&quot;font-weight: 700;&quot;&gt;as&lt;/span&gt; http;

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1131&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() =&gt; runApp(MyApp());

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;917&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1093&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;MyApp&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;918&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1094&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;StatelessWidget&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1147&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  Wid&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;919&quot; style=&quot;font-weight: 700;&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1095&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;build&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BuildContext context&lt;/span&gt;) {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;920&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; MaterialApp(
      title: &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1023&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Flutter Network Example&#39;&lt;/span&gt;,
      &lt;span class=&quot;hljs-attr&quot;&gt;home&lt;/span&gt;: Scaffold(
        appBar: AppBar(
          title: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1024&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Flutter Network Example&#39;&lt;/span&gt;),
        ),
        &lt;span class=&quot;hljs-attr&quot;&gt;body&lt;/span&gt;: Center(
          child: FutureBuilder(
            future: fetchData(),
            &lt;span class=&quot;hljs-attr&quot;&gt;builder&lt;/span&gt;: (context, snapshot) {
              &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;921&quot; style=&quot;font-weight: 700;&quot;&gt;if&lt;/span&gt; (snapshot.hasData) {
                &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;922&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; Text(snapshot.data);
              } &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;923&quot; style=&quot;font-weight: 700;&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;924&quot; style=&quot;font-weight: 700;&quot;&gt;if&lt;/span&gt; (snapshot.hasError) {
                &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;925&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1025&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&quot;${snapshot.error}&quot;&lt;/span&gt;);
              }
              &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;926&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

Future&lt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1132&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;String&lt;/span&gt;&gt; fetchData() &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;927&quot; style=&quot;font-weight: 700;&quot;&gt;async&lt;/span&gt; {
  final response =
      &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;928&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; http.get(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1026&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;https://jsonplaceholder.typicode.com/posts/1&#39;&lt;/span&gt;);

  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;929&quot; style=&quot;font-weight: 700;&quot;&gt;if&lt;/span&gt; (response.statusCode == &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1027&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;200&lt;/span&gt;) {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;930&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; json.decode(response.body)[&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1028&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;title&#39;&lt;/span&gt;];
  } &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;931&quot; style=&quot;font-weight: 700;&quot;&gt;else&lt;/span&gt; {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;932&quot; style=&quot;font-weight: 700;&quot;&gt;throw&lt;/span&gt; Exception(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1029&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Failed to load data&#39;&lt;/span&gt;);
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;186&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위&nbsp;예제에서는&nbsp;Flutter의&nbsp;http&nbsp;패키지를&nbsp;사용하여&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;725&quot; href=&quot;https://jsonplaceholder.typicode.com/posts/1&quot; rel=&quot;noopener&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;https://jsonplaceholder.typicode.com/posts/1&lt;/a&gt;&nbsp;URL로부터 JSON 데이터를 가져오고 있습니다. 이 데이터는 json.decode 함수를 사용하여 파싱하고, title 프로퍼티의 값을 화면에 출력하고 있습니다. FutureBuilder 위젯은 비동기 네트워크 요청의 결과를 기다리는 동안 CircularProgressIndicator 위젯을 표시하고, 요청이 완료되면 결과를 화면에 출력하고 있습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;187&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;188&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;17&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 소켓통신 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;189&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Dart에서 소켓 통신을 구현하는 방법은 다양합니다. 다음은 Dart에서 소켓 통신을 구현하는 단순한 예제입니다:&lt;/p&gt;

&lt;div class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;495&quot; style=&quot;margin: 0px; padding: 0px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; font-size: 18px; background-color: rgb(255, 255, 255);&quot;&gt;
&lt;div class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;496&quot; style=&quot;margin: 0px; padding: 0px;&quot;&gt;
&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;83&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675553337206&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;497&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;933&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1030&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;dart:io&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1133&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;934&quot; style=&quot;font-weight: 700;&quot;&gt;async&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;881&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Create a server socket&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;935&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; server = &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;936&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; ServerSocket.bind(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1031&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;localhost&#39;&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1032&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;4040&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1033&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Listening for connections...&#39;&lt;/span&gt;);

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;882&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Listen for incoming connections&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;937&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;938&quot; style=&quot;font-weight: 700;&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;939&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; socket &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;940&quot; style=&quot;font-weight: 700;&quot;&gt;in&lt;/span&gt; server) {
    print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1034&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Received connection from ${socket.remoteAddress.address}:${socket.remotePort}&#39;&lt;/span&gt;);

    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;883&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Send data to the socket&lt;/span&gt;
    socket.write(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1035&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Hello, client!&#39;&lt;/span&gt;);

    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;884&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Wait for data from the socket&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;941&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; data = &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;942&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; socket.transform(utf8.decoder).join();
    print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1036&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Received: $data&#39;&lt;/span&gt;);

    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;885&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Close the socket&lt;/span&gt;
    socket.close();
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;190&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;191&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;그리고&nbsp;다음은&nbsp;클라이언트&nbsp;코드입니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;84&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675553355972&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;498&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;943&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1037&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;dart:io&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1134&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;944&quot; style=&quot;font-weight: 700;&quot;&gt;async&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;886&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Connect to the server socket&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;945&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; socket = &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;946&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; Socket.connect(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1038&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;localhost&#39;&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1039&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;4040&lt;/span&gt;);
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1040&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Connected to the server: ${socket.remoteAddress.address}:${socket.remotePort}&#39;&lt;/span&gt;);

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;887&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Send data to the socket&lt;/span&gt;
  socket.write(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1041&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Hello, server!&#39;&lt;/span&gt;);

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;888&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Wait for data from the socket&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;947&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; data = &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;948&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; socket.transform(utf8.decoder).join();
  print(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1042&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Received: $data&#39;&lt;/span&gt;);

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;889&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Close the socket&lt;/span&gt;
  socket.close();
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;192&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위의&nbsp;예제에서는&nbsp;소켓&nbsp;통신에&nbsp;필요한&nbsp;dart:io&nbsp;라이브러리를&nbsp;가져오고,&nbsp;단일&nbsp;연결을&nbsp;구현하였습니다.&nbsp;이&nbsp;예제는&nbsp;소켓&nbsp;통신의&nbsp;개념을&nbsp;이해하는데&nbsp;도움이&nbsp;되며,&nbsp;실제&nbsp;애플리케이션에서&nbsp;소켓&nbsp;통신을&nbsp;사용할&nbsp;때는&nbsp;더&nbsp;복잡한&nbsp;로직이&nbsp;필요할&nbsp;수&nbsp;있습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;193&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;194&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;195&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;18&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 탭 메뉴 예제 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;196&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flutter에서&nbsp;탭&nbsp;메뉴를&nbsp;구현하는&nbsp;방법에는&nbsp;다양한&nbsp;방법이&nbsp;있지만,&nbsp;다음은&nbsp;Flutter의&nbsp;Scaffold&nbsp;위젯을&nbsp;이용하여&nbsp;탭&nbsp;메뉴를&nbsp;구현하는&nbsp;예제입니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;85&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675553581069&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;499&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;949&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1043&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flutter/material.dart&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1135&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() =&gt; runApp(MyApp());

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;950&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1096&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;MyApp&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;951&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1097&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;StatelessWidget&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1148&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  Wid&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;952&quot; style=&quot;font-weight: 700;&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1098&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;build&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BuildContext context&lt;/span&gt;) {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;953&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; MaterialApp(
      home: MyHomePage(),
    );
  }
}

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;954&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1099&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;MyHomePage&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;955&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1100&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;StatefulWidget&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1149&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  _MyHomePageState createState() =&gt; _MyHomePageState();
}

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;956&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1101&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;_MyHomePageState&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;957&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1102&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;State&lt;/span&gt;&lt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1103&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;MyHomePage&lt;/span&gt;&gt; &lt;/span&gt;{
  int _selectedIndex = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1044&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0&lt;/span&gt;;
  final List&lt;Widget&gt; _pages = [
      Container(child: Center(child: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1045&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;1&#39;&lt;/span&gt;),),),
      Container(child: Center(child: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1046&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;2&#39;&lt;/span&gt;),),),
      Container(child: Center(child: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1047&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;3&#39;&lt;/span&gt;),),),
  ];

  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1136&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1104&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;_onTabTapped&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;int index&lt;/span&gt;)&lt;/span&gt; {
    setState(() {
      _selectedIndex = index;
    });
  }

  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1150&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  Wid&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;958&quot; style=&quot;font-weight: 700;&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1105&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;build&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BuildContext context&lt;/span&gt;) {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;959&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; Scaffold(
      body: _pages[_selectedIndex],
      &lt;span class=&quot;hljs-attr&quot;&gt;bottomNavigationBar&lt;/span&gt;: BottomNavigationBar(
        currentIndex: _selectedIndex,
        &lt;span class=&quot;hljs-attr&quot;&gt;onTap&lt;/span&gt;: _onTabTapped,
        &lt;span class=&quot;hljs-attr&quot;&gt;items&lt;/span&gt;: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            &lt;span class=&quot;hljs-attr&quot;&gt;title&lt;/span&gt;: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1048&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Home&#39;&lt;/span&gt;),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            &lt;span class=&quot;hljs-attr&quot;&gt;title&lt;/span&gt;: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1049&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Search&#39;&lt;/span&gt;),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            &lt;span class=&quot;hljs-attr&quot;&gt;title&lt;/span&gt;: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1050&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Profile&#39;&lt;/span&gt;),
          ),
        ],
      ),
    );
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;197&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위의&nbsp;예제에서는&nbsp;탭&nbsp;메뉴의&nbsp;인덱스를&nbsp;저장하는&nbsp;_selectedIndex&nbsp;변수와,&nbsp;각&nbsp;탭에&nbsp;대응하는&nbsp;화면을&nbsp;표시할&nbsp;위젯&nbsp;목록&nbsp;_pages&nbsp;를&nbsp;정의하였습니다.&nbsp;그리고&nbsp;_onTabTapped&nbsp;메소드를&nbsp;통해&nbsp;탭을&nbsp;클릭할&nbsp;때마다&nbsp;_selectedIndex&nbsp;변수를&nbsp;변경하여&nbsp;화면을&nbsp;이동하게&nbsp;하였습니다.&lt;br /&gt;
&lt;br /&gt;
BottomNavigationBar&nbsp;위젯에서는&nbsp;현재&nbsp;선택된&nbsp;탭의&nbsp;인덱스를&nbsp;나타내는&nbsp;currentIndex&nbsp;속성,&nbsp;탭을&nbsp;클릭할&nbsp;때&nbsp;호출될&nbsp;콜백&nbsp;메소드&nbsp;onTap&nbsp;속성,&nbsp;각&nbsp;탭에&nbsp;대한&nbsp;정보를&nbsp;담은&nbsp;items&nbsp;속성으로&nbsp;구성되어&nbsp;있습니다.&lt;br /&gt;
&lt;br /&gt;
위와&nbsp;같이&nbsp;구현하여&nbsp;실행하면,&nbsp;탭&nbsp;메뉴를&nbsp;클릭할&nbsp;때마다&nbsp;화면이&nbsp;이동하며,&nbsp;하단에&nbsp;탭&nbsp;메뉴가&nbsp;표시될&nbsp;수&nbsp;있습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;198&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;199&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;200&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;19&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ Flame ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;201&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flame 프레임워크는 게임 개발에 사용되는 프레임워크입니다.&lt;br /&gt;
Flame의&nbsp;기본&nbsp;예제는&nbsp;다음과&nbsp;같습니다:&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;86&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675553892929&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;500&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;960&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1051&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flame/flame.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;961&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1052&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flame/game.dart&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;962&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1106&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;MyGame&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;963&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1107&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Game&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1151&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1137&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1108&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;render&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Canvas canvas&lt;/span&gt;)&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;890&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 게임을 그리는 코드&lt;/span&gt;
  }

  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1152&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1138&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1109&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;update&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;double t&lt;/span&gt;)&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;891&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// 게임을 업데이트하는 코드&lt;/span&gt;
  }
}

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1139&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;964&quot; style=&quot;font-weight: 700;&quot;&gt;async&lt;/span&gt; {
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;965&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; Flame.util.fullScreen();
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;966&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; Flame.util.setOrientation(DeviceOrientation.portraitUp);

  MyGame game = MyGame();
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;967&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; Flame.images.loadAll(&lt;&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1140&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;String&lt;/span&gt;&gt;[
    &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1053&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;images/player.png&#39;&lt;/span&gt;,
    &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1054&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;images/enemy.png&#39;&lt;/span&gt;,
  ]);

  runApp(game.widget);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;202&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위의&nbsp;예제에서&nbsp;MyGame&nbsp;클래스는&nbsp;Game&nbsp;클래스를&nbsp;상속하여&nbsp;정의합니다.&nbsp;render&nbsp;메소드에서는&nbsp;게임을&nbsp;그리는&nbsp;코드,&nbsp;update&nbsp;메소드에서는&nbsp;게임을&nbsp;업데이트하는&nbsp;코드를&nbsp;구현할&nbsp;수&nbsp;있습니다.&lt;br /&gt;
&lt;br /&gt;
main 함수에서는 게임 앱을 전체 화면으로 설정하고, 화면의 방향을 세로방향으로 설정하고, MyGame 객체를 생성하여 실행합니다. 이미지를 로드하는 부분에서는 게임에 사용될 이미지를 로드하고,&nbsp;runApp&nbsp;함수를&nbsp;이용하여&nbsp;게임&nbsp;앱을&nbsp;실행합니다.&lt;br /&gt;
&lt;br /&gt;
위의 예제는 Flutter와 Flame 프레임워크의 기본 구조와 기능에 대한 예제입니다. 실제 게임 개발에서는 이를 활용하여 더 복잡한 게임을 개발할 수 있습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;203&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;204&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;20&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;&lt;br /&gt;
[ Flame &gt; Box2D 물리엔진 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;205&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flame&nbsp;프레임워크에서&nbsp;Box2D&nbsp;물리엔진을&nbsp;사용할&nbsp;수&nbsp;있습니다.&nbsp;다음은&nbsp;Box2D를&nbsp;이용한&nbsp;간단한&nbsp;물리엔진&nbsp;예제입니다.&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;87&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675554066657&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;501&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;968&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1055&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flame/flame.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;969&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1056&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flame/game.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;970&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1057&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flutter/material.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;971&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1058&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:box2d_flame/box2d.dart&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;972&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1110&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;PhysicsGame&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;973&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1111&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;Game&lt;/span&gt; &lt;/span&gt;{
  World world;
  Vector2 gravity;

  &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1112&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;PhysicsGame&lt;/span&gt;()&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;892&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// World 생성&lt;/span&gt;
    gravity = Vector2(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1059&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0.0&lt;/span&gt;, -&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1060&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;9.8&lt;/span&gt;);
    world = World.createWithGravity(gravity);

    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;893&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Body 생성&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;974&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; bodyDef = BodyDef();
    bodyDef.position = Vector2(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1061&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0.0&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1062&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0.0&lt;/span&gt;);
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;975&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; body = world.createBody(bodyDef);

    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;894&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Shape 생성&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;976&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; shape = PolygonShape();
    shape.setAsBoxXY(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1063&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;1.0&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1064&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;1.0&lt;/span&gt;);

    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;895&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Fixture 생성&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;977&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; fixtureDef = FixtureDef();
    fixtureDef.shape = shape;
    fixtureDef.density = &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1065&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;1.0&lt;/span&gt;;
    body.createFixtureFromDef(fixtureDef);
  }

  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1153&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1141&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1113&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;render&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;Canvas canvas&lt;/span&gt;)&lt;/span&gt; {
    &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;896&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Box2D 시뮬레이션&lt;/span&gt;
    world.stepDt(&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1066&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;1&lt;/span&gt; / &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1067&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;60&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1068&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;6&lt;/span&gt;, &lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1069&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;2&lt;/span&gt;);
  }

  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1154&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1142&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1114&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;update&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;double t&lt;/span&gt;)&lt;/span&gt; {}
}

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1143&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;978&quot; style=&quot;font-weight: 700;&quot;&gt;async&lt;/span&gt; {
  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;897&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// Flame 초기화&lt;/span&gt;
  WidgetsFlutterBinding.ensureInitialized();
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;979&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; Flame.util.fullScreen();
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;980&quot; style=&quot;font-weight: 700;&quot;&gt;await&lt;/span&gt; Flame.util.setOrientation(DeviceOrientation.portraitUp);

  &lt;span class=&quot;hljs-comment js-evernote-checked&quot; data-evernote-id=&quot;898&quot; style=&quot;color: rgb(136, 136, 136);&quot;&gt;// PhysicsGame 생성 및 실행&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;981&quot; style=&quot;font-weight: 700;&quot;&gt;var&lt;/span&gt; game = PhysicsGame();
  runApp(game.widget);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;206&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위의 예제에서는 World, Body, Shape, Fixture 등 Box2D의 기본 구성 요소를 생성하여 물리 시뮬레이션을 구현합니다. Box2D 물리엔진의 자세한 사용법은 Box2D 공식 문서를 참조하시면 됩니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;207&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;208&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;209&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;21&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ 3D ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;210&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flutter에서&nbsp;3D&nbsp;파일을&nbsp;보여주려면&nbsp;Flutter&nbsp;플러그인인&nbsp;flutter_3d_obj를&nbsp;사용할&nbsp;수&nbsp;있습니다.&nbsp;다음은&nbsp;flutter_3d_obj&nbsp;플러그인을&nbsp;사용하여&nbsp;.glb&nbsp;파일을&nbsp;보여주는&nbsp;예제입니다.&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;88&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675555282261&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;502&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;982&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1070&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flutter/material.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;983&quot; style=&quot;font-weight: 700;&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1071&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;package:flutter_3d_obj/flutter_3d_obj.dart&#39;&lt;/span&gt;;

&lt;span class=&quot;hljs-built_in js-evernote-checked&quot; data-evernote-id=&quot;1144&quot; style=&quot;color: rgb(57, 115, 0);&quot;&gt;void&lt;/span&gt; main() =&gt; runApp(MyApp());

&lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;984&quot; style=&quot;font-weight: 700;&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1115&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;MyApp&lt;/span&gt; &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;985&quot; style=&quot;font-weight: 700;&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1116&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;StatelessWidget&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;hljs-meta js-evernote-checked&quot; data-evernote-id=&quot;1155&quot; style=&quot;color: rgb(31, 113, 153);&quot;&gt;@override&lt;/span&gt;
  Wid&lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;986&quot; style=&quot;font-weight: 700;&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;hljs-title js-evernote-checked&quot; data-evernote-id=&quot;1117&quot; style=&quot;color: rgb(136, 0, 0); font-weight: 700;&quot;&gt;build&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BuildContext context&lt;/span&gt;) {
    &lt;span class=&quot;hljs-keyword js-evernote-checked&quot; data-evernote-id=&quot;987&quot; style=&quot;font-weight: 700;&quot;&gt;return&lt;/span&gt; MaterialApp(
      title: &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1072&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Flutter 3D Model Example&#39;&lt;/span&gt;,
      &lt;span class=&quot;hljs-attr&quot;&gt;home&lt;/span&gt;: Scaffold(
        appBar: AppBar(
          title: Text(&lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1073&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;Flutter 3D Model Example&#39;&lt;/span&gt;),
        ),
        &lt;span class=&quot;hljs-attr&quot;&gt;body&lt;/span&gt;: Center(
          child: Obj3dViewer(
            objFileAsset: &lt;span class=&quot;hljs-string js-evernote-checked&quot; data-evernote-id=&quot;1074&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;&#39;assets/model.glb&#39;&lt;/span&gt;,
          ),
        ),
      ),
    );
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;211&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위&nbsp;예제에서&nbsp;Obj3dViewer&nbsp;위젯은&nbsp;flutter_3d_obj&nbsp;플러그인에서&nbsp;제공하는&nbsp;위젯으로,&nbsp;.glb&nbsp;파일을&nbsp;보여주기&nbsp;위한&nbsp;뷰어&nbsp;역할을&nbsp;합니다.&nbsp;objFileAsset&nbsp;속성에&nbsp;assets/model.glb&nbsp;파일의&nbsp;경로를&nbsp;지정하여&nbsp;해당&nbsp;파일을&nbsp;로드할&nbsp;수&nbsp;있습니다.&lt;br /&gt;
&lt;br /&gt;
위&nbsp;코드를&nbsp;기반으로&nbsp;개발하기&nbsp;위해서는&nbsp;flutter_3d_obj&nbsp;플러그인을&nbsp;프로젝트에&nbsp;추가해야&nbsp;합니다.&nbsp;pubspec.yaml&nbsp;파일에&nbsp;다음과&nbsp;같이&nbsp;추가할&nbsp;수&nbsp;있습니다.&lt;/p&gt;

&lt;pre class=&quot;typescript js-evernote-checked&quot; data-evernote-id=&quot;89&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; id=&quot;code_1675555325560&quot; style=&quot;overflow: auto; margin: 28px auto; padding: 0px; color: rgb(51, 51, 51); background-color: rgb(246, 247, 248); overflow-wrap: break-word; font-family: Menlo, Consolas, Monaco, monospace; font-size: 16px; line-height: 22px;&quot;&gt;
&lt;code class=&quot;hljs js-evernote-checked&quot; data-evernote-id=&quot;503&quot; style=&quot;margin: 0px; padding: 16px; display: block; overflow-x: auto; background: rgb(240, 240, 240); color: rgb(68, 68, 68); font-family: Menlo, Consolas, Monaco, monospace;&quot;&gt;dependencies:
  flutter:
    sdk: flutter

  &lt;span class=&quot;hljs-attr&quot;&gt;flutter_3d_obj&lt;/span&gt;: ^&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1075&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;0.3&lt;/span&gt;&lt;span class=&quot;hljs-number js-evernote-checked&quot; data-evernote-id=&quot;1076&quot; style=&quot;color: rgb(136, 0, 0);&quot;&gt;.3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;212&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;213&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;214&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;h4 class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;22&quot; data-ke-size=&quot;size20&quot; style=&quot;font-size: 28px; margin: 52px auto 28px; padding: 0px; line-height: 30px; font-weight: normal; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;[ Flutter 커뮤니티 ]&lt;/h4&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;215&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;Flutter 커뮤니티는 Flutter 개발자, 사용자, 애플리케이션 개발자 등 다양한 사용자들이 모여 경험, 지식, 아이디어를 공유하고 도움을 주고 받을 수 있는 공간입니다. 다음은 Flutter 커뮤니티에 참여할 수 있는 몇 가지 장소입니다.&lt;/p&gt;

&lt;ul class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;90&quot; data-ke-list-type=&quot;disc&quot; style=&quot;margin: 0px auto 32px; padding: 0px 0px 0px 10px; list-style-position: initial; list-style-image: initial; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; font-size: 18px; background-color: rgb(255, 255, 255);&quot;&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;91&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: disc;&quot;&gt;Flutter 한국 사용자 그룹:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;726&quot; href=&quot;https://www.facebook.com/groups/flutterkorea&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://www.facebook.com/groups/flutterkorea&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;92&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: disc;&quot;&gt;Flutter 공식 웹사이트:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;727&quot; href=&quot;https://flutter.dev/community&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://flutter.dev/community&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;93&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: disc;&quot;&gt;Flutter 공식 트위터 계정:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;728&quot; href=&quot;https://twitter.com/flutterdev&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://twitter.com/flutterdev&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;94&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: disc;&quot;&gt;Flutter 공식 유튜브 채널:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;729&quot; href=&quot;https://www.youtube.com/c/flutter&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://www.youtube.com/c/flutter&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;95&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: disc;&quot;&gt;Flutter 공식 Discord 채널:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;730&quot; href=&quot;https://discord.gg/flutter&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://discord.gg/flutter&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;96&quot; style=&quot;margin: 0px 0px 10px 24px; padding: 0px; list-style: disc;&quot;&gt;Stack Overflow:&nbsp;&lt;a class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;731&quot; href=&quot;https://stackoverflow.com/questions/tagged/flutter&quot; style=&quot;color: rgb(107, 172, 206); text-decoration-line: none;&quot;&gt;https://stackoverflow.com/questions/tagged/flutter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;216&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;위의 장소들을 통해 Flutter 관련 질문, 토론, 프로젝트 공유, 자유 게시판 등 다양한 내용을 교환하고, Flutter 커뮤니티의 활성적인 구성원으로 참여할 수 있습니다.&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;216&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;[출처]&nbsp;https://banjubu.tistory.com/222&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;216&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p class=&quot;js-evernote-checked&quot; data-evernote-id=&quot;216&quot; data-ke-size=&quot;size16&quot; style=&quot;margin: 0px auto 28px; padding-right: 0px; padding-left: 0px; font-size: 18px; line-height: 32px; color: rgb(51, 51, 51); font-family: &quot;Spoqa Han Sans&quot;, sans-serif; background-color: rgb(255, 255, 255); padding-top: 0px !important; padding-bottom: 0px !important;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Mon, 03 Feb 2025 23:45:23 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter PDF 뷰어를 만드는 방법 : How to build a Flutter PDF viewer]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105767</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105767</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105767#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter PDF 뷰어를 만드는 방법 : How to build a Flutter PDF viewer&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/767/105/4f446254a54a3e428b0a06d47c7e48b2.png&quot; alt=&quot;01.article-header.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;div class=&quot;p1p&quot; style=&quot;box-sizing: border-box; align-items: flex-start; justify-content: space-between; padding: 0px 5rem; visibility: visible;&quot;&gt;
&lt;div class=&quot;prB ptB puB&quot; style=&quot;box-sizing: border-box; align-items: flex-start; align-self: stretch; display: flex; flex-direction: column; gap: 5rem; padding: 2.5rem 0px; container-type: inline-size; margin-left: auto; margin-right: auto; max-width: 79.5rem;&quot;&gt;
&lt;div class=&quot;p6p&quot; style=&quot;box-sizing: border-box; align-items: flex-start; display: flex; width: 1272px;&quot;&gt;
&lt;article class=&quot;p7p&quot; style=&quot;box-sizing: border-box; width: 1272px;&quot;&gt;
&lt;div class=&quot;nut-row nut-justify-center-xs&quot; style=&quot;box-sizing: border-box; display: flex; flex: 0 1 auto; flex-flow: wrap; margin: 0px -0.75rem; row-gap: 1.25rem; justify-content: center;&quot;&gt;
&lt;div class=&quot;nut-col-lg-6 nut-col-md-8 nut-col-sm-10 nut-col-xs-12&quot; style=&quot;box-sizing: border-box; flex: 0 0 50%; max-width: 50%; padding: 0px 0.75rem;&quot;&gt;
&lt;article class=&quot;pvq p1r&quot; style=&quot;box-sizing: border-box; display: flex; flex-direction: column; gap: 1.25rem; max-width: 100%; overflow: visible; width: 624px; color: rgb(26, 20, 20); padding-bottom: 4rem; position: relative;&quot;&gt;
&lt;blockquote class=&quot;p5b p9b&quot; style=&quot;box-sizing: border-box; margin: 0px; border-width: 0px 0px 0px 2px; border-left-style: solid; border-left-color: rgb(226, 219, 217); font-size: 18px; line-height: 22px; padding: 0px 0px 0px 1rem; border-top-style: initial; border-right-style: initial; border-bottom-style: initial; border-top-color: initial; border-right-color: initial; border-bottom-color: initial; border-image: initial; align-items: flex-start; border-radius: 0px; display: flex; flex-direction: row; gap: 1rem;&quot;&gt;
&lt;p class=&quot;pec&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;본 기사는 2022년 3월에 처음 게시되었으며 2024년 9월에 업데이트되었습니다.&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://flutter.dev/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;는 Google에서 개발한 오픈 소스 프레임워크로, Dart의 단일 코드베이스에서 모바일, 웹 및 데스크톱용 네이티브 컴파일 애플리케이션을 만들 수 있습니다. 이 게시물에서는 Flutter에서 단일 페이지 문서를 처리하기 위한 기본 PDF 뷰어를 설정하는 과정을 안내합니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;다양한 오픈 소스 옵션에서 PDF 보기에 적합한 패키지를 선택하는 방법을 알아보는 것으로 시작합니다. 그런 다음 선택한 패키지를 Flutter 프로젝트에 통합하여 기능적인 PDF 뷰어 앱을 만듭니다.&lt;/font&gt;&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;choosing-the-right-pdf-package-for-flutter&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 23px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter에 적합한 PDF 패키지 선택&lt;/font&gt;&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter용 PDF 라이브러리를 선택할 때는 요구 사항을 평가하고 패키지 품질 및 기능과 같은 요소를 고려하는 것이 필수적입니다. 간단한 사용 사례의 경우 오픈 소스 라이브러리를 탐색하는 것이 좋은 시작점입니다. 보다 고급 요구 사항의 경우 Nutrient는 포괄적인 기능을 갖춘 강력한&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/sdk/flutter&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter PDF SDK를&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;제공합니다 .&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;적합한 패키지를 찾으려면&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;pub.dev&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;에서&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/flutter/packages?q=pdf&amp;platform=android+ios&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;검색하면&lt;/font&gt;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;pdf&lt;/code&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;수많은 옵션이 나타납니다. 고려해야 할 주요 요소는 다음과 같습니다.&lt;/font&gt;&lt;/p&gt;

&lt;ul class=&quot;pXc pZc&quot; style=&quot;box-sizing: border-box; margin: 0px; padding-left: 3rem; list-style: none;&quot;&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;Pub 포인트&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;- null 안전성 지원 및 Dart 규칙 준수를 포함하여 정적 분석을 기반으로 한 패키지의 품질을 반영합니다.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;인기&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;- 패키지를 사용하는 개발자의 수를 나타냅니다.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;업데이트 빈도&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;- 최근 업데이트 날짜는 종종 활발하게 유지 관리되는 프로젝트를 의미합니다.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;검증된 게시자&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;- 일부 패키지는 검증된 게시자로부터 제공되므로 신뢰도가 더욱 높아집니다.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;검색 결과 중에서 주목할 만한 패키지는 다음과 같습니다.&lt;/font&gt;&lt;/p&gt;

&lt;ul class=&quot;pXc pZc&quot; style=&quot;box-sizing: border-box; margin: 0px; padding-left: 3rem; list-style: none;&quot;&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/packages/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;/a&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;PDFView&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&mdash; Android와 iOS에서 위젯을&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;제공하는 Flutter 플러그인입니다 .&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/packages/native_pdf_view&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;native_pdf_view&lt;/code&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&mdash; 웹, macOS, Windows, Android, iOS에서 PDF 파일을 렌더링하기 위한 Flutter 플러그인입니다.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/packages/advance_pdf_viewer&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;advance_pdf_viewer&lt;/code&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&mdash; PDF 파일을 처리하기 위한 Flutter 플러그인입니다.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;세 패키지를 빠르게 평가한 결과,&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;간단한 PDF 뷰어를 구현하는 실험의 목표에 가장 적합한 것으로 판명되었습니다.&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;GitHub 저장소 에 예제가 포함되어 있으며, 구성 단계는 따르기 쉽고, 후드 아래에는&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pdfium.googlesource.com/pdfium/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;PDFium&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;이라는 Google 라이브러리가 기반을 두고 있습니다. Nutrient&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;에서는&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/blog/contributing-to-pdfium/&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;PDFium을 좋아합니다&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;! ❤️&lt;/font&gt;&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;building-a-pdf-viewer-with-flutter_pdfview&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 23px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;flutter_pdfview로 PDF 뷰어 구축&lt;/font&gt;&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Android와 iOS 플랫폼에서 PDF를 렌더링할 수 있는 Flutter 패키지입니다. Flutter 앱 내에서 PDF 파일을 표시하는 매끄러운 방법을 제공하며, 페이지 탐색, 확대/축소 등의 기능을 제공합니다. 사용자 지정 환경을 제공하기 위한 몇 가지&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview#options&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;구성 옵션을&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;노출하며 ,&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;GitHub 저장소&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;에&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview/tree/master/example&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;예제 앱&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;이 포함되어 있습니다 .&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;사용 사례를 간단하게 유지하기 위해, 이 게시물에서는&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://developer.android.com/about/versions/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;API 30&lt;/font&gt;&lt;/a&gt;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;이 있는 Android 기기에서 단일 페이지 PDF 문서를 표시하는 데 사용합니다&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;이 앱의 기본 레이아웃은 렌더링된 PDF 문서를 보여주는 위젯이며, 핀치 투 줌, 확대된 페이지 드래그와 같은 간단한 제스처가 가능합니다.&lt;/font&gt;&lt;/p&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;getting-started&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;시작하기&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;시작하려면 개발 머신에 Flutter가 설치되고 설정되어 있는지 확인하세요. 다음 명령을 실행하여 확인할 수 있습니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;플러터 닥터&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;이 명령은 Flutter로 개발을 시작하는 데 필요한 모든 것이 준비되었는지 확인합니다.&lt;/font&gt;&lt;/p&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-1-creating-a-new-flutter-project&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;1단계 - 새로운 Flutter 프로젝트 생성&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;새로운 Flutter 프로젝트를 만드는 것으로 시작합니다. 터미널을 열고 다음을 실행합니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;플러터 pdf_viewer_app 만들기&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;프로젝트 디렉토리로 이동합니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;cd pdf_viewer_app&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-2-adding-the-flutter_pdfview-dependency&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;2단계 - flutter_pdfview 종속성 추가&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;다음으로, 종속성 아래 파일&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;에 패키지를 추가합니다&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;pubspec.yaml&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 161.969px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 145.969px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;1 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
2 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
3 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
4 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
5 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
6&lt;/font&gt;
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 145.969px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;... &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
종속성: &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  플러터: &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    SDK: 플러터 &lt;/font&gt;&lt;span class=&quot;gi&quot; style=&quot;box-sizing: border-box; background: rgb(3, 58, 22); color: rgb(221, 241, 228);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;+ flutter_pdfview: ^1.2.7
&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ...&lt;/font&gt;&lt;/font&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote class=&quot;p5b p8b&quot; style=&quot;box-sizing: border-box; margin: 0px; border-width: 0px 0px 0px 2px; border-left-style: solid; border-left-color: rgb(226, 219, 217); font-size: 18px; line-height: 22px; padding: 0px 0px 0px 1rem; border-top-style: initial; border-right-style: initial; border-bottom-style: initial; border-top-color: initial; border-right-color: initial; border-bottom-color: initial; border-image: initial; align-items: flex-start; border-radius: 0px; display: flex; flex-direction: row; gap: 1rem;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;정보&quot; class=&quot;p-b&quot; src=&quot;./files/attach/binaries/17429/767/105/e52d3ead6ec3f0ff057a6ff0ff945a9e&quot; style=&quot;box-sizing: border-box; vertical-align: middle; display: inline-block; object-fit: cover; height: 2.5rem; margin-bottom: 0.5rem; width: 2.5rem; background-color: rgb(226, 219, 217); border-radius: 0.5rem; padding: 0.5rem;&quot; /&gt;
&lt;p class=&quot;pec&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(40, 49, 62); overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;공백은 YAML 파일에서 중요하므로 위의 내용에 주의하세요.&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter pub get&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;패키지를 설치하려면&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;실행하세요 .&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-3-updating-the-android-and-ios-configurations&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;3단계 - Android 및 iOS 구성 업데이트&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Android의 경우&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;minSdkVersion&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;최소 21 이상 이어야 합니다&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;android/app/build.gradle&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 161.969px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 145.969px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;1 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
2 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
3 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
4 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
5&lt;/font&gt;
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 145.969px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;기본 구성 { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    ... &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    최소 SDK 버전 &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;21&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 
    ... &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
}&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;iOS의 경우 다음을 추가하여 Swift 지원을 활성화하세요&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;ios/Podfile&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;플랫폼 &lt;/font&gt;&lt;span class=&quot;ss&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;:ios&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;span class=&quot;s1&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;11.0&#39;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-4-creating-the-pdf-viewer-widget&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;4단계 - PDF 뷰어 위젯 만들기&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;이제 PDF 뷰어 위젯을 만듭니다.&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;lib/main.dart&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;해당 내용을 열고 다음 코드로 바꿉니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 2186.12px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 2170.12px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;1 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
2 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
3 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
4 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
5 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
6 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
7 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
8 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
9 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
10 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
11 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
12 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
13 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
14 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
15 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
16 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
17 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
18 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
19 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
20 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
21 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
22 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
23 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
24 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
25 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
26 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
27 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
28 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
29 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
30 &lt;/font&gt;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
31 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
32 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
33 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
34 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
35 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
36 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
37 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
38 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
39 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
40 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
41 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
42 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
43 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
44 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
45 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
46 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
47 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
48 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
49 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
50 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
51 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
52 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
53 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
54 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
55 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
56 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
57 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
58 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
59 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
60 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
61 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
62 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
63 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
64 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
65 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
66 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
67 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
68 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
69 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
70 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
71 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
72 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
73 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
74 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
75 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
76 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
77 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
78 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
79 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
80 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
81 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
82 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
83 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
84 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
85 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
86 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
87 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
88 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
89 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
90 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
91 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
92 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
93 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
94 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
95 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
96 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
97 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
98 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
99 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
100 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
101 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
102 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
103 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
104 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
105 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
106 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
107 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
108&lt;/font&gt;&lt;/font&gt;
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 2170.12px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;&#39; 패키지 &lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;: 플러터/material.dart&#39; &lt;/span&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;가져오기&lt;/span&gt; &lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ;
 &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;패키지: 플러터_pdfview/플러터_pdfview.dart&#39; &lt;/span&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;가져오기&lt;/span&gt; &lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ;
 &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;패키지: 경로_공급자/경로_공급자.dart &#39; &lt;/span&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;가져오기&lt;/span&gt; &lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ;
 &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;다트:io&#39;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 가져오기 ;
 &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;다트:async&#39; &lt;/font&gt;&lt;/span&gt;&lt;/font&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;가져오기&lt;/span&gt; &lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ;
 &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;패키지: 플러터/services.dart&#39; &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;가져오기&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ; &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;void&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; main() =&gt; runApp(MyApp()); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;MyApp &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;클래스는 StatelessWidget을 &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;확장합니다&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; . &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  @override &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  Widget build(BuildContext context) { &lt;/font&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;return&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; MaterialApp( &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
      home: PDFScreen(), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    ); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  } &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
} &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;PDFScreen &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;클래스는&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; StatefulWidget을 확장합니다. &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;@override&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 
  _PDFScreenState &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  createState() =&gt; _PDFScreenState(); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
} &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;_PDFScreenState &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;클래스는&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; State&lt;PDFScreen&gt;을
   &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;확장합니다 . { &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;String&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ? _localPath;
   &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;int&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ? _totalPages = &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;0&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ;
   &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;int&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ? _currentPage = &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;0&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ;
   &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;bool&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; pdfReady = &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;false&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  늦은 PDFViewController _pdfViewController; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  @override &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;void&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; initState() {
     &lt;/font&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;super&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; .initState(); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    fromAsset( &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;assets/sample.pdf&#39;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;sample.pdf&#39;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ).then((file) { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
      setState(() { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
        _localPath = 파일.경로; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
        pdfReady = &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;true&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
      }); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    }); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  } &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  Future&lt;File&gt; fromAsset( &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;문자열&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 자산, &lt;/font&gt;&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;문자열&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 파일 이름) 비동기 {
     &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;최종&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; byteData = rootBundle.load(자산)를 기다립니다.
     &lt;/font&gt;&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;최종&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 파일 = File( &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39; &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;${(await getTemporaryDirectory()).경로} &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;/ &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;$파일 이름 &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes)를 기다립니다. &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;파일을 &lt;/font&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;반환합니다&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; . 
  } &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  @override &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  위젯 빌드(BuildContext 컨텍스트) { &lt;/font&gt;&lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;return&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; Scaffold( &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
      appBar: AppBar( &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
        title: Text( &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;PDF 뷰어&#39;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
        actions: _totalPages != &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;null&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; 
            ? &lt;Widget&gt;[ &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                Center(child: Text( &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39; &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;${_currentPage! + 1} &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;/ &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;$_totalPages &lt;/font&gt;&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&#39;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; )), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                IconButton(&lt;/font&gt;&lt;/font&gt; 




    





  

    

    &lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  아이콘: 아이콘(아이콘.chevron_left), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  눌렸을 때: () { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                    setState(() { _ &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                      현재 페이지 = (_현재 페이지! - &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ).clamp( &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;0&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , _총 페이지! - &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                    }); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                    _pdfViewController.setPage(_현재 페이지!); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  }, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                ), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                아이콘 버튼( &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  아이콘: 아이콘(아이콘.chevron_right), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  눌렸을 때: () { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                    setState(() { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                      _현재 페이지 = (_현재 페이지! + &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ).clamp( &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;0&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , _총 페이지! - &lt;/font&gt;&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                    }); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                    _pdfViewController.setPage(_현재 페이지!); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  }, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                ), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              ] &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
            : &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;null&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
      ), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
      본문: pdfReady &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
          ? PDFView( &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              파일 경로: _localPath, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              enableSwipe: &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;true&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              swipeHorizontal: &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;true&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              autoSpacing: &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;false&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              pageFling: &lt;/font&gt;&lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;false&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; , &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              렌더링 시: (_pages) { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                setState(() { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  _totalPages = _pages; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                }); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              }, 뷰 생성 시 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              : (PDFViewController vc) { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                _pdfViewController = vc; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              }, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              페이지 변경 시: (페이지, 전체) { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                setState(() { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                  _currentPage = 페이지; &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                }); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              }, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              오류 시: (오류) { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                print(error.toString()); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              }, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              페이지 오류 시: (페이지, 오류) { &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
                print( &lt;/font&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39; &lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;$page &lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;${error.toString()} &lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt; ); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
              }, &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
            ) &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
          : Center(자식: CircularProgressIndicator()), &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
    ); &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
  } &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
}&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-5-adding-a-sample-pdf&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;5단계 - 샘플 PDF 추가&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;폴더 에&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;이름이 지정된&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/downloads/pspdfkit-flutter-quickstart-guide.pdf&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;샘플 PDF 문서를&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;추가합니다&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;. 폴더가 없으면 프로젝트의 루트 디렉토리에 만듭니다. 그런 다음&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;파일을 업데이트하여 자산을 포함합니다.&lt;/font&gt;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;sample.pdf&lt;/code&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;assets&lt;/code&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;pubspec.yaml&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 122.781px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 106.781px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;1 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
2 &lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
3&lt;/font&gt;
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 106.781px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;플러터:
 &lt;/font&gt;&lt;span class=&quot;gi&quot; style=&quot;box-sizing: border-box; background: rgb(3, 58, 22); color: rgb(221, 241, 228);&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;+ 에셋: &lt;/font&gt;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;
+ - 에셋/샘플.pdf&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-6-running-the-app&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;6단계 - 앱 실행&lt;/font&gt;&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;PDF 뷰어를 실행하려면 실제 Android 기기를 연결하거나&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://developer.android.com/studio/run/managing-avds&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Android Virtual Device Manager&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;에서 에뮬레이터를 열어야 합니다 . 그런 다음 명령줄에서 다음을 입력합니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px;&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;플러터 런&lt;/font&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;짧은 개발 과정을 거치면 PDF 뷰어 앱을 Android 기기에서 사용할 수 있습니다. ????&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;
&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot; src=&quot;https://www.nutrient.io/assets/images/blog/2022/how-to-build-a-flutter-pdf-viewer/flutter-pdf-viewer.mp4&quot; style=&quot;box-sizing: border-box; display: block; vertical-align: initial; border-radius: 1rem; max-width: 100%; margin: 1em auto 2em !important;&quot; width=&quot;50%&quot;&gt;&nbsp;&lt;/video&gt;
&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;conclusion&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 23px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;결론&lt;/font&gt;&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;이 블로그 게시물에서는 오픈 소스 패키지 세트에서 PDF 패키지를 선택할 때 고려해야 할 몇 가지 요소를 다루었고,&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;너무 번거롭지 않고 간단한 사용 사례를 해결하는 데 좋은 오픈 소스 Flutter PDF 라이브러리를 사용하여 PDF 뷰어를 빌드하는 방법을 보여드렸습니다. 그러나&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/barteksc/AndroidPdfViewer&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;AndroidPdfViewer&lt;/code&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;라이브러리 의 기반이 되는 는 몇 년 동안 업데이트를 받지 못했으며,&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;현재 읽기 전용인 아티팩트 저장소인&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://developer.android.com/studio/build/jcenter-migration&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;JCenter&lt;/font&gt;&lt;/a&gt;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;에 여전히 게시되어 있습니다 .&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;더 복잡한 사용자 정의를 위해 Nutrient는 자세한&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/getting-started/flutter/?flutter-platform=android-ios-web&amp;project=new-project&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;시작 가이드가&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;포함된 자체&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter PDF 라이브러리를&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;제공합니다 . Nutrient에는 다음을 포함한 많은 기본 기능이 제공됩니다.&lt;/font&gt;&lt;/p&gt;

&lt;ul class=&quot;pXc pZc&quot; style=&quot;box-sizing: border-box; margin: 0px; padding-left: 3rem; list-style: none;&quot;&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;간편하고 사용하기 쉬운&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/user-interface/&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;사용자 정의 UI&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/annotations/&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;문서에 주석을 달거나&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/forms/&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;PDF 양식&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;에 디지털 서명을 추가하는 등&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;의 기능을 쉽게 추가할 수 있는 내장형 사전 구축 도구입니다&nbsp;&lt;/font&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;다양한 파일 형식 지원 - 이미지 파일(JPG, PNG, TIFF)부터 PDF 문서까지.&lt;/font&gt;&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;또한 지속적인 개선 및 버그 수정을 통해&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/changelog/flutter/&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;활발한 개발 주기를&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;제공합니다 . Nutrient Flutter SDK를 시작하려면&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/try&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;무료 평가판을&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;확인하세요 . Flutter PDF 라이브러리에 대한 질문이 있으면 언제든지 문의하세요&nbsp;&lt;/font&gt;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/support/request&quot; style=&quot;box-sizing: border-box; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&nbsp;기꺼이 도와드리겠습니다!&lt;/font&gt;&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;faq&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative;&quot;&gt;&lt;button aria-label=&quot;제목으로 링크&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 23px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;자주 묻는 질문&lt;/font&gt;&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter PDF 뷰어를 만드는 데 관해 자주 묻는 몇 가지 질문은 다음과 같습니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;p0B&quot; style=&quot;box-sizing: border-box;&quot;&gt;
&lt;details open=&quot;&quot; style=&quot;box-sizing: border-box; display: flex; border-top: 1px solid rgb(194, 184, 174); flex-direction: column; font-size: 1.125rem; min-height: 48px; padding: 0.75rem 2rem 1rem 0.25rem; position: relative; font-family: &quot;ABC Monument Grotesk&quot;; line-height: 27px;&quot;&gt;&lt;summary style=&quot;box-sizing: border-box; display: flex; line-height: 30px; align-items: center; cursor: pointer; font-size: 1.25rem; gap: 0.5rem; justify-content: space-between; user-select: auto; padding-bottom: 0.75rem;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;Flutter에 적합한 PDF 패키지를 선택하려면 어떻게 해야 하나요?&lt;/font&gt;&lt;/font&gt;&lt;/summary&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;PDF 패키지를 선택할 때는 퍼브 포인트, 인기, 업데이트 빈도, 패키지가 필요한 기능을 지원하는지 여부와 같은 요소를 고려하세요. Flutter의 인기 패키지에는&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;,&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;native_pdf_view&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;, 및 가 있습니다&nbsp;&lt;/font&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;advance_p&lt;/code&gt;&lt;font style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/details&gt;
&lt;/div&gt;
&lt;/article&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div&gt;
&lt;div class=&quot;nut-row nut-inner&quot; style=&quot;box-sizing: border-box; display: flex; flex: 0 1 auto; flex-flow: wrap; margin: 0px -312px; row-gap: 1.25rem; width: 1248px; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;nut-col-lg-8 nut-col-lg-offset-2 nut-col-md-10 nut-col-md-offset-1 nut-col-xs&quot; style=&quot;box-sizing: border-box; flex: 0 0 66.667%; max-width: 66.667%; padding: 0px 0.75rem; margin-left: 208px;&quot;&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;Illustration: How to build a Flutter PDF viewer&quot; class=&quot;pnq&quot; height=&quot;750&quot; src=&quot;./files/attach/images/17429/767/105/c2f4213876379ab9de4b86aefdcefad1.png&quot; style=&quot;box-sizing: border-box; vertical-align: middle; display: inline-block; object-fit: cover; border-radius: 1.5rem; height: auto; margin: 3rem 0px; width: 808px;&quot; width=&quot;1500&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote class=&quot;p5b p9b&quot; style=&quot;box-sizing: border-box; margin: 0px; border-width: 0px 0px 0px 2px; border-left-style: solid; border-left-color: rgb(226, 219, 217); font-size: 18px; line-height: 22px; padding: 0px 0px 0px 1rem; border-top-style: initial; border-right-style: initial; border-bottom-style: initial; border-top-color: initial; border-right-color: initial; border-bottom-color: initial; border-image: initial; align-items: flex-start; border-radius: 0px; display: flex; flex-direction: row; gap: 1rem; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;Information&quot; class=&quot;p-b&quot; src=&quot;./files/attach/binaries/17429/767/105/e52d3ead6ec3f0ff057a6ff0ff945a9e&quot; style=&quot;box-sizing: border-box; vertical-align: middle; display: inline-block; object-fit: cover; height: 2.5rem; margin-bottom: 0.5rem; width: 2.5rem; background-color: rgb(226, 219, 217); border-radius: 0.5rem; padding: 0.5rem;&quot; /&gt;
&lt;p class=&quot;pec&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;This article was first published in March 2022 and was updated in September 2024.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://flutter.dev/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;Flutter&lt;/a&gt;&nbsp;is an open source framework developed by Google that allows for creating natively compiled applications for mobile, web, and desktop from a single codebase in Dart. This post will walk through the process of setting up a basic PDF viewer in Flutter to handle single-page documents.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;It&rsquo;ll start by exploring how to choose the right package for PDF viewing from a range of open source options. Then, you&rsquo;ll proceed to integrate the selected package into a Flutter project, resulting in a functional PDF viewer app.&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;choosing-the-right-pdf-package-for-flutter&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 46px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Choosing the right PDF package for Flutter&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;When selecting a PDF library for Flutter, it&rsquo;s essential to evaluate your requirements and consider factors like package quality and functionality. For simple use cases, exploring open source libraries is a great starting point. For more advanced needs, Nutrient offers a robust&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/sdk/flutter&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;Flutter PDF SDK&lt;/a&gt;&nbsp;with comprehensive features.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;To find suitable packages,&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/flutter/packages?q=pdf&amp;platform=android+ios&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;searching for&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;pdf&lt;/code&gt;&lt;/a&gt;&nbsp;on&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;pub.dev&lt;/a&gt;&nbsp;reveals a plethora of options. Key factors to consider include:&lt;/p&gt;

&lt;ul class=&quot;pXc pZc&quot; style=&quot;box-sizing: border-box; margin: 0px; padding-left: 3rem; list-style: none; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;Pub points&lt;/span&gt;&nbsp;&mdash; Reflects the quality of the package based on static analysis, including support for null safety and adherence to Dart conventions.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;Popularity&lt;/span&gt;&nbsp;&mdash; Indicates the number of developers using the package.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;Update frequency&lt;/span&gt;&nbsp;&mdash; A recent update date often signifies an actively maintained project.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;span style=&quot;box-sizing: border-box; font-variation-settings: &quot;wght&quot; 550;&quot;&gt;Verified publisher&lt;/span&gt;&nbsp;&mdash; Some packages come from verified publishers, adding an extra layer of trust.&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Among the search results, the following packages are noteworthy:&lt;/p&gt;

&lt;ul class=&quot;pXc pZc&quot; style=&quot;box-sizing: border-box; margin: 0px; padding-left: 3rem; list-style: none; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/packages/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;/a&gt;&nbsp;&mdash; A Flutter plugin that provides a&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;PDFView&lt;/code&gt;&nbsp;widget on Android and iOS.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/packages/native_pdf_view&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;native_pdf_view&lt;/code&gt;&lt;/a&gt;&nbsp;&mdash; A Flutter plugin for rendering PDF files on web, macOS, Windows, Android, and iOS.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;&lt;a class=&quot;pds&quot; href=&quot;https://pub.dev/packages/advance_pdf_viewer&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;advance_pdf_viewer&lt;/code&gt;&lt;/a&gt;&nbsp;&mdash; A Flutter plugin for handling PDF files.&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;After a quick assessment of the three packages,&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&nbsp;proved to be the most suitable for the goal of the experiment of implementing a simple PDF viewer. It has an example included in the&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;GitHub repository&lt;/a&gt;, the configuration steps are easy to follow, and under its hood, it&rsquo;s based on a Google library called&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://pdfium.googlesource.com/pdfium/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;PDFium&lt;/a&gt;&nbsp;&mdash; and here&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/blog/contributing-to-pdfium/&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;at Nutrient, we love PDFium&lt;/a&gt;! ❤️&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;building-a-pdf-viewer-with-flutter_pdfview&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 46px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Building a PDF viewer with flutter_pdfview&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&nbsp;is a Flutter package that allows you to render PDFs on both Android and iOS platforms. It provides a seamless way to display PDF files within your Flutter app, offering features such as page navigation, zooming, and more. It exposes some&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview#options&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;configuration options&lt;/a&gt;&nbsp;to provide a customized experience, and there&rsquo;s an&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview/tree/master/example&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;example app&lt;/a&gt;&nbsp;included in the&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;To keep the use case simple, this post will use&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&nbsp;to show a single-page PDF document on an Android device with&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://developer.android.com/about/versions/&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;API 30&lt;/a&gt;.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;The main layout of the app will be a widget showing the rendered PDF document, and it&rsquo;ll allow simple gestures like pinch-to-zoom and dragging the zoomed page.&lt;/p&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;getting-started&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Getting started&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;To get started, ensure you have Flutter installed and set up on your development machine. You can check this by running the following command:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
flutter doctor&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;This command will verify if you have everything in place to start developing with Flutter.&lt;/p&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-1-creating-a-new-flutter-project&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Step 1 &mdash; Creating a new Flutter project&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Begin by creating a new Flutter project. Open your terminal and run:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
flutter create pdf_viewer_app&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Navigate to your project directory:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
cd pdf_viewer_app&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-2-adding-the-flutter_pdfview-dependency&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 36.7969px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Step 2 &mdash; Adding the flutter_pdfview dependency&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Next, add the&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&nbsp;package to your&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;pubspec.yaml&lt;/code&gt;&nbsp;file under dependencies:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 181.562px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 165.562px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
1
2
3
4
5
6
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 165.562px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
...
dependencies:
  flutter:
    sdk: flutter
&lt;span class=&quot;gi&quot; style=&quot;box-sizing: border-box; background: rgb(3, 58, 22); color: rgb(221, 241, 228);&quot;&gt;+ flutter_pdfview: ^1.2.7
&lt;/span&gt;...&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;blockquote class=&quot;p5b p8b&quot; style=&quot;box-sizing: border-box; margin: 0px; border-width: 0px 0px 0px 2px; border-left-style: solid; border-left-color: rgb(226, 219, 217); font-size: 18px; line-height: 22px; padding: 0px 0px 0px 1rem; border-top-style: initial; border-right-style: initial; border-bottom-style: initial; border-top-color: initial; border-right-color: initial; border-bottom-color: initial; border-image: initial; align-items: flex-start; border-radius: 0px; display: flex; flex-direction: row; gap: 1rem; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;Information&quot; class=&quot;p-b&quot; src=&quot;./files/attach/binaries/17429/767/105/e52d3ead6ec3f0ff057a6ff0ff945a9e&quot; style=&quot;box-sizing: border-box; vertical-align: middle; display: inline-block; object-fit: cover; height: 2.5rem; margin-bottom: 0.5rem; width: 2.5rem; background-color: rgb(226, 219, 217); border-radius: 0.5rem; padding: 0.5rem;&quot; /&gt;
&lt;p class=&quot;pec&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(40, 49, 62); overflow-wrap: break-word;&quot;&gt;Be careful with the above, as spaces matter in YAML files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Run&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter pub get&lt;/code&gt;&nbsp;to install the package.&lt;/p&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-3-updating-the-android-and-ios-configurations&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 36.7969px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Step 3 &mdash; Updating the Android and iOS configurations&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;For Android, ensure your&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;minSdkVersion&lt;/code&gt;&nbsp;is at least 21 in&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;android/app/build.gradle&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 161.969px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 145.969px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
1
2
3
4
5
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 145.969px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
defaultConfig {
    ...
    minSdkVersion &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;21&lt;/span&gt;
    ...
}&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;For iOS, enable Swift support by adding the following to your&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;ios/Podfile&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
platform &lt;span class=&quot;ss&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;:ios&lt;/span&gt;, &lt;span class=&quot;s1&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;11.0&#39;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-4-creating-the-pdf-viewer-widget&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Step 4 &mdash; Creating the PDF viewer widget&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Now you&rsquo;ll create the PDF viewer widget. Open&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;lib/main.dart&lt;/code&gt;&nbsp;and replace its content with the following code:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 2186.12px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 2170.12px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 2170.12px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;package:flutter/material.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;package:flutter_pdfview/flutter_pdfview.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;package:path_provider/path_provider.dart&#39;&lt;/span&gt;;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;dart:io&#39;&lt;/span&gt;;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;dart:async&#39;&lt;/span&gt;;
&lt;span class=&quot;kn&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;package:flutter/services.dart&#39;&lt;/span&gt;;

&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;void&lt;/span&gt; main() =&gt; runApp(MyApp());

&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;class&lt;/span&gt; MyApp &lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;extends&lt;/span&gt; StatelessWidget {
  @override
  Widget build(BuildContext context) {
    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;return&lt;/span&gt; MaterialApp(
      home: PDFScreen(),
    );
  }
}

&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;class&lt;/span&gt; PDFScreen &lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;extends&lt;/span&gt; StatefulWidget {
  @override
  _PDFScreenState createState() =&gt; _PDFScreenState();
}

&lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;class&lt;/span&gt; _PDFScreenState &lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;extends&lt;/span&gt; State&lt;PDFScreen&gt; {
  &lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;String&lt;/span&gt;? _localPath;
  &lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;int&lt;/span&gt;? _totalPages = &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;0&lt;/span&gt;;
  &lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;int&lt;/span&gt;? _currentPage = &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;0&lt;/span&gt;;
  &lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;bool&lt;/span&gt; pdfReady = &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;false&lt;/span&gt;;
  late PDFViewController _pdfViewController;

  @override
  &lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;void&lt;/span&gt; initState() {
    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;super&lt;/span&gt;.initState();
    fromAsset(&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;assets/sample.pdf&#39;&lt;/span&gt;, &lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;sample.pdf&#39;&lt;/span&gt;).then((file) {
      setState(() {
        _localPath = file.path;
        pdfReady = &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;true&lt;/span&gt;;
      });
    });
  }

  Future&lt;File&gt; fromAsset(&lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;String&lt;/span&gt; asset, &lt;span class=&quot;kt&quot; style=&quot;box-sizing: border-box; color: rgb(232, 98, 95);&quot;&gt;String&lt;/span&gt; fileName) async {
    &lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;final&lt;/span&gt; byteData = await rootBundle.load(asset);
    &lt;span class=&quot;kd&quot; style=&quot;box-sizing: border-box; color: rgb(50, 148, 218);&quot;&gt;final&lt;/span&gt; file = File(&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;${(await getTemporaryDirectory()).path}&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;$fileName&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;);
    await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;return&lt;/span&gt; file;
  }

  @override
  Widget build(BuildContext context) {
    &lt;span class=&quot;k&quot; style=&quot;box-sizing: border-box; color: rgb(133, 153, 0);&quot;&gt;return&lt;/span&gt; Scaffold(
      appBar: AppBar(
        title: Text(&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;PDF Viewer&#39;&lt;/span&gt;),
        actions: _totalPages != &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;null&lt;/span&gt;
            ? &lt;Widget&gt;[
                Center(child: Text(&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;${_currentPage! + 1}&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt; / &lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;$_totalPages&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;)),
                IconButton(
                  icon: Icon(Icons.chevron_left),
                  onPressed: () {
                    setState(() {
                      _currentPage = (_currentPage! - &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;).clamp(&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;0&lt;/span&gt;, _totalPages! - &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;);
                    });
                    _pdfViewController.setPage(_currentPage!);
                  },
                ),
                IconButton(
                  icon: Icon(Icons.chevron_right),
                  onPressed: () {
                    setState(() {
                      _currentPage = (_currentPage! + &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;).clamp(&lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;0&lt;/span&gt;, _totalPages! - &lt;span class=&quot;mi&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;1&lt;/span&gt;);
                    });
                    _pdfViewController.setPage(_currentPage!);
                  },
                ),
              ]
            : &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;null&lt;/span&gt;,
      ),
      body: pdfReady
          ? PDFView(
              filePath: _localPath,
              enableSwipe: &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;true&lt;/span&gt;,
              swipeHorizontal: &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;true&lt;/span&gt;,
              autoSpacing: &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;false&lt;/span&gt;,
              pageFling: &lt;span class=&quot;kc&quot; style=&quot;box-sizing: border-box; color: rgb(233, 102, 47);&quot;&gt;false&lt;/span&gt;,
              onRender: (_pages) {
                setState(() {
                  _totalPages = _pages;
                });
              },
              onViewCreated: (PDFViewController vc) {
                _pdfViewController = vc;
              },
              onPageChanged: (page, total) {
                setState(() {
                  _currentPage = page;
                });
              },
              onError: (error) {
                print(error.toString());
              },
              onPageError: (page, error) {
                print(&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;$page&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;si&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;${error.toString()}&lt;/span&gt;&lt;span class=&quot;s&quot; style=&quot;box-sizing: border-box; color: rgb(42, 161, 152);&quot;&gt;&#39;&lt;/span&gt;);
              },
            )
          : Center(child: CircularProgressIndicator()),
    );
  }
}&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-5-adding-a-sample-pdf&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Step 5 &mdash; Adding a sample PDF&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;Add a&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/downloads/pspdfkit-flutter-quickstart-guide.pdf&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;sample PDF document&lt;/a&gt;&nbsp;named&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;sample.pdf&lt;/code&gt;&nbsp;to your&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;assets&lt;/code&gt;&nbsp;folder. If the folder doesn&rsquo;t exist, create it in the root directory of your project. Then, update your&nbsp;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgba(0, 0, 0, 0); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;pubspec.yaml&lt;/code&gt;&nbsp;file to include the assets:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pOd pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 122.781px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 106.781px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pSd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; cursor: default; left: 0px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 0.5rem 0px 1rem; position: absolute; text-align: right; top: 0px; user-select: none; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255);&quot;&gt;
1
2
3
&lt;/pre&gt;

&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 106.781px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem; tab-size: 2;&quot;&gt;
flutter:
&lt;span class=&quot;gi&quot; style=&quot;box-sizing: border-box; background: rgb(3, 58, 22); color: rgb(221, 241, 228);&quot;&gt;+  assets:
+    - assets/sample.pdf&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h3 class=&quot;pMq&quot; id=&quot;step-6-running-the-app&quot; style=&quot;box-sizing: border-box; font-size: 2rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin-bottom: 0px; margin-top: 1.75rem; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 18.3906px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Step 6 &mdash; Running the app&lt;/h3&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;To run the PDF viewer, make sure to connect a physical Android device or open an emulator from the&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://developer.android.com/studio/run/managing-avds&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;Android Virtual Device Manager&lt;/a&gt;. Then from the command line, type:&lt;/p&gt;

&lt;div class=&quot;pzd pqr pDd pBd&quot; style=&quot;box-sizing: border-box; border: 1px solid rgb(103, 89, 75); border-radius: 0.75rem; display: flex; flex-direction: column; font-family: &quot;ABC Monument Grotesk Semi-Mono&quot;, monospace; overflow: hidden; color: rgb(215, 220, 228); margin: 0px; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;div class=&quot;pJd&quot; style=&quot;box-sizing: border-box; background-color: rgb(26, 20, 20); height: 83.5938px; padding: 0.5rem; position: relative;&quot;&gt;
&lt;div class=&quot;pKd pMd&quot; style=&quot;box-sizing: border-box; height: 67.5938px; position: relative; width: 606px;&quot;&gt;
&lt;pre class=&quot;pNd&quot; style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.4; overflow: auto; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; color: rgb(255, 255, 255); cursor: text; height: 67.5938px; margin-top: 0px; margin-bottom: 0px; padding: 1.5rem 3rem 1.5rem 1.5rem; tab-size: 2;&quot;&gt;
flutter run&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;pPd&quot; id=&quot;copy-click-container&quot; style=&quot;box-sizing: initial; background-size: 100%; border-radius: 0.5rem; bottom: auto; color: rgb(255, 255, 255); cursor: pointer; padding: 0.5rem; position: absolute; right: 0.5rem; top: 0.75rem; transition: color 80ms, background 80ms;&quot;&gt;
&lt;div class=&quot;p1O pRd&quot; id=&quot;copy-click&quot; role=&quot;img&quot; style=&quot;box-sizing: border-box; height: 1.5rem; width: 1.5rem; background-color: currentcolor; mask-image: var(--pspdfMaskImageUrl); mask-position: var(--pspdfMaskImagePosition,center); mask-repeat: no-repeat; mask-size: contain; --pspdfMaskImageUrl: url(&#039;/assets/images/icons/mono/copy.svg&#039;);&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;After a short building process, the PDF viewer app will be ready to use on the Android device. ????&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;
&lt;video autoplay=&quot;&quot; loop=&quot;&quot; muted=&quot;&quot; playsinline=&quot;&quot; src=&quot;https://www.nutrient.io/assets/images/blog/2022/how-to-build-a-flutter-pdf-viewer/flutter-pdf-viewer.mp4&quot; style=&quot;box-sizing: border-box; display: block; vertical-align: initial; border-radius: 1rem; max-width: 100%; margin: 1em auto 2em !important;&quot; width=&quot;50%&quot;&gt;&nbsp;&lt;/video&gt;
&lt;/p&gt;

&lt;h2 class=&quot;pMq&quot; id=&quot;conclusion&quot; style=&quot;box-sizing: border-box; font-size: 2.5rem; font-variation-settings: &quot;wght&quot; 400; font-weight: 400; line-height: 1.15; margin: 1.75rem 0px 0px; letter-spacing: -0.02em; position: relative; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;&lt;button aria-label=&quot;Link to heading&quot; class=&quot;pQr&quot; style=&quot;box-sizing: initial; font: inherit; margin: 0px; overflow: visible; appearance: button; cursor: pointer; border-width: 0px; border-style: initial; border-color: initial; background: rgb(0, 0, 0); height: 1rem; mask-image: url(&quot;/assets/images/icons/mono/link.svg&quot;); mask-origin: content-box; mask-position: center center; mask-repeat: no-repeat; mask-size: cover; opacity: 0; padding: 0.75rem; pointer-events: none; position: absolute; right: 624px; top: 23px; transform: translateY(-50%); transition: opacity 0.12s; width: 1rem;&quot;&gt;&lt;/button&gt;Conclusion&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;In this blog post, we covered some factors to look at when selecting a PDF package from a set of open source packages, and we showed you how to build a PDF viewer using the open source Flutter PDF library,&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;/a&gt;, which is good for solving simple use cases without too much hassle. However,&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/barteksc/AndroidPdfViewer&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;AndroidPdfViewer&lt;/code&gt;&lt;/a&gt;&nbsp;&mdash; the library&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://github.com/endigo/flutter_pdfview&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none;&quot; target=&quot;_blank&quot;&gt;&lt;code style=&quot;box-sizing: border-box; font-family: monospace, monospace; font-size: 0.875rem; line-height: 1.6; font-variation-settings: &quot;wght&quot; 400; margin: 0px; background-color: rgb(226, 219, 217); border: 1px solid rgb(110, 181, 121); border-radius: 0.5rem; overflow-wrap: anywhere; padding: 0.25rem 0.5rem;&quot;&gt;flutter_pdfview&lt;/code&gt;&lt;/a&gt;&nbsp;is based on &mdash; hasn&rsquo;t received an update in a few years, and it&rsquo;s still published to&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://developer.android.com/studio/build/jcenter-migration&quot; rel=&quot;noreferrer&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot; target=&quot;_blank&quot;&gt;JCenter&lt;/a&gt;, an artifact repository that&rsquo;s now read-only.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;For more complex customizations, Nutrient offers its own&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;Flutter PDF library&lt;/a&gt;&nbsp;with a detailed&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/getting-started/flutter/?flutter-platform=android-ios-web&amp;project=new-project&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;getting started guide&lt;/a&gt;. Nutrient ships with many features out of the box, including:&lt;/p&gt;

&lt;ul class=&quot;pXc pZc&quot; style=&quot;box-sizing: border-box; margin: 0px; padding-left: 3rem; list-style: none; color: rgb(26, 20, 20); font-family: &quot;ABC Monument Grotesk Variable&quot;; font-size: 16px; background-color: rgb(239, 235, 231);&quot;&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;A&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/user-interface/&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;customizable UI&lt;/a&gt;&nbsp;that&rsquo;s simple and easy to use.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;Embeddable prebuilt tools to easily add functionality like&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/annotations/&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;annotating documents&lt;/a&gt;, adding digital signatures to a&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/guides/flutter/forms/&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;PDF form&lt;/a&gt;, and much more.&lt;/p&gt;
	&lt;/li&gt;
	&lt;li class=&quot;pYc&quot; style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0.75rem 0px 0px; overflow-wrap: break-word; position: relative;&quot;&gt;
	&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; overflow-wrap: break-word;&quot;&gt;Multiple file type support &mdash; from image files (JPG, PNG, TIFF) to PDF documents.&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;

&lt;p style=&quot;box-sizing: border-box; font-size: 1.125rem; font-variation-settings: &quot;wght&quot; 400; line-height: 27px; margin: 0px; color: rgb(26, 20, 20); overflow-wrap: break-word; font-family: &quot;ABC Monument Grotesk Variable&quot;; background-color: rgb(239, 235, 231);&quot;&gt;It also features&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/changelog/flutter/&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;active development cycles&lt;/a&gt;&nbsp;with constant improvements and bug fixes. To get started with Nutrient Flutter SDK, check out our&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/try&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;free trial&lt;/a&gt;. If you have any questions about our Flutter PDF library, please don&rsquo;t hesitate to&nbsp;&lt;a class=&quot;pds&quot; href=&quot;https://www.nutrient.io/support/request&quot; style=&quot;box-sizing: border-box; background-color: initial; text-decoration-line: none; border-radius: 1px; padding: 3px 0px; position: relative;&quot;&gt;reach out to us&lt;/a&gt;. We&rsquo;re happy to help!&lt;/p&gt;
&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;﻿&lt;span class=&quot;se-ff-nanumgothic se-fs19 __se-node&quot; id=&quot;SE-afd59bd2-4c84-4a96-a723-8b5be543a0d0&quot;&gt;&lt;u&gt;[출처] &lt;/u&gt;&lt;/span&gt;&lt;span class=&quot;se-ff-nanumgothic se-fs19 se-link __se-node&quot; data-href=&quot;https://www.nutrient.io/blog/how-to-build-a-flutter-pdf-viewer/&quot; id=&quot;SE-5af3ba78-5969-4418-b226-8da30ef73b35&quot;&gt;&lt;u&gt;https://www.nutrient.io/blog/how-to-build-a-flutter-pdf-viewer/&lt;/u&gt;&lt;/span&gt;﻿&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;
&lt;/article&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;]]></description>
						<pubDate>Sun, 19 Jan 2025 19:03:21 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (6) 드래그로 Canvas 내 Object 이동시키기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105764</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105764</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105764#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (6) 드래그로 Canvas 내 Object 이동시키기&lt;/h1&gt;

&lt;h3&gt;Flutter Canvas 드래그로 Object 이동시키기&lt;/h3&gt;

&lt;p&gt;이 포스팅에서는 Flutter Canvas에서 드래그를 통해 객체(Object)를 이동시키는 방법을 설명합니다. 사용자는 특정 객체를 터치하고 드래그하여 원하는 위치로 이동시킬 수 있습니다.&lt;/p&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;1. Node 클래스&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;먼저, 이동 가능한 객체를 나타내는 Node 클래스를 정의합니다.&lt;/p&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;

&nbsp;&lt;/pre&gt;

&lt;p&gt;class Node {&lt;/p&gt;

&lt;p&gt;&nbsp; String id;&lt;/p&gt;

&lt;p&gt;&nbsp; String name;&lt;/p&gt;

&lt;p&gt;&nbsp; double x;&lt;/p&gt;

&lt;p&gt;&nbsp; double y;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; Node(this.id, this.name, this.x, this.y);&lt;/p&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;id&lt;/strong&gt;: 객체의 고유 식별자.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;name&lt;/strong&gt;: 객체에 표시될 텍스트.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;x, y&lt;/strong&gt;: Canvas에서의 좌표.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;2. DraggablePainter 클래스&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Canvas에 배경, 그리드, 객체를 그리는 CustomPainter를 정의합니다.&lt;/p&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
class DraggablePainter extends CustomPainter {
  static const gridWidth = 50.0;
  static const gridHeight = 50.0;

  final double offsetX;
  final double offsetY;
  final List&lt;Node&gt; nodeList;

  DraggablePainter(this.nodeList, this.offsetX, this.offsetY);

  void _drawBackground(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.white70;
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
  }

  void _drawGrid(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.grey;
    for (double x = 0; x &lt; size.width; x += gridWidth) {
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint);
    }
    for (double y = 0; y &lt; size.height; y += gridHeight) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);
    }
  }

  void _drawNodes(Canvas canvas) {
    final paint = Paint()..color = Colors.amber;
    const textStyle = TextStyle(color: Colors.black, fontSize: 14);
    const radius = 30.0;

    for (final node in nodeList) {
      final center = Offset(node.x, node.y);
      canvas.drawCircle(center, radius, paint);
      _drawText(canvas, node.x, node.y, node.name, textStyle);
    }
  }

  void _drawText(Canvas canvas, double x, double y, String text, TextStyle style) {
    final textSpan = TextSpan(text: text, style: style);
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    )..layout();
    final offset = Offset(x - textPainter.width / 2, y - textPainter.height / 2);
    textPainter.paint(canvas, offset);
  }

  @override
  void paint(Canvas canvas, Size size) {
    canvas.save();
    canvas.translate(offsetX, offsetY);

    _drawBackground(canvas, size);
    _drawGrid(canvas, size);
    _drawNodes(canvas);

    canvas.restore();
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) =&gt; true;
}
&lt;/pre&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;3. GestureDetector를 활용한 드래그 이벤트 처리&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;사용자의 드래그 이벤트를 처리하여 객체를 이동시킵니다.&lt;/p&gt;

&lt;p&gt;class DraggableObjectPageState extends State&lt;DraggableObjectPage&gt; {&lt;/p&gt;

&lt;p&gt;&nbsp; final List&lt;Node&gt; nodeList = [&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; Node(&quot;1&quot;, &quot;Node\n1&quot;, 150.0, 180.0),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; Node(&quot;2&quot;, &quot;Node\n2&quot;, 220.0, 40.0),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; Node(&quot;3&quot;, &quot;Node\n3&quot;, 380.0, 240.0),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; Node(&quot;4&quot;, &quot;Node\n4&quot;, 640.0, 190.0),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; Node(&quot;5&quot;, &quot;Node\n5&quot;, 480.0, 350.0),&lt;/p&gt;

&lt;p&gt;&nbsp; ];&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; double offsetX = 0.0;&lt;/p&gt;

&lt;p&gt;&nbsp; double offsetY = 0.0;&lt;/p&gt;

&lt;p&gt;&nbsp; double preX = 0.0;&lt;/p&gt;

&lt;p&gt;&nbsp; double preY = 0.0;&lt;/p&gt;

&lt;p&gt;&nbsp; Node? currentNode;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; Node? _getNodeAt(double x, double y) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; const radius = 30.0;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; for (final node in nodeList) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; final distance = (node.x - x).abs() + (node.y - y).abs();&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; if (distance &lt;= radius) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; return node;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; return null;&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; void _handlePanDown(DragDownDetails details) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; final x = details.localPosition.dx - offsetX;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; final y = details.localPosition.dy - offsetY;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; currentNode = _getNodeAt(x, y);&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; preX = details.localPosition.dx;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; preY = details.localPosition.dy;&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; void _handlePanUpdate(DragUpdateDetails details) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; final dx = details.localPosition.dx - preX;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; final dy = details.localPosition.dy - preY;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; if (currentNode != null) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; setState(() {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; currentNode!.x += dx;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; currentNode!.y += dy;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; });&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; } else {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; setState(() {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; offsetX += dx;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; offsetY += dy;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; });&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; preX = details.localPosition.dx;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; preY = details.localPosition.dy;&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; @override&lt;/p&gt;

&lt;p&gt;&nbsp; Widget build(BuildContext context) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; return Scaffold(&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; body: GestureDetector(&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; onPanDown: _handlePanDown,&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; onPanUpdate: _handlePanUpdate,&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; child: CustomPaint(&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; painter: DraggablePainter(nodeList, offsetX, offsetY),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; child: Container(),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; &nbsp; ),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; ),&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; );&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;결론&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;이 코드를 통해 사용자는 Canvas 내부의 특정 객체를 드래그로 이동시킬 수 있습니다. &lt;code&gt;GestureDetector&lt;/code&gt;와 &lt;code&gt;CustomPainter&lt;/code&gt;를 적절히 활용하여 직관적인 인터페이스를 제공합니다. 추가적으로, 객체와 Canvas 전체의 동시 이동도 처리할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Sun, 19 Jan 2025 16:35:22 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (5) 드래그로 Canvas 이동시키기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105760</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105760</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105760#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (5) 드래그로 Canvas 이동시키기&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/760/105/23c94df0f3274404a60bad618a68c2fa.png&quot; alt=&quot;012.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h3&gt;Flutter Canvas 드래그로 이동시키기&lt;/h3&gt;

&lt;p&gt;Flutter Canvas에서 드래그로 화면을 이동시키는 기능은 &lt;code&gt;GestureDetector&lt;/code&gt;와 &lt;code&gt;CustomPainter&lt;/code&gt;를 활용하여 구현할 수 있습니다. 이 포스팅에서는 Canvas를 드래그해 이동시키는 방법을 코드와 함께 자세히 설명합니다.&lt;/p&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;1. 기본 아이디어&lt;/strong&gt;&lt;/h4&gt;

&lt;ol&gt;
	&lt;li&gt;사용자가 드래그를 시작하면 초기 터치 좌표를 저장합니다.&lt;/li&gt;
	&lt;li&gt;드래그를 업데이트할 때마다 이전 좌표와 현재 좌표의 차이를 계산하여 Canvas의 이동량(offset)을 갱신합니다.&lt;/li&gt;
	&lt;li&gt;CustomPainter를 사용하여 Canvas의 내용을 그릴 때 이동된 위치를 반영합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;2. 주요 코드&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;GestureDetector&lt;/code&gt;를 활용한 드래그 이벤트 처리&lt;/strong&gt;&lt;/p&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;&lt;/pre&gt;

&lt;div class=&quot;contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative bg-token-sidebar-surface-primary dark:bg-gray-950&quot;&gt;
&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;
&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;class DraggableObjectPageState extends State&lt;DraggableObjectPage&gt; {&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; var offsetX = 0.0;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; var offsetY = 0.0;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; var preX = 0.0;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; var preY = 0.0;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; @override&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; Widget build(BuildContext context) {&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; return Scaffold(&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; body: GestureDetector(&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; onPanDown: (detail) {&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preX = detail.localPosition.dx;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preY = detail.localPosition.dy;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; },&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; onPanUpdate: (detail) {&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setState(() {&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final dx = detail.localPosition.dx - preX;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final dy = detail.localPosition.dy - preY;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offsetX += dx;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offsetY += dy;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preX = detail.localPosition.dx;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preY = detail.localPosition.dy;&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; },&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; child: CustomPaint(&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; child: Container(),&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; painter: DraggablePainter(offsetX, offsetY),&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; ),&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; &nbsp; ),&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; &nbsp; );&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;&nbsp; }&lt;/div&gt;

&lt;div class=&quot;flex items-center text-token-text-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9 bg-token-sidebar-surface-primary dark:bg-token-main-surface-secondary select-none&quot;&gt;}&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h4&gt;&lt;strong&gt;3. Canvas에 이동 반영&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;CustomPainter의 &lt;code&gt;paint&lt;/code&gt; 메서드에서 &lt;code&gt;canvas.translate&lt;/code&gt;를 사용하여 이동량을 반영합니다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;class DraggablePainter extends CustomPainter {&lt;/p&gt;

&lt;p&gt;&nbsp; final double offsetX;&lt;/p&gt;

&lt;p&gt;&nbsp; final double offsetY;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; DraggablePainter(this.offsetX, this.offsetY);&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; @override&lt;/p&gt;

&lt;p&gt;&nbsp; void paint(Canvas canvas, Size size) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; canvas.save();&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; canvas.translate(offsetX, offsetY);&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; // 배경 그리기&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; _drawBackground(canvas, size);&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; // 그리드 그리기&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; _drawGrid(canvas, size);&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; canvas.restore();&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; void _drawBackground(Canvas canvas, Size size) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; final paint = Paint()..color = Colors.white70;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; void _drawGrid(Canvas canvas, Size size) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; final paint = Paint()..color = Colors.grey;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; const double gridSize = 50.0;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; for (double x = 0; x &lt; size.width; x += gridSize) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint);&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; for (double y = 0; y &lt; size.height; y += gridSize) {&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; &nbsp; canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);&lt;/p&gt;

&lt;p&gt;&nbsp; &nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp; }&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp; @override&lt;/p&gt;

&lt;p&gt;&nbsp; bool shouldRepaint(CustomPainter oldDelegate) =&gt; true;&lt;/p&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;4. 결과&lt;/strong&gt;&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;GestureDetector&lt;/code&gt;를 사용하여 드래그 이벤트를 처리하고, Canvas의 오프셋(offset)을 업데이트합니다.&lt;/li&gt;
	&lt;li&gt;Canvas를 이동시킬 때 그리드와 기타 요소들도 함께 이동합니다.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;CustomPainter&lt;/code&gt;를 활용하여 Canvas를 갱신합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;코드 전체&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;import &#39;package:flutter/material.dart&#39;;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;class DraggableObjectPage extends StatefulWidget {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; @override&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; State&lt;DraggableObjectPage&gt; createState() =&gt; _DraggableObjectPageState();&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;class _DraggableObjectPageState extends State&lt;DraggableObjectPage&gt; {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; double offsetX = 0.0;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; double offsetY = 0.0;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; double preX = 0.0;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; double preY = 0.0;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; @override&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; Widget build(BuildContext context) {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; return Scaffold(&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; body: GestureDetector(&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; onPanDown: (details) {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preX = details.localPosition.dx;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preY = details.localPosition.dy;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; },&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; onPanUpdate: (details) {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setState(() {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offsetX += details.localPosition.dx - preX;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offsetY += details.localPosition.dy - preY;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preX = details.localPosition.dx;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preY = details.localPosition.dy;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; },&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; child: CustomPaint(&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; size: Size.infinite,&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; painter: DraggablePainter(offsetX, offsetY),&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; &nbsp; ),&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; ),&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; );&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; }&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;class DraggablePainter extends CustomPainter {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; final double offsetX;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; final double offsetY;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; DraggablePainter(this.offsetX, this.offsetY);&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; @override&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; void paint(Canvas canvas, Size size) {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; canvas.save();&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; canvas.translate(offsetX, offsetY);&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; final backgroundPaint = Paint()..color = Colors.white70;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), backgroundPaint);&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; final gridPaint = Paint()..color = Colors.grey;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; const double gridSize = 50.0;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; for (double x = 0; x &lt; size.width; x += gridSize) {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; canvas.drawLine(Offset(x, 0), Offset(x, size.height), gridPaint);&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; }&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; for (double y = 0; y &lt; size.height; y += gridSize) {&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; &nbsp; canvas.drawLine(Offset(0, y), Offset(size.width, y), gridPaint);&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; }&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; &nbsp; canvas.restore();&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; }&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; @override&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;&nbsp; bool shouldRepaint(CustomPainter oldDelegate) =&gt; true;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;font face=&quot;monospace&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;}&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;결론&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Flutter Canvas에서 드래그로 이동시키는 기능은 간단한 로직으로 구현할 수 있습니다. 이 방법을 사용하면 사용자가 직관적으로 Canvas를 제어할 수 있는 유용한 인터페이스를 만들 수 있습니다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Sat, 18 Jan 2025 20:04:38 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (4) Canvas에 Text 그리기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105756</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105756</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105756#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (4) Canvas에 Text 그리기&lt;/h1&gt;

&lt;h1 id=&quot;canvas에-text-그리기&quot; style=&quot;box-sizing: border-box; margin: 20px 0px 0.5rem; font-size: 1.6rem; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;Canvas에 Text 그리기&lt;/h1&gt;

&lt;h2 id=&quot;실행-화면&quot; style=&quot;box-sizing: border-box; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); margin: 2em 0px 1em; font-size: 1rem; text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;실행 화면&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;화면 특정 좌표에 원과 텍스트를 그리는 예제입니다. 원, 사각형, 라인 등은 좌표만 입력하면 쉽게 그릴 수 있기 때문에 사용법이 조금 다른 텍스트 그리기 위주로 포스팅합니다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/756/105/5ee7deaafa8cfaae7570a2e0454284ef.png&quot; alt=&quot;011.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h3&gt;Flutter Canvas에서 텍스트 그리기: 자세한 설명과 코드&lt;/h3&gt;

&lt;p&gt;Flutter의 Canvas를 활용하여 화면에 텍스트를 그리는 방법을 다룹니다. 이 과정에서 &lt;code&gt;TextPainter&lt;/code&gt;를 사용하여 텍스트를 원하는 위치에 그리는 예제를 제공합니다.&lt;/p&gt;

&lt;hr /&gt;
&lt;h4&gt;1. &lt;strong&gt;텍스트 그리기 함수&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;Canvas&lt;/code&gt;에 텍스트를 그리기 위해서는 &lt;code&gt;TextPainter&lt;/code&gt;를 활용해야 합니다. 아래는 텍스트를 중심 정렬로 그리는 함수입니다.&lt;/p&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;void _drawText(Canvas canvas, double centerX, double centerY, String text, TextStyle style) {
  final textSpan = TextSpan(
    text: text,
    style: style,
  );

  final textPainter = TextPainter()
    ..text = textSpan
    ..textDirection = TextDirection.ltr
    ..textAlign = TextAlign.center
    ..layout();

  final double xCenter = centerX - textPainter.width / 2;
  final double yCenter = centerY - textPainter.height / 2;
  final Offset offset = Offset(xCenter, yCenter);

  textPainter.paint(canvas, offset);
}&lt;/pre&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&lt;code class=&quot;!whitespace-pre hljs language-dart&quot;&gt; &lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;TextSpan&lt;/code&gt;: 텍스트와 스타일 정보를 담습니다.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;TextPainter&lt;/code&gt;: 텍스트의 레이아웃을 계산하고 그립니다.&lt;/li&gt;
	&lt;li&gt;중심 정렬을 위해 텍스트의 너비와 높이를 계산한 후, 시작 위치를 보정합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h4&gt;2. &lt;strong&gt;전체 코드 예제&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Canvas에 원과 텍스트를 함께 그리는 예제입니다.&lt;/p&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;import &#39;package:flutter/material.dart&#39;;

class TextDrawingPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        child: Container(),
        painter: TextPainterExample(),
      ),
    );
  }
}

class TextPainterExample extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // 배경 그리기
    final paintBackground = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.fill;

    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paintBackground);

    // 원과 텍스트 스타일 정의
    final paintCircle = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill;

    final textStyle = TextStyle(
      color: Colors.white,
      fontSize: 20,
    );

    // 원과 텍스트 그리기
    final center = Offset(size.width / 2, size.height / 2);
    canvas.drawCircle(center, 50.0, paintCircle);
    _drawText(canvas, center.dx, center.dy, &quot;Flutter&quot;, textStyle);
  }

  void _drawText(Canvas canvas, double centerX, double centerY, String text, TextStyle style) {
    final textSpan = TextSpan(
      text: text,
      style: style,
    );

    final textPainter = TextPainter()
      ..text = textSpan
      ..textDirection = TextDirection.ltr
      ..textAlign = TextAlign.center
      ..layout();

    final double xCenter = centerX - textPainter.width / 2;
    final double yCenter = centerY - textPainter.height / 2;
    final Offset offset = Offset(xCenter, yCenter);

    textPainter.paint(canvas, offset);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}&lt;/pre&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;h4&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/h4&gt;

&lt;ol&gt;
	&lt;li&gt;&lt;code&gt;CustomPainter&lt;/code&gt;를 사용하여 화면에 그립니다.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;paint&lt;/code&gt; 메서드에서 배경, 원, 텍스트를 순차적으로 그립니다.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;_drawText&lt;/code&gt; 함수는 텍스트의 위치와 스타일을 정렬하여 Canvas에 텍스트를 렌더링합니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;결론&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Flutter Canvas에서 텍스트를 그리는 방법은 &lt;code&gt;TextPainter&lt;/code&gt;를 활용하여 구현할 수 있습니다. 이 과정을 통해 원하는 위치에 텍스트를 표시하고, 다양한 스타일을 적용할 수 있습니다.&lt;/p&gt;

&lt;p&gt;이 코드를 기반으로 다양한 응용을 시도해보세요! 필요 시 추가적으로 커스터마이징이 가능합니다.&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Sat, 18 Jan 2025 14:22:08 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (3) Canvas내의 터치(마우스) 좌표 획득하는 방법]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105742</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105742</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105742#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (3) Canvas내의 터치(마우스) 좌표 획득하는 방법&lt;/h1&gt;

&lt;h3&gt;Flutter Canvas에서 터치(마우스) 좌표를 획득하는 방법&lt;/h3&gt;

&lt;p&gt;Flutter의 Canvas를 활용해 화면에서 터치 또는 마우스의 좌표를 획득하는 방법을 다룹니다. 이 과정에서 GestureDetector와 CustomPainter를 활용하며, 구현한 코드를 함께 제공합니다.&lt;/p&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;GestureDetector로 좌표 획득&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Flutter에서는 &lt;code&gt;GestureDetector&lt;/code&gt; 위젯을 사용하여 터치 이벤트를 감지하고, 해당 좌표를 획득할 수 있습니다.&lt;/p&gt;

&lt;h5&gt;&lt;strong&gt;코드 예제&lt;/strong&gt;&lt;/h5&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;import &#39;package:flutter/material.dart&#39;;

class GridPage extends StatelessWidget {
  const GridPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTapDown: (detail) {
          print(&quot;onTapDown:(${detail.localPosition})&quot;);
        },
        onTapUp: (detail) {
          print(&quot;onTapUp:(${detail.localPosition})&quot;);
        },
        onHorizontalDragUpdate: (detail) {
          print(&quot;onHorizontalDragUpdate:(${detail.localPosition})&quot;);
        },
        child: CustomPaint(
          child: Container(),
          painter: GridPainter(),
        ),
      ),
    );
  }
}&lt;/pre&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;h4&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;GestureDetector&lt;/code&gt;는 사용자의 터치 이벤트를 감지합니다.

	&lt;ul&gt;
		&lt;li&gt;&lt;code&gt;onTapDown&lt;/code&gt;: 터치가 발생한 좌표를 출력.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;onTapUp&lt;/code&gt;: 터치가 끝난 좌표를 출력.&lt;/li&gt;
		&lt;li&gt;&lt;code&gt;onHorizontalDragUpdate&lt;/code&gt;: 드래그하는 동안의 좌표를 실시간으로 출력.&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;이 위젯의 &lt;code&gt;child&lt;/code&gt;에 &lt;code&gt;CustomPaint&lt;/code&gt;를 사용하여 그리드를 화면에 표시합니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h4&gt;&lt;strong&gt;CustomPainter로 배경과 그리드 그리기&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;다음 코드는 Canvas에 그리드와 배경을 그리며, GestureDetector와 결합하여 터치 좌표를 얻을 수 있습니다.&lt;/p&gt;

&lt;h5&gt;&lt;strong&gt;전체 코드&lt;/strong&gt;&lt;/h5&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;import &#39;package:flutter/material.dart&#39;;

class GridPage extends StatelessWidget {
  const GridPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTapDown: (detail) {
          print(&quot;onTapDown:(${detail.localPosition})&quot;);
        },
        onTapUp: (detail) {
          print(&quot;onTapUp:(${detail.localPosition})&quot;);
        },
        onHorizontalDragUpdate: (detail) {
          print(&quot;onHorizontalDragUpdate:(${detail.localPosition})&quot;);
        },
        child: CustomPaint(
          child: Container(),
          painter: GridPainter(),
        ),
      ),
    );
  }
}

class GridPainter extends CustomPainter {
  static const double gridWidth = 50.0;
  static const double gridHeight = 50.0;

  @override
  void paint(Canvas canvas, Size size) {
    // 배경 색상
    var backgroundPaint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.lime
      ..isAntiAlias = true;

    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), backgroundPaint);

    // 그리드 선 색상
    var linePaint = Paint()
      ..style = PaintingStyle.stroke
      ..color = Colors.black38
      ..isAntiAlias = true;

    // 가로선
    for (double y = 0; y &lt;= size.height; y += gridHeight) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), linePaint);
    }

    // 세로선
    for (double x = 0; x &lt;= size.width; x += gridWidth) {
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), linePaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) =&gt; false;
}&lt;/pre&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;h4&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;GridPainter&lt;/code&gt;는 고정된 간격의 그리드를 그립니다.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;CustomPainter&lt;/code&gt;의 &lt;code&gt;paint&lt;/code&gt; 메서드는 Canvas를 사용하여 배경과 선을 그립니다.&lt;/li&gt;
	&lt;li&gt;GestureDetector와 결합하면 그리드에서 터치 좌표를 손쉽게 감지할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;결론&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Flutter의 GestureDetector는 사용자 입력 이벤트를 처리하고, CustomPainter는 화면에 원하는 요소를 그릴 수 있는 강력한 도구입니다. 이를 결합하여 터치 이벤트와 시각적 피드백을 모두 처리할 수 있습니다.&lt;/p&gt;

&lt;p&gt;위 코드를 사용해 Canvas에서 터치 좌표를 감지하는 기능을 구현해보세요! 추가로 커스터마이징이 필요하면 알려주세요.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Fri, 17 Jan 2025 18:38:32 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (2) Grid 격자 그리기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105739</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105739</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105739#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (2) Grid 격자 그리기&lt;/h1&gt;

&lt;p&gt;﻿Flutter의 Canvas를 활용하여 그리드를 그리는 방법을 두 가지로 설명합니다. 첫 번째는 화면 크기에 맞춘 10x10 Grid, 두 번째는 고정된 간격으로 그리는 Grid입니다. 아래는 코드와 설명을 포함한 가이드입니다.&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stechstar.com/user/zbxe/./files/attach/images/17429/739/105/359f196aadfe9659cfde99855ad6b19c.png&quot; alt=&quot;010.png&quot; style=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;1. 10x10 Grid 그리기&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;화면 크기에 따라 10x10으로 동적으로 크기가 조정되는 격자입니다.&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;코드&lt;/strong&gt;&lt;/h4&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;import &#39;package:flutter/material.dart&#39;;

class GridPage extends StatelessWidget {
  const GridPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        child: Container(),
        painter: GridPainter(),
      ),
    );
  }
}

class GridPainter extends CustomPainter {
  static const int rows = 10;
  static const int cols = 10;

  @override
  void paint(Canvas canvas, Size size) {
    // 배경 색상
    var backgroundPaint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.lime
      ..isAntiAlias = true;

    Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
    canvas.drawRect(rect, backgroundPaint);

    // 격자 선 색상
    var linePaint = Paint()
      ..style = PaintingStyle.stroke
      ..color = Colors.black38
      ..isAntiAlias = true;

    final double gridWidth = size.width / cols;
    final double gridHeight = size.height / rows;

    // 가로선
    for (int row = 0; row &lt;= rows; row++) {
      final double y = row * gridHeight;
      canvas.drawLine(Offset(0, y), Offset(size.width, y), linePaint);
    }

    // 세로선
    for (int col = 0; col &lt;= cols; col++) {
      final double x = col * gridWidth;
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), linePaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) =&gt; false;
}&lt;/pre&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;CustomPainter&lt;/code&gt;를 활용하여 격자를 그립니다.&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;paint&lt;/code&gt; 메서드에서 Canvas와 Size를 사용하여 그리드를 동적으로 계산합니다.&lt;/li&gt;
	&lt;li&gt;화면 크기에 따라 각 셀의 크기가 동적으로 변경됩니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;2. 고정 간격 Grid 그리기&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;화면 크기와 상관없이 고정된 간격으로 격자를 그립니다.&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;코드&lt;/strong&gt;&lt;/h4&gt;

&lt;pre class=&quot;!overflow-visible&quot;&gt;
&nbsp;import &#39;package:flutter/material.dart&#39;;

class GridPage extends StatelessWidget {
  const GridPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        child: Container(),
        painter: GridPainter(),
      ),
    );
  }
}

class GridPainter extends CustomPainter {
  static const double gridWidth = 50.0;
  static const double gridHeight = 50.0;

  @override
  void paint(Canvas canvas, Size size) {
    // 배경 색상
    var backgroundPaint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.lime
      ..isAntiAlias = true;

    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), backgroundPaint);

    // 격자 선 색상
    var linePaint = Paint()
      ..style = PaintingStyle.stroke
      ..color = Colors.black38
      ..isAntiAlias = true;

    // 가로선
    for (double y = 0; y &lt;= size.height; y += gridHeight) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), linePaint);
    }

    // 세로선
    for (double x = 0; x &lt;= size.width; x += gridWidth) {
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), linePaint);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) =&gt; false;
}&lt;/pre&gt;

&lt;div&gt;&nbsp;&lt;/div&gt;

&lt;h4&gt;&lt;strong&gt;설명&lt;/strong&gt;&lt;/h4&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;gridWidth&lt;/code&gt;와 &lt;code&gt;gridHeight&lt;/code&gt;를 고정값으로 설정하여 일정 간격의 격자를 만듭니다.&lt;/li&gt;
	&lt;li&gt;화면 크기가 작아도 고정된 간격의 격자가 유지됩니다.&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;
&lt;h3&gt;&lt;strong&gt;결론&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Flutter Canvas는 다양한 방식으로 화면에 그리드를 그릴 수 있는 강력한 도구입니다. 첫 번째 방법은 동적 크기 조절이 필요한 경우, 두 번째 방법은 고정된 격자를 원하는 경우에 적합합니다. 두 방법 모두 Flutter 앱 디자인에 유용하게 활용될 수 있습니다.&lt;/p&gt;

&lt;p&gt;해당 코드로 직접 격자를 구현하며 Flutter Canvas의 가능성을 탐험해보세요!&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Fri, 17 Jan 2025 18:25:48 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (1) 배경 색상 그리기]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105704</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105704</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105704#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (1) 배경 색상 그리기&lt;/h1&gt;

&lt;h1 id=&quot;canvas-사용하기&quot; style=&quot;box-sizing: border-box; margin: 20px 0px 0.5rem; font-size: 1.6rem; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;Canvas 사용하기&lt;/h1&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;Flutter에서 Canvas를 사용하기 위해서는&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;CustomPainter&lt;/code&gt;라는 위젯을 상속받아 구현해야 합니다. 그리고&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;void paint(...)&lt;/code&gt;&nbsp;함수와&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;bool shouldRepaint(...)&lt;/code&gt;&nbsp;함수를 오버라이드해서 구현해주면 됩니다.&lt;/p&gt;

&lt;h2 id=&quot;backgroundpainter-클래스&quot; style=&quot;box-sizing: border-box; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); margin: 2em 0px 1em; font-size: 1rem; text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;BackgroundPainter 클래스&lt;/h2&gt;

&lt;pre class=&quot;prettyprint prettyprinted&quot; style=&quot;box-sizing: border-box; overflow: auto; font-family: Menlo, &quot;Bitstream Vera Sans Mono&quot;, &quot;DejaVu Sans Mono&quot;, Monaco, Consolas, monospace; font-size: 16px; padding: 1rem; margin-top: 0px; margin-bottom: 1rem; line-height: 1.4; color: rgb(51, 51, 51); word-break: break-all; overflow-wrap: break-word; background: rgb(0, 0, 0); border: 0px solid rgb(136, 136, 136); border-radius: 4px; max-width: 100%;&quot;&gt;
&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;BackgroundPainter&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;CustomPainter&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;@override&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; paint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Canvas&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; canvas&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; size&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; background &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Paint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;style &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;PaintingStyle&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;fill
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;color &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;lime
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;isAntiAlias &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Rect&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; rect &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Rect&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;fromLTWH&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; size&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; size&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    canvas&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;drawRect&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; background&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;@override&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; shouldRepaint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;CustomPainter&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; oldDelegate&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&gt;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;void paint(Canvas canvas, Size size)&lt;/code&gt;&nbsp;메소드의 인자로 넘어오는&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;size&lt;/code&gt;는 현재 CustomPainter의 크기가 들어옵니다.&lt;/p&gt;

&lt;h2 id=&quot;emptypage-클래스&quot; style=&quot;box-sizing: border-box; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); margin: 2em 0px 1em; font-size: 1rem; text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;EmptyPage 클래스&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;그리고 위에서 구현한&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;BackgroundPainter&lt;/code&gt;를 화면에 그리기 위해서는 다음과 같이&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;CustomPainter&lt;/code&gt;의&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;paint&lt;/code&gt;&nbsp;속성에 위에서 만든 객체를 배치하면 됩니다.&lt;/p&gt;

&lt;pre class=&quot;prettyprint prettyprinted&quot; style=&quot;box-sizing: border-box; overflow: auto; font-family: Menlo, &quot;Bitstream Vera Sans Mono&quot;, &quot;DejaVu Sans Mono&quot;, Monaco, Consolas, monospace; font-size: 16px; padding: 1rem; margin-top: 0px; margin-bottom: 1rem; line-height: 1.4; color: rgb(51, 51, 51); word-break: break-all; overflow-wrap: break-word; background: rgb(0, 0, 0); border: 0px solid rgb(136, 136, 136); border-radius: 4px; max-width: 100%;&quot;&gt;
&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;EmptyPage&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;StatelessWidget&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;EmptyPage&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; key&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; key&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;@override&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;BuildContext&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; context&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Scaffold&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
      body&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;CustomPaint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
        child&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
        painter&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;BackgroundPainter&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;여기서 주의할 점은&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;CustomPaint&lt;/code&gt;&nbsp;속성 중&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;child: Container()&lt;/code&gt;를 지정해주어야&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;BackgroundPainter&lt;/code&gt;&nbsp;클래스의&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;void paint(Canvas canvas, Size size)&lt;/code&gt;&nbsp;함수 인자인&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;size&lt;/code&gt;&nbsp;크기가 전달됩니다. 만약&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;child&lt;/code&gt;&nbsp;속성이 없다면&nbsp;&lt;code class=&quot;language-plaintext highlighter-rouge&quot; style=&quot;box-sizing: border-box; font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 13.6px; padding: 0.25em 0.5em; color: rgb(102, 102, 102); background-color: rgb(249, 249, 249); border-radius: 3px;&quot;&gt;size&lt;/code&gt;는 (0, 0)이 됩니다.&lt;/p&gt;

&lt;h2 id=&quot;전체-코드&quot; style=&quot;box-sizing: border-box; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); margin: 2em 0px 1em; font-size: 1rem; text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;전체 코드&lt;/h2&gt;

&lt;pre class=&quot;prettyprint prettyprinted&quot; style=&quot;box-sizing: border-box; overflow: auto; font-family: Menlo, &quot;Bitstream Vera Sans Mono&quot;, &quot;DejaVu Sans Mono&quot;, Monaco, Consolas, monospace; font-size: 16px; padding: 1rem; margin-top: 0px; margin-bottom: 1rem; line-height: 1.4; color: rgb(51, 51, 51); word-break: break-all; overflow-wrap: break-word; background: rgb(0, 0, 0); border: 0px solid rgb(136, 136, 136); border-radius: 4px; max-width: 100%;&quot;&gt;
&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;str&quot; style=&quot;box-sizing: border-box; color: rgb(185, 202, 74);&quot;&gt;&#39;package:flutter/material.dart&#39;&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;EmptyPage&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;StatelessWidget&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;EmptyPage&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; key&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; key&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;@override&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Widget&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; build&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;BuildContext&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; context&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Scaffold&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
      body&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;CustomPaint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
        child&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Container&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
        painter&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;BackgroundPainter&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(),&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;BackgroundPainter&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;CustomPainter&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;@override&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; paint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Canvas&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; canvas&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; size&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; background &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Paint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;style &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;PaintingStyle&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;fill
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;color &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;lime
      &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;isAntiAlias &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

    &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Rect&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; rect &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;Rect&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;fromLTWH&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; size&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; size&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
    canvas&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;drawRect&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;rect&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; background&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;

  &lt;/span&gt;&lt;span class=&quot;lit&quot; style=&quot;box-sizing: border-box; color: rgb(231, 140, 69);&quot;&gt;@override&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; shouldRepaint&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;typ&quot; style=&quot;box-sizing: border-box; color: rgb(122, 166, 218);&quot;&gt;CustomPainter&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; oldDelegate&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;=&gt;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kwd&quot; style=&quot;box-sizing: border-box; color: rgb(195, 151, 216);&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;pln&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;pun&quot; style=&quot;box-sizing: border-box; color: rgb(234, 234, 234);&quot;&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;h2 id=&quot;maindart&quot; style=&quot;box-sizing: border-box; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); margin: 2em 0px 1em; font-size: 1rem; text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;main.dart&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;&lt;/pre class=&rdquo;prettyprint&rdquo;&gt; import &lsquo;package:flutter/material.dart&rsquo;;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;import &lsquo;canvas/01_background_color.dart&rsquo;;&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;void main() { runApp(MyApp()); }&lt;/p&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: &lsquo;Flutter Demo&rsquo;, debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), home: EmptyPage(), ); } } &lt;/pre&gt;&lt;/p&gt;

&lt;h2 id=&quot;실행-화면&quot; style=&quot;box-sizing: border-box; font-family: &quot;PT Sans&quot;, Helvetica, Arial, sans-serif; line-height: 1.25; color: rgb(49, 49, 49); margin: 2em 0px 1em; font-size: 1rem; text-rendering: optimizelegibility; letter-spacing: -0.025rem; background-color: rgb(255, 255, 255);&quot;&gt;실행 화면&lt;/h2&gt;

&lt;p style=&quot;box-sizing: border-box; margin: 0px 0px 1rem; color: rgb(81, 81, 81); font-family: &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img data-autoattach=&quot;success&quot; alt=&quot;image&quot; src=&quot;./files/attach/images/17429/704/105/7dfd0399b60d6f0d0b54b22294db2925.png&quot; style=&quot;box-sizing: border-box; vertical-align: middle; display: block; margin: 0px 0px 1rem; border-radius: 5px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;[출처]&nbsp;https://snowdeer.github.io/flutter/2021/12/28/flutter-custom-painter-example-01/&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Thu, 16 Jan 2025 22:48:49 +0900</pubDate>
								</item>
				<item>
			<title><![CDATA[[게임 일반] 선택 기반 게임의 표준 패턴 : Standard Patterns in Choice-Based Games]]></title>
			<dc:creator><![CDATA[졸리운_곰]]></dc:creator>
			<link>https://www.stechstar.com/user/zbxe/MultiFGame/105690</link>
			<guid isPermaLink="true">https://www.stechstar.com/user/zbxe/MultiFGame/105690</guid>
						<comments>https://www.stechstar.com/user/zbxe/MultiFGame/105690#comment</comments>
									<description><![CDATA[&lt;div class=&quot;xe_content&quot;&gt;&lt;h1&gt;[게임 일반] 선택 기반 게임의 표준 패턴 : Standard Patterns in Choice-Based Games&lt;/h1&gt;

&lt;h2 class=&quot;entry-title&quot; style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; clear: both; font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, &quot;Nimbus Sans L&quot;, sans-serif; line-height: 1.3em; font-size: 21px;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/&quot; rel=&quot;bookmark&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0); text-decoration-line: none;&quot;&gt;선택 기반 게임의 표준 패턴&lt;/a&gt;&lt;/h2&gt;

&lt;div class=&quot;entry-meta&quot; style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, &quot;Nimbus Sans L&quot;, sans-serif; color: rgb(119, 119, 119); font-size: 12px; text-size-adjust: 120%;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/&quot; rel=&quot;bookmark&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(119, 119, 119);&quot; title=&quot;오후 5시 55분&quot;&gt;&lt;span class=&quot;entry-date&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;2015년 1월 26일&lt;/span&gt;&lt;/a&gt;&nbsp;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;게시자&nbsp;&lt;/font&gt;&lt;span class=&quot;meta-sep&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;:&nbsp;&lt;/span&gt;&lt;span class=&quot;author vcard&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a class=&quot;url fn n&quot; href=&quot;https://heterogenoustasks.wordpress.com/author/samkaboashwell/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(119, 119, 119);&quot; title=&quot;Sam Kabo Ashwell의 모든 게시물 보기&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Sam Kabo Ashwell&lt;/font&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;

&lt;div class=&quot;entry-content&quot; style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px; padding: 12px 0px 0px; vertical-align: baseline; clear: both; counter-reset: footnotes 0; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;
&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;몇 년 전 CYOA 작업의 구조를 분석할 때, 저는 몇 가지 강력한 반복적 디자인 패턴을 인식하기 시작했습니다. 저는 몇 가지 자체 제작 용어를 생각해 냈지만, 그것을 멋지고 명확한 방식으로 배치한 적은 없습니다. 이것은 다소 업데이트된(그 이후로 많은 것이 바뀌었습니다) 몇 가지 보다 일반적인 접근 방식에 대한 비철저한 검토입니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;이것들이 별개의 범주가 아니라는 점을 강조해야겠습니다. 많은 작품이 매우 간단하게 단일 패턴에 속하지만, 많은 작품이 여러 패턴의 요소를 포함할 것입니다. (그리고 물론, 종종 다른 패턴의 메커니즘을 사용하여 하나를 시뮬레이션할 수 있다는 것을 알고 있습니다. 그것은 대부분 요점이 아닙니다.) 또한, 제가 사용하는 예시 다이어그램은 실제 작품에서 볼 수 있는 것보다 작고 간단합니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;시간 동굴.&nbsp;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;심하게 분기된 시퀀스. 모든 선택은 대략 동등한 중요성을 갖습니다. 재병합이 거의 없거나 전혀 없으므로 상태 추적이 필요 없습니다. 수많은 엔딩이 있습니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-timeout&quot; alt=&quot;타임케이브&quot; class=&quot;aligncenter wp-image-1171 size-full&quot; data-attachment-id=&quot;1171&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;timecaveb&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=640&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png&quot; data-orig-size=&quot;640,118&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/timecaveb/&quot; height=&quot;118&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=640&amp;h=118&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png 640w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=150&amp;h=28 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=300&amp;h=55 300w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;시간 동굴은 가장 오래되고 가장 명확한 CYOA 구조입니다. 자유와 열린 가능성에 대한 서사,&nbsp;&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;어디든 갈 수 있는 모험,&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;공상에 대한 비행에 종종 좋습니다. 시간 동굴은 비교적 짧은 플레이스루를 갖는 경향이 있지만, 리플레이를 강력히 권장합니다. 길기보다는 광범위하기 때문입니다. 여러 번 플레이하더라도 대부분 플레이어는 아마도 콘텐츠의 상당 부분을 놓칠 것입니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;시간 동굴의 구조는 연대순 진행에 따라 조직되고 그것과 분리되어 있습니다. 규칙성에 근거하지 않습니다. 가능성이&nbsp;&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;너무&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;열려 있어서 종종 환상적이거나 초현실적이 되고, 다른 가지가 완전히 다른 현실을 차지합니다. 플레이어는 속도가 있지만 이해력이 부족하고, 자유가 엄청나지만 이해할 능력이 부족합니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;에드워드 패커드의 초기 작품(&nbsp;&lt;/font&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/05/cyoa-structures-the-cave-of-time/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;시간의 동굴&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;,&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/10/cyoa-structures-more-packard/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;사탕수수 섬&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;), 에밀리 쇼트의&nbsp;&lt;/font&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/24/cyoa-structure-if/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;어둡고 폭풍우 같은 입구&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;,&nbsp;&lt;/font&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2012/04/04/cyoa-structure-millennial-snark/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;예쁜 작은 실수들&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;i style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;장갑.&nbsp;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;폭이 넓지 않고 긴 장갑은 비교적 선형적인 중앙 실을 가지고 있으며, 죽음, 후퇴 또는 빠른 재결합으로 끝나는 가지에 의해 가지치기됩니다. 장갑은 일반적으로 하나의 기름 부음받은 이야기를 말하는데, 이는 선택적인 내용으로 장식되거나 실패로 조기에 끝날 수 있습니다. 여러 개의 엔딩이 있는 경우 최종 선택에서 파생될 가능성이 높습니다. 장갑은 거의 국가에 크게 의존하지 않습니다(그렇게 하는 경우 가지와 병목 구조로 발전할 가능성이 높습니다).&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;긴 장갑&quot; class=&quot;aligncenter size-full wp-image-1172&quot; data-attachment-id=&quot;1172&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;gauntlet&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=640&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png&quot; data-orig-size=&quot;640,139&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/gauntlet/&quot; height=&quot;139&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=640&amp;h=139&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png 640w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=150&amp;h=33 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=300&amp;h=65 300w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;플레이어는 자신이 제한된 경로에 있다는 것을 깨달을 가능성이 높지만, 측면 분기의 표현은 매우 중요합니다. 죽음을 의미할까요? 잘못된 답변일까요? 시간을 거슬러 여행할까요? 막힌 경로, 각주 또는 풍경 세부 정보일까요? 대부분의 경우,&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;건틀릿은 위험하고 어렵거나 제한된 세계의 분위기를 조성합니다. 때로는 이것이 처벌적이거나 우울할 수 있습니다. 때로는 어둡고 코믹할 수 있습니다. 때로는 성찰적이거나 수사적 선택에 크게 의존하는 작품에 있다는 신호입니다. 아마도 작성하기 가장 쉬운 구조인 건틀릿은 선형 스토리와 비슷한 용어로 구상할 수 있으며, 대부분의 플레이어가 중요한 콘텐츠의 대부분을 볼 수 있도록 합니다.&lt;/font&gt;&lt;/p&gt;

&lt;div class=&quot;wordads-ad-wrapper wordads-ad-wrapper--inline&quot; style=&quot;background: 0px 0px; border: 0px; margin: 25px auto; padding: 0px; vertical-align: baseline; position: relative; visibility: visible; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Arial, sans-serif; letter-spacing: 1px; width: 640px; clear: both; display: table;&quot;&gt;
&lt;div data-adtags-width=&quot;640&quot; id=&quot;atatags-26942-788759&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;건틀릿에는 치명적인 건틀릿과 친절한 건틀릿의 두 가지 주요 종류가 있습니다. 치명적인 건틀릿은 대부분 실패&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;로 나무를 가지치고&nbsp; 친절한 건틀릿은 대부분 짧은 범위의 재결합으로 가지치고 간단한&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;가지와 병목&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;구조 처럼 보입니다&nbsp;&lt;/font&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;. 친절한 건틀릿은 최근 몇 년 동안 훨씬 더 흔해져서 Twine 작업의 높은 비율을 차지합니다.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예:&nbsp;&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/20/cyoa-structure-spin-offs/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Zork: The Forces of Krill&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&nbsp;&lt;/em&gt;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=qgyhzznz7r5p64eq&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Our Boys In Uniform&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;브랜치와 병목.&nbsp;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;게임은 브랜치지만 브랜치는 일반적으로 모든 버전의 스토리에 공통적인 이벤트를 중심으로 정기적으로 다시 합쳐집니다. 과거 선택의 효과를 없애는 것을 피하기 위해 브랜치와 병목 구조는 거의 항상 상태 추적을 많이 사용합니다(게임에서 이를 수행하지 않으면 도전을 다루고 있을 가능성이 큽니다).&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;드물지만 병목 현상이 눈에 띄지 않을 수도 있습니다. 줄거리가 갈라지고 결코 명확한 재결합 노드에 도달하지 않지만, 각 가지의 끝에서 선택 사항이 동일하거나 유사하여 정교한 시체 효과가 생성됩니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;병가지&quot; class=&quot;aligncenter size-full wp-image-1182&quot; data-attachment-id=&quot;1182&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;bottlebranch&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=640&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png&quot; data-orig-size=&quot;650,231&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/bottlebranch/&quot; height=&quot;227&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=640&amp;h=227&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=640&amp;h=227 640w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=150&amp;h=53 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=300&amp;h=107 300w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png 650w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;브랜치 앤 보틀넥 게임은 시간의 흐름에 크게 좌우되는 경향이 있지만, 플레이어가 상당히 강하게 이해할 수 있도록 합니다.&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;브랜치 앤 보틀넥 구조는 플레이어 캐릭터의 성장을 반영하는 데 가장 자주 사용됩니다. 플레이어가 다소 독특한 스토리 및/또는 개성을 구성할 수 있게 하면서도 관리 가능한 플롯을 허용합니다. 초기 게임에서는 플레이가 매우 유사하다가 이전 선택의 효과가 누적되면서 갈라지는 경향이 있습니다. 이 접근 방식이 효과를 발휘하려면 상당히 큰 부분에서 사용해야 합니다. 결과를 반영하기 전에 변화를 축적할 시간이 필요합니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예:&nbsp; 이것은&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2014/12/13/long-live-the-queen/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Long Live the Queen이&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;작동하는 방식과 거의 같으며&nbsp; ,&nbsp;&lt;/font&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/choiceofgames.com&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Choice of Games&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;의 지침 원칙입니다 (Dan Fabulich는&nbsp;&lt;/font&gt;&lt;a href=&quot;https://www.choiceofgames.com/2011/07/by-the-numbers-how-to-write-a-long-interactive-novel-that-doesnt-suck/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;지연된 분기라는&lt;/em&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;용어를 사용합니다&nbsp;&lt;/font&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;). 또한 상당한 플롯 선택을 허용하는 비 IF 게임에서 일반적인 플롯 구조입니다.&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;br /&gt;
&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;퀘스트.&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;퀘스트 구조는 별개의 분기를 형성하지만, 상대적으로 적은 수의 승리 엔딩(종종 단 하나)에 도달하기 위해 다시 합쳐지는 경향이 있습니다. 이러한 분기의 요소는 모듈식 구조를 가지고 있습니다. 즉, 작고 밀접하게 그룹화된 노드 클러스터로, 각 클러스터 내부에 많은 상호 연결이 있고 외부에는 상대적으로 거의 없는 단일 상황에 접근할 수 있는 여러 가지 방법이 있습니다. 다시 병합하는 것은 꽤 흔하고, 후퇴하는 것은 덜 흔합니다. 퀘스트는 일반적으로 어느 정도의 상태 추적을 포함하며, 그렇지 않으면 성과가 좋지 않습니다. 퀘스트의 최소 크기는 비교적 크고, 이 범주에는 가장 큰 CYOA 중 일부가 포함됩니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;탐구&quot; class=&quot;alignleft size-full wp-image-1181&quot; data-attachment-id=&quot;1181&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;quest&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=400&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png&quot; data-orig-size=&quot;400,179&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/quest/&quot; loading=&quot;lazy&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=640&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png 400w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=150&amp;h=67 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=300&amp;h=134 300w&quot; style=&quot;background: 0px 0px; margin: 4px 24px 12px 0px; padding: 0px; vertical-align: baseline; height: auto; display: inline; float: left;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;효과:&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;이 모드는 탐험 여행에 적합하며, 설정에 초점을 맞춥니다. 퀘스트의 구조는 시간보다는 지리적 구조로 구성되는 경향이 있습니다. 사실, 이런 종류의 대부분 작품은 특정 목적을 염두에 두고 여행을 포함합니다. 퀘스트는 근거 있고 일관된 세계에 적합하지만, 그 맥락에서 플레이어 캐릭터의 상황은 끊임없이 변화합니다. 내러티브는 오래된 D&amp;D 조우처럼 단편적이거나 에피소드적일 경향이 있습니다. 큰 그림에 큰 의미가 없을 수 있는 작은 스토리 조각입니다.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;파이팅&nbsp;&lt;/font&gt;&lt;i style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;판타지&lt;/i&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;시리즈와 그 후속작(&nbsp;&lt;/font&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/17/cyoa-structures-cyo-rpg/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;론 울프&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;,&nbsp;&nbsp;&lt;/font&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2014/08/24/80-days-the-map-is-the-territory/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;80 데이즈&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);&quot;&gt;&lt;b style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;오픈 맵.&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;퀘스트가 지리적 구조로 구성되어 있지만, 시간은 여전히 ​​중요한 역할을 합니다. 내장된 이동 방향이 있기 때문입니다. 하지만 CYOA 구조를 취하고 주요 노드 간 이동을 가역적으로 만들면 정적 지리, 즉 플레이어가 무한정 돌아다닐 수 있는 세계가 생깁니다. 종종 이는&nbsp;&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;문자적 지리이며, 내러티브 진행을 위해 명시적이든 비밀적이든 광범위한 상태 추적에 의존합니다. 하지만 하이퍼텍스트 소설 관용어에 근거한 가정이 있는 것, 즉&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;/em&gt;&lt;a href=&quot;http://www.francoiscoulon.com/le_reprobateur.html&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Le Reprobateur&lt;/font&gt;&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;와 같은 정적이지만 비선형적인 작품의 경우 드문 모드가 아닙니다&nbsp;&nbsp;&lt;/font&gt;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;.&lt;/font&gt;&lt;/font&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;오픈맵&quot; class=&quot;aligncenter size-full wp-image-1173&quot; data-attachment-id=&quot;1173&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;openmap&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=400&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png&quot; data-orig-size=&quot;400,228&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/openmap/&quot; loading=&quot;lazy&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=640&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png 400w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=150&amp;h=86 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=300&amp;h=171 300w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;이것은 종종 파서 IF의 기본 스타일을 모방한 것으로 사용되지만, 일부는 전자의 D&amp;D 뿌리에서 평행하게 파생된 것일 수 있습니다. 고전적인 맵 기반 파서 게임과 마찬가지로 내러티브는 속도가 느려지고 방향성이 떨어지는 경향이 있습니다. 플레이어는 세계를 탐험하고 파악할 여유가 더 많지만, 스토리를 진행하는 데 시간을 덜 보냅니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예: 듀얼마스터&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;,&nbsp;&nbsp;&lt;/font&gt;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=qfvfc6576i90py4w&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;화학 및 물리학&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;분류 모자.&nbsp;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;초기 게임은 크게 분기되고 다시 합류합니다(분기와 병목이 여기서 유력한 모델입니다). 궁극적으로 플레이어가 어느 주요 분기에 배정되는지 결정합니다. 이러한 주요 분기는 일반적으로 매우 선형적입니다. 때로는 장갑처럼 보이지만 선택의 여지가 없는 직선일 수 있습니다. 분류 모자는 초기 게임에서 거의 항상 상태 추적에 크게 의존하며 종종 결정 지점에서 병목 현상이 발생합니다.&lt;/font&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;분류 모자는 더 개방적인 포맷의 폭과 선형적인 포맷의 깊이 사이의 타협입니다. 때때로 다양한 분기의 특성이 플레이어에게 신호로 전달됩니다. 사실, 이것은 플레이어가 후반부의 선형성을 알아차릴 가능성이 높고&nbsp;&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;모든&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;선택이 궁극적으로 특정 스레드로 흘러들어갈 것이라고 생각할 수 있기 때문에 중요합니다. 플레이어는&nbsp; 스토리가 어떻게 진행되는지에&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;많은&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;영향을 받지만, 작가는 결국 여러 개의 다른 게임을 써야 할 수도 있습니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예:&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/09/11/cyoa-structure-graphic-novels/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;카타와 쇼조&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&nbsp;&lt;/em&gt;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=es0sfij74uu4barv&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;마법의 화장&nbsp;&lt;/font&gt;&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;플로팅 모듈.&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;컴퓨터 기반 작품에서만 실제로 가능한 모드입니다. 나무가 없습니다. 또는 흩어진 나뭇가지와 가지가 있을 수 있지만 줄기가 없습니다. 중심 플롯도 없고, 관통선도 없습니다. 모듈형 조우는 주로 상태에 따라 또는 무작위로 플레이어에게 제공됩니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;이 스타일은 쓰기에 도전적인데, 직관적으로 이해하기 어렵기 때문입니다. 작가들은 더 통합된 구조로 빠르게 회복하는 경향이 있고, 이전 이벤트에 대한 가정이 거의 없기 때문입니다. 많은 양의 콘텐츠가 없으면 이 방법은 선형 시스템으로 붕괴되는 경향이 있습니다. 플레이 메커니즘은 주로 세계를 협상하기 위해 통계를 변경하는 것에 관한 것이기 때문에 플레이어에게 이러한 통계를 노출하는 데 강력한 인센티브가 있습니다. 통계에 영향을 미치도록 선택된 반복 이벤트(그라인딩)는 기능일 수 있습니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;플로팅 모듈에는 다양한 접근 방식이 있습니다.&nbsp;&lt;/font&gt;&lt;a href=&quot;https://emshort.wordpress.com/2016/04/12/beyond-branching-quality-based-and-salience-based-narrative-structures/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Emily Short는 여기에서 잠정적인 분류를 제시합니다&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;예:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;모듈형 디자인의 순수한 예는 비교적 드뭅니다.&nbsp;&lt;/font&gt;&lt;a href=&quot;http://web.archive.org/web/20040404061317/www.channelzilch.com/doug/battle.htm&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;시카고의 왕&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;(Sean Barrett에게 경의를 표합니다)은 초기의 예입니다.&nbsp;&nbsp;&lt;/font&gt;&lt;a href=&quot;http://storynexus.com/s&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;StoryNexus&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;와 그 개념적 친척(예:&nbsp;&nbsp;&lt;/font&gt;&lt;a href=&quot;http://varytale.com/books/book/short-bee/info/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;Bee&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;)은 이 공간에 거주하지만, 일반적으로 선형 진행 구조를 더 많이 부과합니다. (Alexis Kennedy는 일반적인 접근 방식을 설명하기 위해&nbsp;&lt;/font&gt;&lt;a href=&quot;http://www.failbettergames.com/storynexus-developer-diary-2-fewer-spreadsheets-less-swearing/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;품질 기반 내러티브라는&lt;/font&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;용어를 사용합니다 . &#39;파이프나 복잡한 기계가 아닌 모자이크 타일과 같은 스토리 조각.&#39;)&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;사이클그로우&quot; class=&quot;alignright size-full wp-image-1178&quot; data-attachment-id=&quot;1178&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;cyclegrow&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=300&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png&quot; data-orig-size=&quot;300,243&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/cyclegrow/&quot; loading=&quot;lazy&quot; sizes=&quot;(max-width: 300px) 100vw, 300px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=640&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png 300w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=150&amp;h=122 150w&quot; style=&quot;background: 0px 0px; margin: 4px 0px 12px 24px; padding: 0px; vertical-align: baseline; height: auto; display: inline; float: right;&quot; /&gt;&lt;/a&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;루프 앤 그로우.&lt;/font&gt;&lt;/font&gt;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;이 게임은 어떤 종류의 중심 스레드가 있는데, 이 스레드는 같은 지점까지 반복해서 돌지만, 상태 추적 덕분에 매번 새로운 옵션이 잠금 해제되고 다른 옵션은 닫힐 수 있습니다. 이는 매우 일반적인 패턴이며, 다른 많은 패턴과 공존할 수 있습니다.&nbsp; 예를 들어,&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Trapped in Time 은&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;기본적으로 사이클 앤 그로우잉 Gauntlet입니다.&nbsp;&nbsp;&lt;/font&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Bee 는&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;&nbsp;1년 동안 루프 구조로 떠다니는 모듈의 특성을 길들입니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;효과:&nbsp;&lt;/em&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;Loop and Grow는 서사적 모멘텀을 유지하면서도 세계의 규칙성을 강조합니다. 서사의 전체 섹션이 반복될 수 있는 이유에 대한 정당화가 필요합니다. 플레이어 캐릭터는 종종 익숙한 공간에서 일상적인 활동을 따르거나, 시간 여행을 하거나, 특정 수준의 추상화에서 작업을 수행합니다. 이러한 규칙성은 종종 개방성의 대가로 제공됩니다. 강력한 Loop and Grow 구조를 가진 많은 스토리는 구속이나 침체에 맞서 싸우는 내용을 포함합니다.&lt;/font&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;루프 앤 그로우 구조의 중요한 변형은&nbsp;&nbsp;&lt;/font&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;스포크와 허브입니다.&nbsp;&lt;/span&gt;&lt;font style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: inherit;&quot;&gt;&nbsp;게임에는 여러 가지 주요 분기가 있지만 모두 중앙 노드 또는 노드 집합에서 시작하여 돌아갑니다. 플레이어는 각 스포크를 따라 한 번 또는 여러 번 나갈 수 있습니다.&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&lt;span style=&quot;color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px; background-color: rgb(255, 255, 255);&quot;&gt;[출처]&nbsp;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;h2 class=&quot;entry-title&quot; style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; clear: both; font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, &quot;Nimbus Sans L&quot;, sans-serif; line-height: 1.3em; font-size: 21px;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/&quot; rel=&quot;bookmark&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0); text-decoration-line: none;&quot;&gt;Standard Patterns in Choice-Based&nbsp;Games&lt;/a&gt;&lt;/h2&gt;

&lt;div class=&quot;entry-meta&quot; style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-family: &quot;Helvetica Neue&quot;, Arial, Helvetica, &quot;Nimbus Sans L&quot;, sans-serif; color: rgb(119, 119, 119); font-size: 12px; text-size-adjust: 120%;&quot;&gt;&lt;span class=&quot;meta-prep meta-prep-author&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Posted on&lt;/span&gt;&nbsp;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/&quot; rel=&quot;bookmark&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(119, 119, 119);&quot; title=&quot;5:55 pm&quot;&gt;&lt;span class=&quot;entry-date&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;January 26, 2015&lt;/span&gt;&lt;/a&gt;&nbsp;&lt;span class=&quot;meta-sep&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;by&lt;/span&gt;&nbsp;&lt;span class=&quot;author vcard&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a class=&quot;url fn n&quot; href=&quot;https://heterogenoustasks.wordpress.com/author/samkaboashwell/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(119, 119, 119);&quot; title=&quot;View all posts by Sam Kabo Ashwell&quot;&gt;Sam Kabo Ashwell&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;

&lt;div class=&quot;entry-content&quot; style=&quot;background: 0px 0px rgb(255, 255, 255); border: 0px; margin: 0px; padding: 12px 0px 0px; vertical-align: baseline; clear: both; counter-reset: footnotes 0; color: rgb(51, 51, 51); font-family: Georgia, &quot;Bitstream Charter&quot;, serif; font-size: 16px;&quot;&gt;
&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;When I was analysing the structures of CYOA works a few years back, I began to recognise some strong recurring design patterns. I came up with some home-brewed terminology, but didn&rsquo;t ever lay it out in a nice clear way. This is a non-exhaustive look at some of the more common approaches, somewhat-updated (a lot has changed since then).&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;I should stress that these aren&rsquo;t discrete categories: while a lot of works will fall very straightforwardly into a single pattern, many will involve elements of multiple patterns. (And yes, I&rsquo;m aware that you can often simulate one using the mechanics of another. That&rsquo;s mostly beside the point.) Also, the example diagrams I&rsquo;m using are smaller and simpler than would be&nbsp;likely in actual works.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;Time Cave.&nbsp;&lt;/span&gt;A heavily-branching sequence. All choices are of roughly equal significance; there is little or no re-merging, and therefore no need for state-tracking. There are many, many endings.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;timecaveb&quot; class=&quot;aligncenter wp-image-1171 size-full&quot; data-attachment-id=&quot;1171&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;timecaveb&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=640&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png&quot; data-orig-size=&quot;640,118&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/timecaveb/&quot; height=&quot;118&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=640&amp;h=118&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png 640w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=150&amp;h=28 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/timecaveb.png?w=300&amp;h=55 300w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;The time cave is the oldest and most obvious CYOA structure. It is often good for narratives about freedom and open possibility, adventures that could go&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;anywhere,&lt;/em&gt;&nbsp;flights of fancy.&nbsp;Time caves tend to have relatively short playthroughs, but strongly&nbsp;encourage replay: they are broad rather than long. Even with multiple playthroughs, most players will probably miss a good deal of the content.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;The time cave&rsquo;s&nbsp;structure is both organised by chronological progression and detached from it.&nbsp;It&rsquo;s ungrounded by regularity: possibility is&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;so&lt;/em&gt;&nbsp;open that it often becomes fantastic or surreal, with different branches occupying wholly different realities. The player has velocity but little grasp, vast freedom but little&nbsp;ability to comprehend it.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;&lt;/em&gt;Edward Packard&rsquo;s earlier work (&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/05/cyoa-structures-the-cave-of-time/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;The Cave of Time&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;,&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/10/cyoa-structures-more-packard/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Sugarcane Island&lt;/a&gt;), Emily Short&rsquo;s&nbsp;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/24/cyoa-structure-if/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;A dark and stormy entry&lt;/a&gt;;&nbsp;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2012/04/04/cyoa-structure-millennial-snark/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Pretty Little Mistakes&lt;/a&gt;&lt;i style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/i&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;Gauntlet.&nbsp;&lt;/span&gt;Long rather than broad, gauntlets have a relatively linear central thread, pruned by branches which end in death, backtracking, or quick rejoining. The Gauntlet generally tells one anointed story, which can be adorned with optional content or prematurely ended with failure; if there are multiple endings, they&rsquo;re likely to derive from a Final Choice. Gauntlets rarely rely on state to any great extent (if they do, they are likely to evolve into a branch-and-bottleneck structure.)&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;gauntlet&quot; class=&quot;aligncenter size-full wp-image-1172&quot; data-attachment-id=&quot;1172&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;gauntlet&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=640&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png&quot; data-orig-size=&quot;640,139&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/gauntlet/&quot; height=&quot;139&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=640&amp;h=139&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png 640w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=150&amp;h=33 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/gauntlet.png?w=300&amp;h=65 300w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;The player is likely to realise that they are on a constrained path, but the presentation of side-branches matters a great deal &ndash; do they mean death? incorrect answers? travel back in time? blocked paths, footnotes, &nbsp;or&nbsp;scenic details? Most often,&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/em&gt;the gauntlet creates an atmosphere of a hazardous, difficult or constrained world. Sometimes this can be punishing or depressing; sometimes it can be darkly comic; sometimes it&rsquo;s a sign that you&rsquo;re in a work heavily dependent on reflective or rhetorical choice. Perhaps the easiest structure to author, gauntlets can be conceived of in similar terms to&nbsp;linear stories, and ensure that most players will see most of the important content.&lt;/p&gt;

&lt;div class=&quot;wordads-ad-wrapper wordads-ad-wrapper--inline&quot; style=&quot;background: 0px 0px; border: 0px; margin: 25px auto; padding: 0px; vertical-align: baseline; position: relative; visibility: visible; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Arial, sans-serif; letter-spacing: 1px; width: 640px; clear: both; display: table;&quot;&gt;
&lt;div data-adtags-width=&quot;640&quot; id=&quot;atatags-26942-55772&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/div&gt;
&lt;/div&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;There are two major varieties of gauntlet: deadly and friendly. Deadly gauntlets mostly prune the tree with&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;failure&lt;/em&gt;; friendly ones mostly do so with short-range rejoining, and look a bit more like simple&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;branch-and-bottleneck&lt;/em&gt;&nbsp;structures. Friendly gauntlets have been vastly more common in recent years, making up a high&nbsp;proportion of Twine works.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/20/cyoa-structure-spin-offs/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Zork: The Forces of Krill&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&nbsp;&lt;/em&gt;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=qgyhzznz7r5p64eq&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Our Boys In Uniform&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;Branch and Bottleneck.&nbsp;&lt;/span&gt;&nbsp;The game branches, but the branches regularly rejoin, usually around events that are common to all versions of the story. To avoid obliterating the effect of past choices, branch-and-bottleneck structures almost always rely on heavy use of state-tracking (if a game doesn&rsquo;t do this, chances are you are dealing with a gauntlet).&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;Somewhat rarely, the bottlenecks may be invisible &ndash; the plot branches and never reaches an explicit rejoining node, but the choices at the end of each branch are the same or similar, creating an exquisite-corpse effect.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;bottlebranch&quot; class=&quot;aligncenter size-full wp-image-1182&quot; data-attachment-id=&quot;1182&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;bottlebranch&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=640&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png&quot; data-orig-size=&quot;650,231&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/bottlebranch/&quot; height=&quot;227&quot; sizes=&quot;(max-width: 640px) 100vw, 640px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=640&amp;h=227&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=640&amp;h=227 640w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=150&amp;h=53 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png?w=300&amp;h=107 300w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/bottlebranch.png 650w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;Branch-and-bottleneck games tend to be heavily&nbsp;governed by the passage of time, while still allowing the player fairly strong grasp.&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/em&gt;The branch-and-bottleneck structure is most often used to reflect the growth of the player-character: it allows the player to construct a somewhat-distinctive story and/or personality, while still allowing for a manageable plot. There&rsquo;s a tendency &ndash; not a necessary one, by any means &ndash; for playthroughs to be very similar in the early game, then diverge as the effects of earlier choices accumulate. In order for the approach to work, it has to be used in a fairly large piece; you need time to accumulate change before producing results that reflect it.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;&lt;/em&gt;This is pretty much how&nbsp;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2014/12/13/long-live-the-queen/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Long Live the Queen&lt;/a&gt;&nbsp;works, and is the guiding principle of&nbsp;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/choiceofgames.com&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Choice of Games&lt;/a&gt;&nbsp;(Dan Fabulich uses the&nbsp;term&nbsp;&lt;a href=&quot;https://www.choiceofgames.com/2011/07/by-the-numbers-how-to-write-a-long-interactive-novel-that-doesnt-suck/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;delayed branching&lt;/em&gt;&lt;/a&gt;). It&rsquo;s also a common plot structure in non-IF games that allow significant plot choices.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;br /&gt;
&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;Quest.&nbsp;&lt;/span&gt;The quest structure forms distinct branches, though they tend to rejoin to reach a relatively small number of winning endings (often only one). The elements of these branches have&nbsp;a modular structure: small, tightly-grouped clusters of nodes allowing&nbsp;many ways to approach a single situation, with lots of interconnection within each cluster and relatively little outside it. Re-merging is fairly common; backtracking rather less so. Quests generally involve some level of state-tracking, and do poorly when they don&rsquo;t. The minimal size for a quest is relatively large, and this category includes some of the largest CYOAs.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;quest&quot; class=&quot;alignleft size-full wp-image-1181&quot; data-attachment-id=&quot;1181&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;quest&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=400&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png&quot; data-orig-size=&quot;400,179&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/quest/&quot; loading=&quot;lazy&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=640&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png 400w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=150&amp;h=67 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/quest.png?w=300&amp;h=134 300w&quot; style=&quot;background: 0px 0px; margin: 4px 24px 12px 0px; padding: 0px; vertical-align: baseline; height: auto; display: inline; float: left;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;This mode is well-suited for journeys of exploration, focused on setting; the quest&rsquo;s structure tends to be organised by geography rather than time. Indeed, most works of this kind involve a journey with a specific purpose in mind. Quests work well for grounded, consistent worlds, but within that context the player-character&rsquo;s situation is constantly changing. The&nbsp;narrative&nbsp;tends to be fragmentary or episodic, like old-school D&amp;D encounters: little chunks of story which might not have any great significance for the big picture.&lt;/span&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;&lt;/em&gt;The&nbsp;&lt;i style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Fighting Fantasy&lt;/i&gt;&nbsp;books and their descendants (&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/08/17/cyoa-structures-cyo-rpg/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Lone Wolf&lt;/a&gt;,&nbsp;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2014/08/24/80-days-the-map-is-the-territory/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;80 Days&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 0, 0);&quot;&gt;&lt;b style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Open Map.&lt;/b&gt;&nbsp;Even though quests are structured by geography, time still plays an important part: there&rsquo;s a built-in direction of travel. But take a&nbsp;CYOA structure, make travel between the major nodes reversible, and you&nbsp;have a static geography, a world in which the player can toodle about indefinitely. Often&nbsp;this is a&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;literal&lt;/em&gt;&nbsp;geography and relies on extensive state-tracking both explicit and secret for narrative progress. But it&rsquo;s not an uncommon mode for things with assumptions grounded in the hypertext-novel idiom &ndash; static but non-linear works like&nbsp;&lt;a href=&quot;http://www.francoiscoulon.com/le_reprobateur.html&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Le Reprobateur&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;openmap&quot; class=&quot;aligncenter size-full wp-image-1173&quot; data-attachment-id=&quot;1173&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;openmap&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=400&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png&quot; data-orig-size=&quot;400,228&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/openmap/&quot; loading=&quot;lazy&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=640&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png 400w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=150&amp;h=86 150w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/openmap.png?w=300&amp;h=171 300w&quot; style=&quot;background: 0px 0px; margin: 0px auto 12px; padding: 0px; vertical-align: baseline; height: auto; clear: both; display: block;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;This is often used as an imitation of the default style of parser IF, although some may be parallel derivation from the former&rsquo;s D&amp;D roots. As with classic map-based parser games, the narrative tends to become slower-paced and less directed; the player has more leisure to explore and grasp the world, but spends less of their time advancing the story.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;Duelmaster&lt;/em&gt;;&nbsp;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=qfvfc6576i90py4w&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Chemistry and Physics&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;Sorting Hat.&nbsp;&lt;/span&gt;The early game branches heavily and rejoins heavily (branch-and-bottleneck is a likely model here), ultimately determining which major branch the player gets assigned to. These major branches are typically quite linear&nbsp;&ndash; sometimes they look like gauntlets, but they might be choiceless&nbsp;straight-shots.&nbsp;Sorting Hats almost always rely substantially&nbsp;on state-tracking in the early game, and often bottleneck at the decision point.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;The Sorting Hat&nbsp;is a compromise between the breadth of more open formats and the depth of linear ones. Sometimes&nbsp;the nature of the various branches is signaled to the player; this is kind of important, in fact, because the player is pretty likely to notice the linearity of the second half and might assume that&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;all&nbsp;&lt;/em&gt;of their choices will ultimately get funneled&nbsp;into that particular thread. The player gets a&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;lot&lt;/em&gt;&nbsp;of influence over how the story goes; however, the author may end up effectively having to write several different games.&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;&lt;/em&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/2011/09/11/cyoa-structure-graphic-novels/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Katawa Shoujo&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;;&nbsp;&lt;/em&gt;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=es0sfij74uu4barv&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Magical Makeover&lt;/a&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;Floating&nbsp;Modules.&lt;/span&gt;&nbsp;A mode only really possible in computer-based works. There is no tree &ndash; or, while there may be scattered twigs and branches, there&rsquo;s no trunk. No central plot, no through-line: modular encounters become available to the player based largely on state, or perhaps randomly.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;This is a challenging&nbsp;style to write for, both because it&rsquo;s difficult to intuitively grasp &ndash; writers tend to rebound quickly to a more unified structure &ndash; and because few assumptions can ever be made about prior events.&nbsp;Without a large amount of content, the method tends to collapse into a linear system. Because play mechanics are largely about altering stats in order to negotiate a world, there&rsquo;s a strong incentive to expose those stats to the player; repeated events chosen only to affect a stat (grinding) may be a feature.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;There are different approaches to&nbsp;floating-module:&nbsp;&lt;a href=&quot;https://emshort.wordpress.com/2016/04/12/beyond-branching-quality-based-and-salience-based-narrative-structures/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Emily Short has a tentative categorisation here&lt;/a&gt;.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;&lt;/em&gt;Pure examples of modular design are relatively rare.&nbsp;&lt;a href=&quot;http://web.archive.org/web/20040404061317/www.channelzilch.com/doug/battle.htm&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;King of Chicago&lt;/a&gt;&nbsp;(hat-tip Sean Barrett)&nbsp;is an early example.&nbsp;&lt;a href=&quot;http://storynexus.com/s&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;StoryNexus&lt;/a&gt;&nbsp;and its conceptual relatives (e.g.&nbsp;&lt;a href=&quot;http://varytale.com/books/book/short-bee/info/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Bee&lt;/a&gt;) inhabit&nbsp;this space, though they&nbsp;generally impose some more linear-progression structure on it. (Alexis Kennedy uses the term&nbsp;&lt;a href=&quot;http://www.failbettergames.com/storynexus-developer-diary-2-fewer-spreadsheets-less-swearing/&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;quality-based narrative&lt;/a&gt;&nbsp;to describe the general approach: &lsquo;pieces of story like mosaic tiles, not pipes or complex machinery.&rsquo;)&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;&lt;a href=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;&lt;img data-autoattach=&quot;download-failure&quot; alt=&quot;cyclegrow&quot; class=&quot;alignright size-full wp-image-1178&quot; data-attachment-id=&quot;1178&quot; data-comments-opened=&quot;1&quot; data-image-caption=&quot;&quot; data-image-description=&quot;&quot; data-image-meta=&quot;{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}&quot; data-image-title=&quot;cyclegrow&quot; data-large-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=300&quot; data-medium-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=300&quot; data-orig-file=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png&quot; data-orig-size=&quot;300,243&quot; data-permalink=&quot;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/cyclegrow/&quot; loading=&quot;lazy&quot; sizes=&quot;(max-width: 300px) 100vw, 300px&quot; src=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=640&quot; srcset=&quot;https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png 300w, https://heterogenoustasks.wordpress.com/wp-content/uploads/2015/01/cyclegrow.png?w=150&amp;h=122 150w&quot; style=&quot;background: 0px 0px; margin: 4px 0px 12px 24px; padding: 0px; vertical-align: baseline; height: auto; display: inline; float: right;&quot; /&gt;&lt;/a&gt;Loop&nbsp;and Grow.&nbsp;&lt;/span&gt;&nbsp;The game has a central thread of some kind, which loops around, over and over,&nbsp;to the same point: but thanks to state-tracking, each time around new options may be unlocked and&nbsp;others closed off. This is a very general pattern, and can co-exist with many others.&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Trapped in Time&lt;/em&gt;, for instance, is basically a cycle-and-growing Gauntlet;&nbsp;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Bee&lt;/em&gt;&nbsp;tames its floating-module&nbsp;nature with a year-long loop structure.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Effects:&nbsp;&lt;/em&gt;Loop&nbsp;and Grow emphasizes the regularity of the world while retaining narrative momentum. A justification is needed for why whole sections of narrative can repeat: the player-character is often following routine activities in a familiar space, engaged in time-travel, or performing tasks at a certain level of abstraction. This regularity often comes at the price of openness: many stories with a strong Loop&nbsp;and Grow structure involve a struggle against confinement or stagnation.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;An important variation&nbsp;of&nbsp;loop-and-grow structures is&nbsp;&lt;span style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; font-weight: 700;&quot;&gt;spoke and hub:&nbsp;&lt;/span&gt;the game has several major branches, but they all originate at and return to a central node or set of nodes. The player may go out along each spoke once, or many times.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;em style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Examples:&nbsp;Bee&lt;/em&gt;,&nbsp;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=juj5b61griyoswn2&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Trapped in Time&lt;/a&gt;,&nbsp;&lt;a href=&quot;http://ifdb.tads.org/viewgame?id=b6ljg2m07tmc2ffv&quot; style=&quot;background: 0px 0px; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline; color: rgb(0, 102, 204);&quot;&gt;Solarium&lt;/a&gt;.&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;[출처]&nbsp;https://heterogenoustasks.wordpress.com/2015/01/26/standard-patterns-in-choice-based-games/&lt;/p&gt;

&lt;p style=&quot;background-image: initial; background-position: 0px 0px; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/p&gt;

&lt;p style=&quot;background: 0px 0px; border: 0px; margin: 0px 0px 24px; padding: 0px; vertical-align: baseline;&quot;&gt;&nbsp;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;

&lt;p&gt;&nbsp;&lt;/p&gt;&lt;/div&gt;]]></description>
						<pubDate>Mon, 13 Jan 2025 15:07:10 +0900</pubDate>
								</item>
			</channel>
</rss>
