<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-483639015604758145</id><updated>2026-10-02T22:15:06.022+09:00</updated><category term="Java"/><category term="오픈소스"/><category term="Spring"/><category term="Linux"/><category term="자바"/><category term="AI 코딩"/><category term="Oracle"/><category term="Vue3"/><category term="spring boot"/><category term="Javascript"/><category term="보안"/><category term="스프링"/><category term="codex"/><category term="웹"/><category term="CentOS"/><category term="mysql"/><category term="Spring-Security"/><category term="소프트웨어 공학"/><category term="SPA"/><category term="Security"/><category term="모바일"/><category term="생성형 AI 코딩"/><category term="Tomcat"/><category term="maven"/><category term="vuetify 3"/><category term="클라우드컴퓨팅"/><category term="Android"/><category term="Apache"/><category term="Gradle"/><category term="JWT"/><category term="OpenCV"/><category term="OracleCloud"/><category term="SqlDeveloper"/><category term="Vite"/><category term="Vue"/><category term="chatgpt"/><category term="eclipse"/><category term="macOS"/><category term="spring data jpa"/><category term="라스베리파이4"/><category term="스프링시큐리티"/><category term="암호화"/><category term="Apple Silicon Mac (M1)"/><category term="Claude Code"/><category term="Design Pattern"/><category term="Objective-C 언어"/><category term="SpringBoot"/><category term="Typescript"/><category term="VMware Fusion"/><category term="ag-grid"/><category term="docker"/><category term="hibernate"/><category term="httpd"/><category term="iOS"/><category term="코딩 자동화"/><category term="클라우드"/><category term="AES"/><category term="AI Code Generator"/><category term="CentOS7"/><category term="CodeGraph"/><category term="Freemarker"/><category term="Gemini Code Assist"/><category term="GitHub"/><category term="GitHub Copilot"/><category term="HTML5"/><category term="Intel MacBook Pro"/><category term="Lombok"/><category term="M1"/><category term="MacbookPro M1"/><category term="Nginx"/><category term="Open Source"/><category term="PC-FI"/><category term="PWAs"/><category term="Pinia"/><category term="REST"/><category term="Spring framework"/><category term="VS Code"/><category term="VSCode"/><category term="Windows 11"/><category term="blob"/><category term="coding agent"/><category term="headroom"/><category term="jpa"/><category term="jquery"/><category term="lob"/><category term="raspberry"/><category term="spring cloud"/><category term="subversion"/><category term="vue-material-kit"/><category term="vuetify3"/><category term="webpack"/><category term="yum"/><category term="리눅스"/><category term="빅데이터"/><category term="스마트폰"/><category term="안드로이드"/><category term="오라클클라우드"/><category term=".NET"/><category term="ACL"/><category term="AI 기반 개발"/><category term="ARM Windows"/><category term="AWS"/><category term="CKEditor5"/><category term="Chrome"/><category term="Code"/><category term="CodeWhisperer"/><category term="CryptoJS"/><category term="Data Export"/><category term="Data Import"/><category term="ERD"/><category term="Feedback Loop Engineering"/><category term="Flyway"/><category term="Gif"/><category term="Git"/><category term="GitHub Packages"/><category term="Glide"/><category term="Harness Engineering"/><category term="Hessian"/><category term="Jeus8"/><category term="Job Scheduling"/><category term="Lighthouse"/><category term="Log4j"/><category term="Logitech"/><category term="MySQL Workbench"/><category term="POI"/><category term="Paragon Partition Manager"/><category term="Peter Eckersley"/><category term="Postman"/><category term="Push"/><category term="Quartz"/><category term="Quartz Clustering"/><category term="R"/><category term="RSA"/><category term="Redhat"/><category term="Rserv"/><category term="SELinux"/><category term="SSE"/><category term="Safari"/><category term="Singleton"/><category term="Spotbugs"/><category term="Sycophancy"/><category term="Ubuntu"/><category term="VOLUMIO"/><category term="Visual Studio Code"/><category term="Visual Studio for Mac"/><category term="Volley"/><category term="Vue2"/><category term="Vuetiry"/><category term="Vuex"/><category term="Youtube Downloader"/><category term="bouncy castle"/><category term="chromium"/><category term="cloud"/><category term="daily build and smoke test"/><category term="docs"/><category term="filepond"/><category term="github actions"/><category term="jasypt"/><category term="javamail"/><category term="jcodec"/><category term="kendo"/><category term="markdown"/><category term="moment"/><category term="mono"/><category term="mp3"/><category term="nmon"/><category term="object storage"/><category term="oci"/><category term="office365"/><category term="openapi"/><category term="oracle cloud"/><category term="orm"/><category term="postgres"/><category term="react"/><category term="retorpi"/><category term="schemaspy"/><category term="self-hosted runner"/><category term="skill"/><category term="smtp"/><category term="sonarqube"/><category term="spring actuator"/><category term="spring cloud config server"/><category term="spring jpa"/><category term="springsecurity"/><category term="ssl"/><category term="streaming"/><category term="subagents"/><category term="svn"/><category term="swagger"/><category term="swift"/><category term="tus"/><category term="uppy"/><category term="widows10iot"/><category term="windows10"/><category term="youtube"/><category term="yuicompressor"/><category term="게임"/><category term="교차 검증"/><category term="구형 맥미니 재설치"/><category term="기술적 근거 확인"/><category term="네이버클라우드"/><category term="대용량 파일 다운로드"/><category term="대용량 파일 스트리밍"/><category term="동영상 스트리밍"/><category term="디자인패턴"/><category term="마크다운"/><category term="맥 프로그램"/><category term="맥OS"/><category term="머신러닝"/><category term="무료SSL"/><category term="문서자동화"/><category term="반대 질문"/><category term="생성형 AI"/><category term="성능"/><category term="성능모니터링"/><category term="쇼셜네트워크"/><category term="시큐어코딩"/><category term="아파치"/><category term="웹에디터"/><category term="웹취약점"/><category term="유튜브 다운로드"/><category term="유튜브 음원다운로드"/><category term="전자정부프레임워크"/><category term="정적보안취약점분석"/><category term="캘럭시S"/><category term="코덱스"/><category term="코드 품질 개선"/><category term="크롬"/><category term="표준시"/><category term="하네스엔지니어링"/><category term="하이브리드 암호화"/><category term="한글"/><title type='text'>한국에서 SW 개발자로 산다는것</title><subtitle type='html'>한국에서 SW 개발자로 산다는것은 어떤 것일까?</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>192</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-2604207988425030146</id><published>2026-06-16T10:28:09.078+09:00</published><updated>2026-06-17T13:21:39.532+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="CodeGraph"/><category scheme="http://www.blogger.com/atom/ns#" term="headroom"/><category scheme="http://www.blogger.com/atom/ns#" term="skill"/><category scheme="http://www.blogger.com/atom/ns#" term="생성형 AI 코딩"/><title type='text'>사용기 -  Large Context Analysis 스킬 적용기: CodeGraph로 컨텍스트를 적게 읽게 만들기</title><content type='html'>&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;MIT CSAIL의 논문 「&lt;a href=&quot;https://arxiv.org/pdf/2512.24601 &quot; target=&quot;_blank&quot;&gt;Recursive Language Models&lt;/a&gt;」는 긴 컨텍스트 문제를 다른 방식으로 접근한다. 이 논문은 OOLONG-Pairs처럼 입력 전체의 많은 쌍을 비교해야 하는 작업에서, GPT-5 기본 모델과 compaction agent가 각각 0.1 F1 수준에 머무른 반면 RLM depth=1은 58.0 F1을 기록했다는 결과를 제시한다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;이를 바탕으로 논문은 긴 프롬프트를 LLM 컨텍스트 창에 직접 넣거나 반복 요약하는 대신, 외부 환경에 두고 필요한 부분을 프로그램적으로 탐색·분해·재귀 호출하는 Recursive Language Models, RLMs를 제안한다.&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;* OOLONG-Pairs : &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;논문에서 RLM 성능을 검증하기 위해 사용한 &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;긴 컨텍스트·고밀도 추론 벤치마크&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&lt;i&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;compaction agent : &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;긴 입력을 그대로 넣지 않고, 중간에 요약하거나 압축해서 더 짧은 컨텍스트로 만든 뒤 답하게 하는 방식의 에이전트&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: xx-small;&quot;&gt;&lt;i&gt;* F1 : 정답을 얼마나 잘 맞혔는지 보는 평가 지표&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;* &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;RLM depth=1: &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재귀 호출의 깊이를 1단계까지 허용&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7nuYazBMyHDw5v-8-q2v_5UKCytTk9pAu3k3uSXttQvchCYm2XoigQ_fGBbXwGOyAkpngNQg_AQKn3K4ELe1nHSNYvWVvrO2mjYEEpUcyfRDByot1lEzwx_YBybpvldaAODFgnErkPffg3kWsi2cXKnPuhXlnAW-aMqxBzSXqJY5ycvFC2mc63aaDkFeb/s1536/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7nuYazBMyHDw5v-8-q2v_5UKCytTk9pAu3k3uSXttQvchCYm2XoigQ_fGBbXwGOyAkpngNQg_AQKn3K4ELe1nHSNYvWVvrO2mjYEEpUcyfRDByot1lEzwx_YBybpvldaAODFgnErkPffg3kWsi2cXKnPuhXlnAW-aMqxBzSXqJY5ycvFC2mc63aaDkFeb/w640-h426/image.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Headroom을 사용하면서 성능 리포트상으로는 토큰 절감 효과가 크게 표시되었지만, 컨텍스트를 줄인다는 것은 결국 모델에게 전달되는 정보가 줄어든다는 뜻이기도 하다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;특히&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;성능 지표에서 TOIN retrieval이 0%로 표시되는 상황에서는, 압축된 정보가 필요할 때 원문을 다시 꺼내 검증하는 루프가 실제로 동작하고 있는지 확신하기 어려웠다.&lt;/span&gt;&lt;/div&gt;&lt;span&gt;&lt;div&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;이 지점에서 앞서 언급한&amp;nbsp;&lt;a href=&quot;https://arxiv.org/pdf/2512.24601&quot; target=&quot;_blank&quot;&gt;Recursive Language Models &lt;/a&gt;논문이 주는 시사점이 있었다.&amp;nbsp; 논문은 긴 컨텍스트 문제를 단순히 더 큰 컨텍스트 창에 넣거나, 반복적으로 요약·압축하는 방식만으로 해결하기 어렵다고 본다. 특히 OOLONG-Pairs처럼 입력 전체의 많은 조합을 비교해야 하는 고밀도 추론 작업에서, GPT-5 기본 모델과 compaction agent는 각각 0.1 F1 수준에 머무른 반면, RLM depth=1은 58.0 F1을 기록했다. 이 결과는 긴 입력을 무조건 넣거나 줄이는 것보다, 외부 환경에 두고 필요한 부분을 탐색·분해·재귀 호출하는 방식이 더 효과적일 수 있음을 보여준다.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;이 내용을 Codex 사용 방식에 그대로 적용하기는 어렵지만, 실무적인 힌트는 얻을 수 있었다. 코딩 에이전트들은 대부분 기본적인 파일 검색, 코드 탐색, 부분 읽기, 요약 기능을 제공한다. 그렇다면 반드시 Headroom처럼 컨텍스트를 프록시에서 압축하지 않더라도, 작업 절차 자체를 바꿔 불필요한 컨텍스트 생성을 줄일 수 있다.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;기본적으로 CodeGraph를 사용하고 있기 때문에&amp;nbsp;&lt;b&gt;CodeGraph를 RLM식으로 쓰는 스킬을 적용해보기로 했다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;







&lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;&lt;i&gt;*CodeGraph :&amp;nbsp;&lt;b&gt;코드베이스를 미리 분석해서 클래스, 함수, 호출 관계, 파일 구조를 그래프로 만들어두고, 코딩 에이전트가 필요한 코드 위치를 빠르게 찾도록 도와주는 도구&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;&lt;h3 style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;&lt;b&gt;1. 스킬 생성하기&lt;/b&gt;&lt;/h3&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;스킬 생성은 코덱스 앱을 사용했고 적용 모델은 GPT-5.5 매우 높음을 사용 &lt;/b&gt;&lt;b&gt;plugin-creator 플러그인을 사용하여 다음 내용으로 생성을 요청했다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
  
  &lt;p class=&quot;p1&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p class=&quot;p1&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;
  &lt;script src=&quot;https://gist.github.com/donghyuck/9fed3921b7ac544279c20db948608be9.js&quot;&gt;&lt;/script&gt;
  &lt;/p&gt;
  &lt;p class=&quot;p1&quot;&gt;코덱스의 create-plugins 에 의하여 생성된 결과물은 ~/plugins/large-context-analysis/.codex-plugin/ 경로에 자동으로 생성되었다.&lt;/p&gt;
  
  &lt;p class=&quot;p1&quot;&gt;&lt;br /&gt;
  &lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji6haAgmV_xpTsrvrv4-REIV4oKKMw3YmXp61b2nEXco5vhv9VJlsQvtPxq2ERJw2sz9xsk_OuJQmDD4B9ktnuFT-7HuL1Fk3UwT67OY-0lJdsUgLxCFD6WW6-AqqcH_-C1NZpWoda03RYgFvVk10DJruJWDXs92vegmViLgrH-tPAl2ym8fo-PWGPiPOr/s1536/image.png&quot; style=&quot;display: block; padding: 1em 0px; text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEji6haAgmV_xpTsrvrv4-REIV4oKKMw3YmXp61b2nEXco5vhv9VJlsQvtPxq2ERJw2sz9xsk_OuJQmDD4B9ktnuFT-7HuL1Fk3UwT67OY-0lJdsUgLxCFD6WW6-AqqcH_-C1NZpWoda03RYgFvVk10DJruJWDXs92vegmViLgrH-tPAl2ym8fo-PWGPiPOr/s600/image.png&quot; width=&quot;600&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
    &lt;br /&gt;
  &lt;p&gt;&lt;/p&gt;
  &lt;p class=&quot;p1&quot;&gt;
  &lt;script src=&quot;https://gist.github.com/donghyuck/ebb28c19fb41e7832cba67ec02a9beb8.js&quot;&gt;&lt;/script&gt;
  &lt;/p&gt;
  &lt;p class=&quot;p1&quot;&gt;&lt;br /&gt;&lt;/p&gt;
  &lt;p class=&quot;p1&quot;&gt;생성된 사용자 플러그인은 플러그인 메뉴 내가 만든 항목에서 확인 할 수 있고 &quot;추가&quot; 버튼을 클릭하여 바로 사용할 수 있다.&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd28in7s2y5B9N8GIIxDoDTH0FhMGoZe0rauYiecby0WKzZTEbxe8JsxkBJCtTKjLDrkhkFxqMWNgyUty8R2uc_CsBxgZRyF-W1Zn79P_9E_AMTRynwY7VIhq5DroMQDvc_4lDmyZuuM-IGarmEpw5V2wsOmso1YFBRbfhya67NW88zEGLO2AJGvfDddUq/s2954/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-16_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_03_56.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1058&quot; data-original-width=&quot;2954&quot; height=&quot;230&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjd28in7s2y5B9N8GIIxDoDTH0FhMGoZe0rauYiecby0WKzZTEbxe8JsxkBJCtTKjLDrkhkFxqMWNgyUty8R2uc_CsBxgZRyF-W1Zn79P_9E_AMTRynwY7VIhq5DroMQDvc_4lDmyZuuM-IGarmEpw5V2wsOmso1YFBRbfhya67NW88zEGLO2AJGvfDddUq/w640-h230/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-16_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_03_56.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;새로운 플러그인 생성을 위해 @plugin-creator 채팅으로 이동&lt;/li&gt;&lt;li&gt;생성 후 플러그인 메뉴에서 내가 만든 항목으로 이동&lt;/li&gt;&lt;li&gt;생성된 목록에서 새로운 스킬을 추가&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;p1&quot;&gt;&lt;br /&gt;&lt;/p&gt;



&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. 스킬 테스트 하기&lt;/span&gt;&lt;/h3&gt;&lt;p class=&quot;p2&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQgE79BCvdpQ6aKhXsRcHx7qZk5peoTBI10nbvJhyphenhyphenheKFFo-lCNg67FiWaotF-TbulbbBIFuy2jRfKRSH6lgFw177OEdlTf1A6ZUqY10kHVj8vYgXivLzgl3z45QMWJ_LLvsTGHBS1gNxBAY0-irCaMMIi1O13nntfVCLUtstWKYokenWQzS0T9Rg0OW5F/s1350/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1350&quot; data-original-width=&quot;1165&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQgE79BCvdpQ6aKhXsRcHx7qZk5peoTBI10nbvJhyphenhyphenheKFFo-lCNg67FiWaotF-TbulbbBIFuy2jRfKRSH6lgFw177OEdlTf1A6ZUqY10kHVj8vYgXivLzgl3z45QMWJ_LLvsTGHBS1gNxBAY0-irCaMMIi1O13nntfVCLUtstWKYokenWQzS0T9Rg0OW5F/w552-h640/image.png&quot; width=&quot;552&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음으로 실제 테스트를 진행해보았다. 문제는 Large Context Analysis 스킬의 효과를 확인하기 어렵다는 점이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;큰 파일/데이터을 다룰때는 large-context-analysis 사용해.&lt;/span&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;첨부한 로그를 분석해줘.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;전체 로그를 한 번에 읽지 말고,&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;최초 ERROR, 반복 stack trace, root cause 후보를 먼저 분리해줘.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;그 다음 CodeGraph로 관련 클래스와 호출 경로를 찾고,&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;필요한 소스 구간만 확인해줘.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;마지막에는 원인, 수정 후보, 검증 방법을 정리해줘.&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p2&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보통은 간단하게 아래와 같은 작업 기준을 전달하는 것으로도 충분했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;



&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;큰 파일·긴 로그·대형 diff·복잡한 데이터 분석 시 `large-context-analysis` 스킬을 사용하고, CodeGraph로 작업 대상 코드를 먼저 선정한 뒤, 작업 완료 후 `Context Usage Report`를 반드시 제시한다.&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;strike&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Headroom처럼 토큰 절감률이나 압축률이 숫자로 표시되는 것이 아니기 때문이다. &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;그래서 작업 요청에 추가 조건을 넣었다.&amp;nbsp;&lt;/span&gt;&lt;/strike&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;strike&gt;단순히 로그를 분석하게 하는 것이 아니라, 작업 완료 후 `Context Usage Report`를 제출하도록 했다. 이 보고서에는 사용한 검색어, CodeGraph 탐색 단계, 읽은 파일 목록, 전체 파일을 읽었는지 또는 일부 구간만 읽었는지, 확인한 주요 라인·메서드·SQL ID, 불필요하다고 판단해 읽지 않은 파일, 최종 원문 검증 여부를 포함하도록 했다.&amp;nbsp;&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;strike&gt;이렇게 하면 스킬의 효과를 “토큰이 얼마나 줄었는가”가 아니라 “Codex가 얼마나 불필요한 파일과 로그를 덜 읽었는가”, “관련 후보를 먼저 좁혔는가”, “최종 결론을 원문 기준으로 검증했는가”로 판단할 수 있을 것으로 기대했다. ( 테스트 과정에서 SKILL 에 Report 기능을 추가하여 아래 추가 설명없이도 확인이 가능하게 했다).&amp;nbsp;&lt;/strike&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;strike&gt;&lt;br /&gt;&lt;/strike&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;&quot;Context Usage Report&quot;를 작성해줘.&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;Context Usage Report에는 다음을 포함해줘.&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 사용한 검색어&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 사용한 CodeGraph 쿼리 또는 탐색 단계&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 읽은 파일 목록&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 전체 파일을 읽었는지, 일부 구간만 읽었는지&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 확인한 주요 라인/메서드/SQL ID&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 불필요하다고 판단해 읽지 않은 파일&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;



















&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;strike&gt;- 최종 판단 전 원문 검증 여부&lt;/strike&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWamR61cFpsx1YzRvi2v7DxWtJLfRJiHLnmkWs2QrMxRveEMUCoTEKdnIO5yhBVYzE9x07bokWmp2fJ_CJCfaX_WxWANqAYv1IHXc501B3u5rx9bI1g7KpXXaWschQRenfIVJJCFQ8cL37-8uscFVxiWidttS6j1-EcKr6H8IVLOidMOx9PkU-iJXBdT-/s1604/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.19.34.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1604&quot; data-original-width=&quot;779&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBWamR61cFpsx1YzRvi2v7DxWtJLfRJiHLnmkWs2QrMxRveEMUCoTEKdnIO5yhBVYzE9x07bokWmp2fJ_CJCfaX_WxWANqAYv1IHXc501B3u5rx9bI1g7KpXXaWschQRenfIVJJCFQ8cL37-8uscFVxiWidttS6j1-EcKr6H8IVLOidMOx9PkU-iJXBdT-/w310-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.19.34.png&quot; width=&quot;310&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #666666; font-size: x-small;&quot;&gt;Context Useage Report&amp;nbsp;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이번 테스트 결과를 보면 Large Context Analysis 스킬은 어느 정도 의도한 방식으로 동작했다. Codex는 처음부터 전체 코드베이스를 읽지 않고, search-visualization, VectorSearchVisualizationService, VectorStorePort, PgVectorStoreAdapterV2, PgVectorMapper, metadataFilter, includeText, includeMetadata 같은 기능과 관련된 구체적인 검색어를 사용해 관련 범위를 좁혀 갔다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CodeGraph 탐색도 /search-visualization에서 시작해 Controller → Service → VectorStorePort → PgVectorStoreAdapterV2 → PgVectorJdbcMapper → PgVectorMapper.xml 경로로 진행되었다. 즉 단순히 파일을 많이 읽는 방식이 아니라, 기능의 호출 흐름을 먼저 따라가며 후보 파일을 좁힌 것이다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;실제로 읽은 파일도 구분되었다. DefaultVectorSearchVisualizationService.java와 PgVectorSearchParameter.java는 전체를 확인했고, PgVectorJdbcMapper.java, PgVectorMapper.xml, 테스트 파일은 관련 SQL 또는 테스트 구간만 부분적으로 확인했다. 반면 RAG 일반 검색 Controller/DTO, SkillGraph/Markdown 파일, projection 생성 및 point 저장 관련 파일은 이번 작업 범위와 직접 관련성이 낮다고 판단해 재검토 대상에서 제외했다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 점은 Large Context Analysis 스킬의 효과를 보여주는 부분이다. 효과가 토큰 절감률처럼 숫자로 표시되지는 않지만, Codex가 검색과 CodeGraph를 먼저 사용해 후보를 좁히고, 필요한 파일과 구간만 확인했으며, 불필요한 파일을 읽지 않도록 유도했다는 점에서 컨텍스트 사용을 줄이는 방향으로 동작했다고 볼 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;또한 최종 판단 전 CodeGraph 결과를 원문으로 확인하고, rg로 SQL 패턴을 재확인했으며, 대상 Gradle 테스트와 git diff --check까지 통과시켰다는 점도 중요하다. 이는 요약이나 CodeGraph 결과만 믿지 않고 원본 파일과 테스트 결과를 기준으로 검증했다는 의미다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strike&gt;다만 효과를 더 명확히 보려면 다음부터는 후보 파일 수, 실제 읽은 파일 수, 전체 읽기 파일 수, 부분 읽기 파일 수, 제외한 파일 수를 함께 기록하는 것이 좋다. 그렇게 하면 Large Context Analysis 스킬의 효과를 “느낌”이 아니라, 실제 탐색 범위 축소 결과로 비교할 수 있을 것 같다.&amp;nbsp;&lt;/strike&gt;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: xx-small;&quot;&gt;&lt;i&gt;* 앞에서 언급되는 이름들은 테스트에 적용된 프로젝트 소스 이름이다.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: xx-small;&quot;&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;마지막으로 이번 실험의 결론은 Headroom이 불필요하다는 것이 아니다. Headroom은 긴 로그나 반복 tool output을 줄이는 데 여전히 유용할 수 있다. 다만 압축된 컨텍스트 품질이 찜찜하다면 (개인적인 생각), 먼저 CodeGraph와 스킬을 이용해 “처음부터 필요한 것만 읽게 만드는 방식”을 적용해볼 만하다. Large Context Analysis 스킬은 토큰 절감 도구라기보다, 코딩 에이전트의 조사 습관을 바꾸는 절차적 안전장치에 가깝다.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/2604207988425030146/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/06/large-context-analysis.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/2604207988425030146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/2604207988425030146'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/06/large-context-analysis.html' title='사용기 -  Large Context Analysis 스킬 적용기: CodeGraph로 컨텍스트를 적게 읽게 만들기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7nuYazBMyHDw5v-8-q2v_5UKCytTk9pAu3k3uSXttQvchCYm2XoigQ_fGBbXwGOyAkpngNQg_AQKn3K4ELe1nHSNYvWVvrO2mjYEEpUcyfRDByot1lEzwx_YBybpvldaAODFgnErkPffg3kWsi2cXKnPuhXlnAW-aMqxBzSXqJY5ycvFC2mc63aaDkFeb/s72-w640-h426-c/image.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-7261340206255748407</id><published>2026-06-15T17:07:23.629+09:00</published><updated>2026-06-15T17:30:55.321+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="headroom"/><category scheme="http://www.blogger.com/atom/ns#" term="생성형 AI 코딩"/><title type='text'>사용기 - Headroom으로 Codex 토큰 사용량 줄이기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코딩 에이전트를 사용하여 코드를 분석하고 수정하다보면 가장 먼저 부딪치는 문제는 컨텍스트(모델이 답변을 만들기 위해 한 번에 참고하는 입력 정보 전체)와 토큰 사용량이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;LLM 은 텍스트를 글자 단위가 아닌 토큰(token) 단위로 처리하는데 토큰은 대략 단어 조각, 기호, 코드 조각에 해당한다. 즉 컨텍스트가 길어질 수록 LLM 에 전달되는 토큰 수도 증가하게 된다.&lt;/span&gt;&lt;/p&gt;



&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCZ5sVghS8oFANff6z69rR3JCyhQtLdcZS5KFiMHLYZCgD-ErbvlNVv5gNb7X0R3J9loEGs285xhbPIOEkMPmkesfgLXS5ejb-6svpzq7OVxB0b-88m8YJuXVXsWJhsDiST7Mui8ih509ItI7k8qVF9ZjVEfZXLvCTRHPzLlQZx-pfI1Ol5OAHOZWL2Fy6/s1353/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1162&quot; data-original-width=&quot;1353&quot; height=&quot;550&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCZ5sVghS8oFANff6z69rR3JCyhQtLdcZS5KFiMHLYZCgD-ErbvlNVv5gNb7X0R3J9loEGs285xhbPIOEkMPmkesfgLXS5ejb-6svpzq7OVxB0b-88m8YJuXVXsWJhsDiST7Mui8ih509ItI7k8qVF9ZjVEfZXLvCTRHPzLlQZx-pfI1Ol5OAHOZWL2Fy6/w640-h550/image.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. Headroom&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm5yC3usUb1EWtlNwY_yTnTP0F-fpX8wDaMY51I6Pv3GY8Lab9p_4sFZVa1CT3DIVKKKFrgWzhSak54eVFJBMfyt0GV6oFtuO2BI-yjUWbqnui6qD5Okz9oWEoyztPrt6zSpFWOThT0yQAtY3D7W-lfQfD525vLsM9QDgi70RbZlnhLt95ELBh6ihrYgA_/s1746/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.19.17.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1332&quot; data-original-width=&quot;1746&quot; height=&quot;488&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjm5yC3usUb1EWtlNwY_yTnTP0F-fpX8wDaMY51I6Pv3GY8Lab9p_4sFZVa1CT3DIVKKKFrgWzhSak54eVFJBMfyt0GV6oFtuO2BI-yjUWbqnui6qD5Okz9oWEoyztPrt6zSpFWOThT0yQAtY3D7W-lfQfD525vLsM9QDgi70RbZlnhLt95ELBh6ihrYgA_/w640-h488/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.19.17.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;



&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://github.com/chopratejas/headroom&quot; target=&quot;_blank&quot;&gt;Headroom&lt;/a&gt;은 AI 코딩 에이전트가 LLM에 전달하는 컨텍스트를 압축해 토큰 사용량을 줄이기 위한 오픈소스 프로젝트다. 공식 README에서는 Headroom을 다음 문장으로 설명한다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Compress everything your AI agent reads.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Same answers, fraction of the tokens.&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;



&lt;p class=&quot;p1&quot; style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;즉, AI 에이전트가 읽는 파일, 로그, tool output, RAG chunk, 대화 이력 등을 LLM에 전달하기 전에 압축해서, 가능한 한 같은 답변을 더 적은 토큰으로 얻는 것이 목표다.&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;



&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Codex 같은 AI 코딩 에이전트는 사용자의 질문만 LLM에 보내지 않는다. 문제 해결을 위해 소스 파일, 오류 로그, 터미널 명령 결과, git diff, 프로젝트 문서, 이전 대화 이력 등을 함께 전달한다. 이 정보들이 모두 컨텍스트가 되고, 컨텍스트가 길어질수록 토큰 사용량과 비용도 증가한다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;



&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Headroom은 이 지점에서 Codex와 LLM 사이에 위치하는 컨텍스트 압축 레이어로 동작한다. 기술적으로 보면 Headroom은 Codex가 LLM Provider로 요청을 보내기 전에 중간에서 요청을 받아 컨텍스트를 정리한다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;Codex가 파일을 읽거나, 터미널 명령을 실행하거나, 검색 결과와 로그를 수집하면 이 결과들은 그대로 LLM 입력에 포함될 수 있다. Headroom은 이 입력을 가로채서 중복 제거, 요약, 필터링, 구조화 같은 처리를 수행한 뒤 더 짧은 형태의 컨텍스트로 다시 구성한다.&lt;/span&gt;&lt;/p&gt;



&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUR5es21UCz02uPWRVycSXjVbW0ez7-FTgW72_bnTagHtQsYmXI89lq-klb2uhrmdknUTjGG3tlJ0qrTPOYt0M3nz5qS8fylfRJvGaq-1KRCdxuIoOUvhoIbjmkRFszR4PRhyb5sl_lIja_xquWcIFpv06tutDuupoCTwGDM5q_dw_HoREt8WDI6cnsWJC/s1536/image.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUR5es21UCz02uPWRVycSXjVbW0ez7-FTgW72_bnTagHtQsYmXI89lq-klb2uhrmdknUTjGG3tlJ0qrTPOYt0M3nz5qS8fylfRJvGaq-1KRCdxuIoOUvhoIbjmkRFszR4PRhyb5sl_lIja_xquWcIFpv06tutDuupoCTwGDM5q_dw_HoREt8WDI6cnsWJC/w640-h426/image.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;아키텍처 및 동작방식&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 구조에서 중요한 점은 Headroom이 최종 답변을 직접 생성하는 모델이 아니라는 것이다. Headroom은 Codex와 LLM 사이에서 입력 컨텍스트를 최적화하는 계층이다. 즉, “무엇을 답할 것인가”는 여전히 LLM이 담당하고, Headroom은 “LLM에게 어떤 정보를 얼마나 효율적으로 전달할 것인가”를 담당한다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;





&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예를 들어 Codex가 테스트 실패 원인을 찾기 위해 수천 줄의 로그와 여러 개의 소스 파일을 읽었다고 가정해보자. 이 정보를 그대로 LLM에 보내면 토큰 사용량이 크게 증가한다. Headroom은 이 중 반복되는 stack trace, 중복 로그, 관련성이 낮은 출력 등을 줄이고, 오류 원인 분석에 필요한 핵심 정보를 중심으로 컨텍스트를 다시 구성한다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot;&gt;



&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyG80jcruYctV9d2vyBtZTuUCset9Sr8nrwTeg79X_y9CF6xnxWlPoESEqtfaEZ_ZfDJ3aDk-qohhAAG48lI-rwOCLPciOIdH-U2FEJNqA4gG55gT6e5_MmyNzSX4M433KOohGp4apSIOIILFNZrM1rhwqZeWi2k3Nm-GN7vkyYQkMcYDvNIanpvj_ly0-/s1536/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyG80jcruYctV9d2vyBtZTuUCset9Sr8nrwTeg79X_y9CF6xnxWlPoESEqtfaEZ_ZfDJ3aDk-qohhAAG48lI-rwOCLPciOIdH-U2FEJNqA4gG55gT6e5_MmyNzSX4M433KOohGp4apSIOIILFNZrM1rhwqZeWi2k3Nm-GN7vkyYQkMcYDvNIanpvj_ly0-/w640-h426/image.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;따라서 Headroom의 기술적 역할은 단순히 텍스트 길이를 줄이는 것이 아니다. 컨텍스트 안에서 의미 있는 정보는 유지하고, 반복되거나 덜 중요한 정보는 줄여서 LLM이 더 적은 토큰으로 문제를 이해하도록 돕는 것이다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;



&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 때문에 Headroom은 특히 다음과 같은 작업에서 효과를 기대할 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;긴 빌드 로그 분석&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트 실패 원인 추적&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;대형 코드베이스의 여러 파일 분석&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;큰 git diff 검토&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;검색 결과가 많은 작업&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이전 대화 이력이 길게 누적된 Codex 세션&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;반대로 다음과 같은 경우라면 굳이 사용할 필요가 없다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;짧은 파일 수정&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;간단한 질문&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;작은 버그 수정&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;정확한 원문 로그 전체가 중요한 장애 분석&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보안/권한/결제/마이그레이션처럼 작은 차이가 중요한 작업&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;



&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2w6Bp5YvelcuOfRKz7SfP24c5M4fRDh7d2yZjUWFal7-2ueM4IP-z4_BAaW4fM1SZJJlhIJbrwtn3nvx-tPc18LdfIfSxDXoZH-8mIEtrgahXvml_QzzH7OUUXHBSgr3XFiM3NM_vc1q7ACvEj1EtlLAlU2eTLHKbf7DSCiPaoFf7cGYl8cz8amPfH9Wc/s1536/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2w6Bp5YvelcuOfRKz7SfP24c5M4fRDh7d2yZjUWFal7-2ueM4IP-z4_BAaW4fM1SZJJlhIJbrwtn3nvx-tPc18LdfIfSxDXoZH-8mIEtrgahXvml_QzzH7OUUXHBSgr3XFiM3NM_vc1q7ACvEj1EtlLAlU2eTLHKbf7DSCiPaoFf7cGYl8cz8amPfH9Wc/w640-h426/image.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. 설치하기&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 14.85px;&quot;&gt;&amp;nbsp;&lt;b&gt;환경&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;background-color: white; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;&quot;&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;font-size: 14.85px;&quot;&gt;OS : macOS 15.3.1 (24D70)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI Coding Agent : Codex&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-size: 14.85px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;



&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Headroom은 Codex 앱에 직접 붙는 도구라기보다, &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;Codex CLI를 감싸거나 proxy로 연결하는 도구이다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;공식 README도 Headroom을 “AI agent가 읽는 tool output, logs, RAG chunks, files, conversation history를 LLM에 도달하기 전에 압축하는 도구”로 설명하고, Codex 같은 coding agent와 함께 사용할 수 있다고 안내하고 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;먼저 Codex CLI 와 파이선이 설치되었는지를 아래 명령으로 확인한다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;python3 --version&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;pip3 --version&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;which codex&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;codex --version&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHle8Li-EdU4Ty8fDdnzf_aH4eCOOMaAx89LmpPLruVjbkjdJjXiHW8AUm-5kYaPBFPZx9fuEU5-Zdpb_ZNXtos1MM-W613vrHvggm6bMvkqb-AsUjcjc_fPW2txFiAIZ3J9-OH-kR8e4zJ5b6fWJGKuzGioUNoOSsrKyoe7EtADAlcGkqt8PA0j9N5n-L/s1670/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-15_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_54_11.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;222&quot; data-original-width=&quot;1670&quot; height=&quot;86&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHle8Li-EdU4Ty8fDdnzf_aH4eCOOMaAx89LmpPLruVjbkjdJjXiHW8AUm-5kYaPBFPZx9fuEU5-Zdpb_ZNXtos1MM-W613vrHvggm6bMvkqb-AsUjcjc_fPW2txFiAIZ3J9-OH-kR8e4zJ5b6fWJGKuzGioUNoOSsrKyoe7EtADAlcGkqt8PA0j9N5n-L/w640-h86/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-15_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_54_11.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;참고로 Codex 앱만 사용하고 있더라도 Codex CLI 설치는 별도이다.&amp;nbsp; 설치는 아래와 같은 명령으로 진행한다. (OpenAI 공식 문서 기준)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic Coding;&quot;&gt;curl -fsSL https://chatgpt.com/codex/install.sh | sh&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;다음으로 python 패키지 형태로 headroom 을 설치한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic Coding;&quot;&gt;python3 -m pip install -U &quot;headroom-ai[all]&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic; font-weight: normal;&quot;&gt;3. 사용하기&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;설치가 완료 되었다면 아래 명령으로 실행할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;headroom wrap codex&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;성능 리포트 기능을 사용하여 컨텍스트 압축이 효과가 있는지를 확인해 볼 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;headroom perf&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7nY8DYHSgmBviQcqV8ZFVdUBP4v79ui8nnajZxOjrEBamlyRfYPNjA9kBL4TJ7t06yArJhMASLw4xXRUBpKkRo9OaDcFoMGo27x7p9CT2U9stlLRhJxORyDa51ZhKkxyhI_CZ1TZXQ2WmBgO5VGoNDfjhJbla4gkOMjkPxlWmB19gIocTGFeo6SRCUBKM/s1390/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-15_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_07_57.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1156&quot; data-original-width=&quot;1390&quot; height=&quot;532&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7nY8DYHSgmBviQcqV8ZFVdUBP4v79ui8nnajZxOjrEBamlyRfYPNjA9kBL4TJ7t06yArJhMASLw4xXRUBpKkRo9OaDcFoMGo27x7p9CT2U9stlLRhJxORyDa51ZhKkxyhI_CZ1TZXQ2WmBgO5VGoNDfjhJbla4gkOMjkPxlWmB19gIocTGFeo6SRCUBKM/w640-h532/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-15_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_07_57.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;위 리포트 결과를 보면 압축후 토큰 사용량이 0 이 된점을 보아 좀 과장되었다고 생각을 하게 되었다. 또한 Retrievals 비율이 0% 인것으로 보아 패턴을 학습하고는 있지만, 그 학습된 패턴을 다시 꺼내 재사용하지는 못하고 있음을 알 수 있다. 이 결과는 사용 시간이 너무 잛아서 그런거라고 예상하고 있다.&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;좀더 긴 시간을 사용후에 확인 해보았지만&amp;nbsp; 필요할 때 원문을 꺼내 사용한 기록은 존재하지 않았다.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;아쉬운 점은 /status 을 사용해도 요금 한도부분을 확인 할 수 없었다. (추측하건데 headroom warp API 가 이를 지원하지 않아서 인것 같다.) 사용하다 갑짜기 limit 에 도달했다는 메시지를 받았다.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;headroom wrap 명령이 codex 설정을 자동으로 모델 provider , openai_base_url 정보를 수정하기 때문에 headroom 을 사용하지 않는 경우에는 unwrap 으로 다시 설정을 원복 해줘야 한다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;headroom unwrap codex&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;4. 결론&lt;/span&gt;&lt;/h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;



&lt;p class=&quot;p1&quot;&gt;개인적으로 Headroom을 사용하면서도 품질에 대한 찜찜함을 완전히 버리기는 어려웠다. 성능 리포트상으로는 토큰 절감 효과가 크게 표시되었지만, 컨텍스트를 줄인다는 것은 결국 모델에게 전달되는 정보가 줄어든다는 뜻이기도 하다. 특히 TOIN retrieval이 0%로 표시되는 상황에서는, 압축된 정보가 필요할 때 원문을 다시 꺼내 검증하는 루프가 실제로 동작하고 있는지 확신하기 어려웠다.&lt;/p&gt;&lt;/div&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/7261340206255748407/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/06/headroom-codex.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/7261340206255748407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/7261340206255748407'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/06/headroom-codex.html' title='사용기 - Headroom으로 Codex 토큰 사용량 줄이기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCZ5sVghS8oFANff6z69rR3JCyhQtLdcZS5KFiMHLYZCgD-ErbvlNVv5gNb7X0R3J9loEGs285xhbPIOEkMPmkesfgLXS5ejb-6svpzq7OVxB0b-88m8YJuXVXsWJhsDiST7Mui8ih509ItI7k8qVF9ZjVEfZXLvCTRHPzLlQZx-pfI1Ol5OAHOZWL2Fy6/s72-w640-h550-c/image.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-4111244006438370402</id><published>2026-06-12T16:01:34.347+09:00</published><updated>2026-06-15T17:31:22.814+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="CodeGraph"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="coding agent"/><title type='text'>사용기 - CodeGraph 사용하여 Codex 가 코드를 구조화된 코드 그래프로 이해하게 만들기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI 코딩 도구를 사용하면 자주 경험하는 문제는 &quot;프로젝트 구조를 파악하는 데 시간이 많이 걸린다&quot; 였다. 특히 멀티 모듈이나 대규모 코드로 구성된 프로젝트의 경우 기존 소스를 검색하여 파악하는데 많은 시간이 걸린다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;



&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://github.com/colbymchenry/codegraph&quot; target=&quot;_blank&quot;&gt;CodeGraph&lt;/a&gt; 는 소스 코드를 분석해서 코드베이스를 그래프 형태로 인덱싱하는 오픈소스 프로젝트이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;



&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0i5DYaLrV_HnTbGVOigqgSnAYj4P2ZofwDwZ_Hy2232L4lPfKXr9Fn0F_jKYh8uFgGnloXaR8GftRHyokOLxHr-1zLyeTaliWpUljoaoe2X9uQY9OvQ3amBAL-Mv94NY7kZHd0t9KImZSjwO619y0Qq7qczncYmY0jPw6kelfG2zxvcRBf2wyfNSAHJAi/s1748/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.12.35.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;968&quot; data-original-width=&quot;1748&quot; height=&quot;354&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0i5DYaLrV_HnTbGVOigqgSnAYj4P2ZofwDwZ_Hy2232L4lPfKXr9Fn0F_jKYh8uFgGnloXaR8GftRHyokOLxHr-1zLyeTaliWpUljoaoe2X9uQY9OvQ3amBAL-Mv94NY7kZHd0t9KImZSjwO619y0Qq7qczncYmY0jPw6kelfG2zxvcRBf2wyfNSAHJAi/w640-h354/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.12.35.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;



&lt;/span&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CodeGraph는 AI 코딩 에이전트가 프로젝트 소스코드를 매번 &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;Read&lt;/code&gt;로 처음부터 탐색하지 않도록, 코드베이스를 미리 인덱싱해 &lt;span class=&quot;s1&quot;&gt;코드 지식 그래프&lt;/span&gt;로 제공하는 도구다. 로컬 코드베이스를 분석해 &lt;code&gt;.codegraph/&lt;/code&gt; 디렉터리에 인덱스를 저장하고, Codex CLI, Claude Code, Cursor, Gemini CLI, Antigravity IDE 같은 AI 에이전트가 MCP를 통해 이 그래프를 조회할 수 있도록 해준다. 공식 설명에서도 CodeGraph는 &lt;code&gt;tree-sitter&lt;/code&gt; 기반으로 코드베이스를 파싱하고, 심볼·엣지·파일 정보를 SQLite/FTS5에 저장하며, MCP를 통해 AI 에이전트에 제공하는 로컬 우선 코드 인텔리전스 도구라고 설명한다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC173ihu7HOoHQhQ1HSZprWnjmBX1v4b0FNqrKCy36ZnpCAK5dAH_QZ0es2c22JXEjn7edA4N7SsSmXqRWf8-CFkEKFcZQez_XmdMGWsOwb8ez2mEckrBivwZe5RDTgIp4XH9W1zPmpJaffIQle1o6l_KealUFt10YjDbKqjxo5nvlVF6wPvseMQA6ac4S/s1536/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC173ihu7HOoHQhQ1HSZprWnjmBX1v4b0FNqrKCy36ZnpCAK5dAH_QZ0es2c22JXEjn7edA4N7SsSmXqRWf8-CFkEKFcZQez_XmdMGWsOwb8ez2mEckrBivwZe5RDTgIp4XH9W1zPmpJaffIQle1o6l_KealUFt10YjDbKqjxo5nvlVF6wPvseMQA6ac4S/w640-h426/image.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CodeGraph 는 AST(Abstract Syntax Tree) 결과를 이용하여 코드 그래프를 만들어 사용하고 있는데 관련하여 2026년 arXiv 논문 &lt;a href=&quot;https://arxiv.org/abs/2603.27277&quot; target=&quot;_blank&quot;&gt;&quot;Codebase-Memory:Tree-Sitter-Based Knowledge Graphs for LLM Code Exploration via MCP&quot;&lt;/a&gt; 에 따르면Tree-sitter 기반 코드 지식 그래프 + MCP 방식이 **토큰은 10배 적게, tool call은 2.1배 적게 사용했지만, 답변 품질은 파일 탐색형 agent 92% 대비 83%**였다고 보고한다. 즉, 그래프 기반 탐색은 효율성은 높지만, 원본 파일을 충분히 읽는 방식보다 품질이 낮아질 수 있다는 문제를 보여주고 있다. &lt;br /&gt;&lt;br /&gt;CodeGraph는 이런 품질 이슈를 “자동 정답화”로 해결하지 않고, AST 기반 그래프 + context/trace/impact + 원본 body 제공으로 사실 확인 비용을 줄이는 방식으로 완화하고 있다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwKI7c-FLv1hBVLi9zqupZR3a8K6qhWV06Da447e81DvC4DxS0X2TZAM2YNcufrDWqTLkv0KVN9Ph8wKd-F93YRnZAZXrLOS0vgORT9G3BfbbS8SZ6tDHeOtiY-YLcu45U0H141cTGIokBAN5dCKUsKDcki1Vv_gUZBVPD7Lgmts05UerV0-7HxHZAfyx/s1536/image3.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAwKI7c-FLv1hBVLi9zqupZR3a8K6qhWV06Da447e81DvC4DxS0X2TZAM2YNcufrDWqTLkv0KVN9Ph8wKd-F93YRnZAZXrLOS0vgORT9G3BfbbS8SZ6tDHeOtiY-YLcu45U0H141cTGIokBAN5dCKUsKDcki1Vv_gUZBVPD7Lgmts05UerV0-7HxHZAfyx/w640-h426/image3.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. 설치하기&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 14.85px;&quot;&gt;&amp;nbsp;&lt;b&gt;환경&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;background-color: white; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;&quot;&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;font-size: 14.85px;&quot;&gt;OS : macOS 15.3.1 (24D70)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border-color: currentcolor; border-image: initial; border-style: none; border-width: medium; border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI Coding Agent : Codex&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설치는 npm 을 사용하여 전역으로 설치하는 방식을 사용했다. (여러 프로젝트에서 사용할 수 있도록)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;npm install -g @colbymchenry/codegraph&lt;/span&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설치 이후에는 다음 명령으로 확인 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;codegraph --version&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;which codegraph&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghkAV5gZVsUkklSk3_uW5dLjnRvCg_ePp47VPSjrPe1s9UC0Cdhr6-xCYuL9YiVoJ0iNwJAMmPbhHvCaPi3sB7umCUxjSYTJdZN8dCc8HYB0iacsPmbx1DkGTP_nbS26qtchG70V4YsVqFtRUvor-34Xkl1P67sx-qbnS91Gdjt0mw1I3ZbJeqOu15nZzU/s1070/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_30_36.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;124&quot; data-original-width=&quot;1070&quot; height=&quot;74&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghkAV5gZVsUkklSk3_uW5dLjnRvCg_ePp47VPSjrPe1s9UC0Cdhr6-xCYuL9YiVoJ0iNwJAMmPbhHvCaPi3sB7umCUxjSYTJdZN8dCc8HYB0iacsPmbx1DkGTP_nbS26qtchG70V4YsVqFtRUvor-34Xkl1P67sx-qbnS91Gdjt0mw1I3ZbJeqOu15nZzU/w640-h74/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_30_36.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. AI 코딩 에이전트에 MCP 연결&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;



&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CodeGraph는 MCP 서버로 동작한다. 따라서 Codex, Claude Code, Cursor 같은 AI 코딩 도구에서 사용하려면 먼저 MCP 설정을 연결해야 한다. Codex 를 주력으로 사용하고 있어 Codex 에 MCP 로 등록했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;codegraph install&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p1&quot;&gt;



&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 명령은 현재 개발환경에 설치된 AI 에이전트를 감지하고, CodeGraph MCP 서버 설정을 자동으로 추가한다. 공식 README 기준으로 자동 설정 대상에는 Claude Code, Cursor, Codex CLI, opencode, Hermes Agent, Gemini CLI, Antigravity IDE, Kiro 등이 포함된다.&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghgvDVxbDGqkjoLyot_XdFMjN0ZM8gYUY7e-QLrQjyAezxPv3hFFwTklTLgMZWWIettxEfymjdaT1fU9WRwna7yQCmBkuV-PiX1buiUR2qcji9GnHB_01lveVSnW6pbFt0zKCtrunj0UkmBZD_yoIaQt4QA8ywa26z1IUtdB7BMJLtM3asbGR8N5qPJ38Y/s1114/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_35_59.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;394&quot; data-original-width=&quot;1114&quot; height=&quot;226&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghgvDVxbDGqkjoLyot_XdFMjN0ZM8gYUY7e-QLrQjyAezxPv3hFFwTklTLgMZWWIettxEfymjdaT1fU9WRwna7yQCmBkuV-PiX1buiUR2qcji9GnHB_01lveVSnW6pbFt0zKCtrunj0UkmBZD_yoIaQt4QA8ywa26z1IUtdB7BMJLtM3asbGR8N5qPJ38Y/w640-h226/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_35_59.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기본적으로 설치는 전역으로 설치하고 각 프로젝트 경로에서 초기화를 해주것이 좋다. (여러 프로젝트에서 사용할 수 있게)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;성공적으로 연결되었다면 아래와 같이 확인하거나 codex 도구에서 /mcp 명령으로 확인 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;grep -A 3 -B 1 &quot;codegraph&quot; ~/.codex/config.toml&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtuiBgyCMv56S-IhnL38XXXJWtFIzAXh6MFl6C7p1StMWV-gbYmEE7Cj7UL8B54bzCcscBONjk2Lovy8Sz9XhDz5ETo5LI0DYu-YadKe-OlO95tkiEYcQgvY6BoQuaL9_TnaWKs2GJI8NAkDU0E0SDtY1phW8WCZZc2YT9cOmoYOSl4u4tIcLpVB4ygxZd/s1482/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_41_47.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;150&quot; data-original-width=&quot;1482&quot; height=&quot;64&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtuiBgyCMv56S-IhnL38XXXJWtFIzAXh6MFl6C7p1StMWV-gbYmEE7Cj7UL8B54bzCcscBONjk2Lovy8Sz9XhDz5ETo5LI0DYu-YadKe-OlO95tkiEYcQgvY6BoQuaL9_TnaWKs2GJI8NAkDU0E0SDtY1phW8WCZZc2YT9cOmoYOSl4u4tIcLpVB4ygxZd/w640-h64/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_41_47.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;Codex 앱에서 /mcp 입력&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuE68rA01kjkd7oF-_c3enAsCUYtkC74IiBGbp6brMrtVG1PyOkFIGnepkFz3etddaW_wabv3sOyTn878ufGMPoDKh3Py2D80n9Cf5IuLd6xG6zxIdFKvE2hME5yZtGM603BMIoo7YMy1oXJ6cOoYse4jf0sYXwmi9S4pODLo5H5fM3LgPllTE7W-X0VFl/s1534/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_43_35.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;666&quot; data-original-width=&quot;1534&quot; height=&quot;278&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuE68rA01kjkd7oF-_c3enAsCUYtkC74IiBGbp6brMrtVG1PyOkFIGnepkFz3etddaW_wabv3sOyTn878ufGMPoDKh3Py2D80n9Cf5IuLd6xG6zxIdFKvE2hME5yZtGM603BMIoo7YMy1oXJ6cOoYse4jf0sYXwmi9S4pODLo5H5fM3LgPllTE7W-X0VFl/w640-h278/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_43_35.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;3. 로컬 프로젝트 초기화 및&amp;nbsp; 인덱스 생성&lt;/span&gt;&lt;/h3&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;로컬 프로젝트 루트로 이동하여 init 명령을 사용하여 초기화를 실행 합니다. 최초 초기화인 경우 -i 옵션을 사용하여 코드 분석 인덱싱까지 함께 진행하는 것이 일반적이다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;codegraph init -i&lt;/span&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlmAxWINGlSO_WohZRh3piLyqgAJnvmoLK0pmMMDnlQ4thgIt69vLHi5ZWvmwUEW2X-6-mxcoNB8xbq4vIAjMA_nIPooOBJ-JvQQsAzayKED47RfWILXDYyUfLcQDSfan-DA9lJLHr5nVVDARahTa5C8MHPbZGEw7yqlzLAuRRnCAYjcNUO5IT6bUT-KMs/s1256/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_3_06_12.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;430&quot; data-original-width=&quot;1256&quot; height=&quot;220&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlmAxWINGlSO_WohZRh3piLyqgAJnvmoLK0pmMMDnlQ4thgIt69vLHi5ZWvmwUEW2X-6-mxcoNB8xbq4vIAjMA_nIPooOBJ-JvQQsAzayKED47RfWILXDYyUfLcQDSfan-DA9lJLHr5nVVDARahTa5C8MHPbZGEw7yqlzLAuRRnCAYjcNUO5IT6bUT-KMs/w640-h220/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_3_06_12.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코드가 추가 되거나 수정되면 index 명령을 사용하여 인덱스를 갱신한다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;codegraph index&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;status 명령으로 초기화 또는 인덱싱 상태를 확인할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;codegraph status&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhilrvyvDAywnOFVgFgjhZL95boyLvqVAKCCoHNWMCAyDYA_FAb5ghbWkG4DDrwhaJdwHkTni-GGry4lEgJbOKwq5NyrmGBwMpgru_3nsIAtXMKMo1GnKJwDymOIyGpWBsklmtH0RBTehD2r7QWusiZovKqUPwCK-b_x5TFk76YTW0VrpT4Xj4cIGGa32mq/s1144/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_3_03_29.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1084&quot; data-original-width=&quot;1144&quot; height=&quot;606&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhilrvyvDAywnOFVgFgjhZL95boyLvqVAKCCoHNWMCAyDYA_FAb5ghbWkG4DDrwhaJdwHkTni-GGry4lEgJbOKwq5NyrmGBwMpgru_3nsIAtXMKMo1GnKJwDymOIyGpWBsklmtH0RBTehD2r7QWusiZovKqUPwCK-b_x5TFk76YTW0VrpT4Xj4cIGGa32mq/w640-h606/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-06-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_3_03_29.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;4. 사용 방법&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGOd2Up2IpxDPJYIqAqJGLx7PFQvEWH_ij3MLItHBAjhi0WPQJ_Setc8NuebWFI4mYSobDbP_2182l3W8seh5L_h38DBJBXD04RIvR-CWcARPSCpC0yI2YCWu3xF5db0IS6O3sYKHE8pUfVxR-6SoaKZcIjwJLMNpCI21UiEFtOZkjUBEvo-_OT3wr-uL8/s1536/image2.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGOd2Up2IpxDPJYIqAqJGLx7PFQvEWH_ij3MLItHBAjhi0WPQJ_Setc8NuebWFI4mYSobDbP_2182l3W8seh5L_h38DBJBXD04RIvR-CWcARPSCpC0yI2YCWu3xF5db0IS6O3sYKHE8pUfVxR-6SoaKZcIjwJLMNpCI21UiEFtOZkjUBEvo-_OT3wr-uL8/w640-h426/image2.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOY0ZCIcP4vq_uYilL2hL7vni74UmT0CUKuZm87AimxFKRCM6oQ4tRnii6e7g5IZI1bRnQAdhRc9wJgtg372Rx0Prx9RtRUtBSFdh1UnSmPAgy2mQmD7F-1CRfOSDHtX6h4WAQlR2QEs777QUbcRYos0p33wWNrzoHL5ZzYPBZ7LNI1gUEmhQ__Zh2R7OM/s1536/image4.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOY0ZCIcP4vq_uYilL2hL7vni74UmT0CUKuZm87AimxFKRCM6oQ4tRnii6e7g5IZI1bRnQAdhRc9wJgtg372Rx0Prx9RtRUtBSFdh1UnSmPAgy2mQmD7F-1CRfOSDHtX6h4WAQlR2QEs777QUbcRYos0p33wWNrzoHL5ZzYPBZ7LNI1gUEmhQ__Zh2R7OM/w640-h426/image4.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;clear: both; text-align: left;&quot;&gt;5. 사용 후기&lt;/h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;CodeGraph 을 코덱스에 사용한 결과 코드 검색 속도는 아주 빨라졌다. 작업 하기 전에 관련 코드를 검색하는 작업을 하는 것이 일반적인데 codegraph 을 사용하여 검색하고 해당 파일들을 기준으로 수정작업을 진행하기 때문에 상당한 속도 개선은 있는 것 같다.&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;추가로 CodeGraph 는 아주 빠른 속도록 업데이트 되고 있기 때문에 다음과 같이 설치된 버전과 최신 버전을 확인해서&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;echo &quot;installed: $(codegraph --version)&quot;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;echo &quot;latest:&amp;nbsp; &amp;nbsp; $(npm view @colbymchenry/codegraph version)&quot;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;최신 버전으로 업데이트 할 수 있다. (전역 설치의 경우에)&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;blockquote&gt;npm update -g @colbymchenry/codegraph&lt;/blockquote&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;CodeGraph 버전을 업데이트했다면 필수는 아니지만 최신 분석 로직 반영을 위해서 index 을 다시 실행한는 것이 좋다.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;



&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p class=&quot;p1&quot;&gt;codegraph index&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;codegraph status&lt;/p&gt;&lt;/blockquote&gt;&lt;p class=&quot;p1&quot;&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/4111244006438370402/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/06/codegraph-codex.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/4111244006438370402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/4111244006438370402'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/06/codegraph-codex.html' title='사용기 - CodeGraph 사용하여 Codex 가 코드를 구조화된 코드 그래프로 이해하게 만들기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0i5DYaLrV_HnTbGVOigqgSnAYj4P2ZofwDwZ_Hy2232L4lPfKXr9Fn0F_jKYh8uFgGnloXaR8GftRHyokOLxHr-1zLyeTaliWpUljoaoe2X9uQY9OvQ3amBAL-Mv94NY7kZHd0t9KImZSjwO619y0Qq7qczncYmY0jPw6kelfG2zxvcRBf2wyfNSAHJAi/s72-w640-h354-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-06-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.12.35.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-4371551475317599959</id><published>2026-05-06T09:54:57.829+09:00</published><updated>2026-05-08T13:53:46.583+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="chatgpt"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="생성형 AI 코딩"/><title type='text'>사용기 - ChatGPT 에서 설계 하고 개발은 Codex 에서</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Codex 와 대화 하면서 구체적인 설계를 진행하는 것 보다 ChatGPT 에서 설계를 하고 대화 결과를 코덱스에 공유하여 구현을 하는 것을 테스트 해보았다. 실험의 목적은 코덱스의 토큰 사용량을 최소화하기 위한 경제성이다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;모델은 5.5&lt;span&gt;&amp;nbsp;Pro 을 사용하였고 대화를 통하여 원하는 설계를 구체화 했다. Codex 전달용 작업 계획을 요청했지만 한번에 복사하여 사용하기는 어려운 점이 있었다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoTXIgpA67E0ad0TKvC2ZZwm5tmeDoD0rI_ynI_5N8wUUVTax8zaMcCcHzOLUrfp9uKIqQ5dvGDQP2rWZ96Ip1Bk89KlNhVgz0kWsssC9i1BwNTjfnJj_IUCqdrGIPgRvOooF9KA5GJxjQSjUXNklh_iJC9YGF6vQ7SuaO2OxTlsPzyYPs9WT-CWkEJxGJ/s2094/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.49.21.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1746&quot; data-original-width=&quot;2094&quot; height=&quot;534&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoTXIgpA67E0ad0TKvC2ZZwm5tmeDoD0rI_ynI_5N8wUUVTax8zaMcCcHzOLUrfp9uKIqQ5dvGDQP2rWZ96Ip1Bk89KlNhVgz0kWsssC9i1BwNTjfnJj_IUCqdrGIPgRvOooF9KA5GJxjQSjUXNklh_iJC9YGF6vQ7SuaO2OxTlsPzyYPs9WT-CWkEJxGJ/w640-h534/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.49.21.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;대화에 대한 공유 링크를 생성하고 링크를 Codex 에 전달하여 진행을 시도하였다. 다만 이경우 전체 대화 내용을 읽어서 작업 계획을 수립하기 때문에 진행 과정의 대화 까지 읽어 들여 비효율적이며 토큰을 낭비하게 된다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgghOqAiRHPpXTxCTM9uFiM6NwCaeAc4yOpKgL-0d3YQS0dEwazcON_SyYefkFOzllQvBZMslFU1VDHJKwSeJ3V3lXLuSQsEe_HgobCUVqfpf5AdyyVM9dik56Y25Sczp1TagOH9Mt9lDeOxrTLXnpthnEkKP7UG2Jdn2fmHymzvknLA6V1EXbTM9oa0jLy/s1946/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.10.22.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1418&quot; data-original-width=&quot;1946&quot; height=&quot;466&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgghOqAiRHPpXTxCTM9uFiM6NwCaeAc4yOpKgL-0d3YQS0dEwazcON_SyYefkFOzllQvBZMslFU1VDHJKwSeJ3V3lXLuSQsEe_HgobCUVqfpf5AdyyVM9dik56Y25Sczp1TagOH9Mt9lDeOxrTLXnpthnEkKP7UG2Jdn2fmHymzvknLA6V1EXbTM9oa0jLy/w640-h466/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.10.22.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;좀더 효과적은 작업 내용 전달을 위해서 ChatGPT 대화에서 최종 결과에 대한 md 파일 생성을 요청하여 Codex 에 공유하여 작업을 진행하게 했다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlkECGiJMN7AsmXNPU47aZawWgYR9vXRO08IQ1gtD5FGrQA7o6Bux4Uy31Dr4h6U_C0q8k4gYWX86lDlHHaleGT41ys5Hy6PQgyavqmJm6r_re6qEFlkodFeawDZwW3QZ7mxSzLW94NXwsFkfCPLV1PrUCcVzWsDeG7AVAbJ9ulDu9URTe6KkkyAJ31ie-/s2068/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.07.13.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1392&quot; data-original-width=&quot;2068&quot; height=&quot;430&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlkECGiJMN7AsmXNPU47aZawWgYR9vXRO08IQ1gtD5FGrQA7o6Bux4Uy31Dr4h6U_C0q8k4gYWX86lDlHHaleGT41ys5Hy6PQgyavqmJm6r_re6qEFlkodFeawDZwW3QZ7mxSzLW94NXwsFkfCPLV1PrUCcVzWsDeG7AVAbJ9ulDu9URTe6KkkyAJ31ie-/w640-h430/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.07.13.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOlqHpc2JgdUCTzTXKVWXSODmPqyQpA_LKnynHKcvnIu5pcQKpU4sNHlBmRg7M4J0Aep1BgM5FFCSc_RZD03yKQr7e7Vy5vfkncROjsYf3kQSsQvfIBsYF8st5Nd1aa__vSOrHMgQUGbWlCCBNb_5oIu_jF47-IJ4xYPnUYiF7K8pFsn1rZ-rj4qWvofNJ/s1712/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.14.02.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1426&quot; data-original-width=&quot;1712&quot; height=&quot;534&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOlqHpc2JgdUCTzTXKVWXSODmPqyQpA_LKnynHKcvnIu5pcQKpU4sNHlBmRg7M4J0Aep1BgM5FFCSc_RZD03yKQr7e7Vy5vfkncROjsYf3kQSsQvfIBsYF8st5Nd1aa__vSOrHMgQUGbWlCCBNb_5oIu_jF47-IJ4xYPnUYiF7K8pFsn1rZ-rj4qWvofNJ/w640-h534/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.14.02.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;생성된 md 파일을 통한 작업 지시의 장점은 md 파일 계획이 1차, 2차 구현으로 구분되어 있는 경우 Codex 는 1차 구현만 진행하게 되는데 작업이 완료된 이후에 다시 2차 를 구현하도록 지시할 수 있다는 점이다. (&lt;/span&gt;또한 미리 작업 계획 초안을 검토하는 것이 용이)&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt2qfgGMSjXLrBjdoo27w3Swq4nf8FoMVfR5Hdv9kczNdykCUc5L6LLyZE178AL_nYsZ8VeC6eMhV7JXQbhDANLpx01EIVFk2H8TBjP0tpsmwBeHjnmAKejoiciUe9XjX3A4LxR9IyUs5qXT6ZVfy8dC6MguxUWDHFDTwby1PyrezDiWfHDXnVBpC9dFNR/s1666/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.16.48.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1430&quot; data-original-width=&quot;1666&quot; height=&quot;550&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt2qfgGMSjXLrBjdoo27w3Swq4nf8FoMVfR5Hdv9kczNdykCUc5L6LLyZE178AL_nYsZ8VeC6eMhV7JXQbhDANLpx01EIVFk2H8TBjP0tpsmwBeHjnmAKejoiciUe9XjX3A4LxR9IyUs5qXT6ZVfy8dC6MguxUWDHFDTwby1PyrezDiWfHDXnVBpC9dFNR/w640-h550/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.16.48.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmnn_WfIVffYr_g1DvxpRu3SNCbG-F9A02XSAYi5_uUrnxXUVRR8x-WW5k7JXO04TZB4EhWymDww3udh2j3LlaHOr2Aq_RI0wP12SBWw0CQSN3wGI7LbBLwBNpjuzEHKYLiguQyWELHN8CwoB9asrM2CP3XzV_LliLBo4UlrtAIwcuYLD1JxiITeV8J_oW/s1536/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmnn_WfIVffYr_g1DvxpRu3SNCbG-F9A02XSAYi5_uUrnxXUVRR8x-WW5k7JXO04TZB4EhWymDww3udh2j3LlaHOr2Aq_RI0wP12SBWw0CQSN3wGI7LbBLwBNpjuzEHKYLiguQyWELHN8CwoB9asrM2CP3XzV_LliLBo4UlrtAIwcuYLD1JxiITeV8J_oW/w640-h426/image.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이번 작업을 통해 느낀 점은 AI 코딩에서 중요한 것은 단순히 좋은 모델을 사용하는 것이 아니라,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;AI가 안정적으로 이해하고 작업할 수 있도록&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;작업 자체를 구조화하는 것&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;이라는 점이다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특히 ChatGPT에서 충분히 설계와 정리를 수행한 뒤, 최종 내용을 md 기반 작업 계획으로 압축하여 Codex에 전달하는 방식은 예상보다 효율적이었다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;공유 링크 방식은 전체 대화 흐름까지 모두 포함되므로 불필요한 컨텍스트 증가와 토큰 낭비가 발생하기 쉽다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;반면 md 기반 작업 문서는:&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;작업 범위를 제한하고&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;구현 단계를 분리하며&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;필요한 정보만 압축 전달하고&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;검토 가능한 형태로 유지할 수 있다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결국 AI 시대의 개발 생산성은 “얼마나 긴 프롬프트를 작성했는가”보다,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;AI가 일하기 좋은 구조와 흐름을 어떻게 설계했는가&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;에 더 크게 좌우된다고 느꼈다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/4371551475317599959/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/05/chatgpt.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/4371551475317599959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/4371551475317599959'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/05/chatgpt.html' title='사용기 - ChatGPT 에서 설계 하고 개발은 Codex 에서'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoTXIgpA67E0ad0TKvC2ZZwm5tmeDoD0rI_ynI_5N8wUUVTax8zaMcCcHzOLUrfp9uKIqQ5dvGDQP2rWZ96Ip1Bk89KlNhVgz0kWsssC9i1BwNTjfnJj_IUCqdrGIPgRvOooF9KA5GJxjQSjUXNklh_iJC9YGF6vQ7SuaO2OxTlsPzyYPs9WT-CWkEJxGJ/s72-w640-h534-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-05-06%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.49.21.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-5805214727800154494</id><published>2026-04-30T09:45:55.405+09:00</published><updated>2026-05-03T09:03:13.325+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="Feedback Loop Engineering"/><category scheme="http://www.blogger.com/atom/ns#" term="Harness Engineering"/><category scheme="http://www.blogger.com/atom/ns#" term="생성형 AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="코덱스"/><category scheme="http://www.blogger.com/atom/ns#" term="하네스엔지니어링"/><title type='text'>사용기 - 프롬프트는 시작이고, AI는 환경에서 일한다</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Feedback Loop Engineering은 2026년 1월 다니엘 데멜(Daniel Demmel)이 AI 코딩 에이전트의 품질을 높이는 핵심을 “검증 가능한 반복 구조”로 설명하면서 제시한 개념이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhcwmibrPSGiaB6AJzDf5okdo6RxIeT0i1AEH-OcwRk1u3ltYzQJUnr41P9RjAQ0XGbIUQTzF3ZN0gs_kF5H1_6NHQlbsV5IydoKevdtDfJnB-Mb6pypQ_yBQ0wxdzDRbTWBCu7kKeM1RPilrqYAd6XuSJvMX9xgTqVenXrt29L66mBZGg8pkUH_N_n0_c-&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;502&quot; data-original-width=&quot;920&quot; height=&quot;350&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhcwmibrPSGiaB6AJzDf5okdo6RxIeT0i1AEH-OcwRk1u3ltYzQJUnr41P9RjAQ0XGbIUQTzF3ZN0gs_kF5H1_6NHQlbsV5IydoKevdtDfJnB-Mb6pypQ_yBQ0wxdzDRbTWBCu7kKeM1RPilrqYAd6XuSJvMX9xgTqVenXrt29L66mBZGg8pkUH_N_n0_c-=w640-h350&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이후 2026년 2월 OpenAI는 Codex 활용 사례를 통해 하네스 엔지니어링(Harness Engineering)이라는 표현을 사용하며, 에이전트가 안정적으로 일할 수 있도록 실행 환경·검증 체계·피드백 구조를 설계하는 접근을 소개했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjjOHBuyOqYICzy-VxSexREGNudaNe6MXYxdi6tQQWpKIoIH4N6ipxXryq9x_ybYB5Qo5bFQxqQW2IT1KVh7QWgjjCIzvBzYFaGA5hitzfE2d8pIGollDZ0KmJbDwi1x0N34XREtrkAuy50urAYEVVSuqjrQ_Dpsj0bA69RElrEIM4-l9BfdqdQNkH23n1z&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;427&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEjjOHBuyOqYICzy-VxSexREGNudaNe6MXYxdi6tQQWpKIoIH4N6ipxXryq9x_ybYB5Qo5bFQxqQW2IT1KVh7QWgjjCIzvBzYFaGA5hitzfE2d8pIGollDZ0KmJbDwi1x0N34XREtrkAuy50urAYEVVSuqjrQ_Dpsj0bA69RElrEIM4-l9BfdqdQNkH23n1z&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;두 개념은 별개라기보다, Feedback Loop Engineering이 “무엇을 반복해야 하는가”를 설명하고 하네스 엔지니어링(Harness Engineering)이 “그 반복이 가능하도록 어떤 환경을 설계해야 하는가”를 설명한다고 볼 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;많은 사람들이 AI 코딩 에이전트를 잘 사용하는 방법은 “프롬프트를 잘 쓰는 것”이라고 생각한다.&lt;br /&gt;하지만 최근 흐름은 다르다.  “스스로 검증하고 개선할 수 있는 구조를 만드는 것”이다.&lt;br /&gt;&lt;br /&gt;프롬프트 중심에서는 결과가 프롬프트 품질에 크게 의존하며 사람이 계속 개입해야 한다. Feedback Loop Engineering은 완전히 다른 방향을 제시한다. AI가 스스로 결과를 개선하는 구조를 통하여, 결과 품질이 프롬프트가 아니라 테스트와 검증에 의해 결정되도록 만든다. 이러한 구조에서는 사람이 모든 과정을 직접 통제할 필요가 없다. AI는 실행 결과와 오류를 기반으로 스스로 수정하고, 반복적으로 품질을 높여간다.&lt;br /&gt;&lt;br /&gt;결국 중요한 것은 더 정교한 질문이 아니라, 잘못된 결과를 빠르게 발견하고 수정할 수 있는 피드백 루프를 설계하는 것이다.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgl3KwPsxboNkYNfnJBx2IaMLGOMkoDXcPtsxpdUzolmR4zTH5a-0z5NRcSYYPgvHZ0oc6dhzwXOnFWZt3i5bWxBWhiH3jwQ1LuQvct7Uw07SIKR35ctAcJuh2cCVV76uoDi7EgkcTY9voinKCTTTaCzm1TGxNt8lUMiAgzH843Vbrp-5NVYwtcQh1bQ6rF&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgl3KwPsxboNkYNfnJBx2IaMLGOMkoDXcPtsxpdUzolmR4zTH5a-0z5NRcSYYPgvHZ0oc6dhzwXOnFWZt3i5bWxBWhiH3jwQ1LuQvct7Uw07SIKR35ctAcJuh2cCVV76uoDi7EgkcTY9voinKCTTTaCzm1TGxNt8lUMiAgzH843Vbrp-5NVYwtcQh1bQ6rF=w640-h426&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;



&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결정적으로 최근 Codex에서 지원하기 시작한 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;“Computer Use”, “Browser Use” 기능을 직접 경험하면서&lt;/b&gt;&lt;/span&gt; 생각이 완전히 바뀌었다.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그동안은 좋은 프롬프트, 정교한 스킬, 다양한 서브에이전트를 만드는 것이 핵심이라고 생각했다.&lt;br /&gt;
하지만 실제로는 전혀 다른 결과를 보게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;단순한 명령만으로도&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트 후 수정하고&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버를 재시작하고&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;브라우저에서 직접 화면을 확인하고&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트 결과를 바탕으로 다시 수정하는&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p class=&quot;p4&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;b&gt;전체 작업 흐름을 AI가 스스로 수행하는 경험&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;을 하게 되었다.&amp;nbsp;&lt;/span&gt;이 과정에서 느낀 것은 명확했다.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p4&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;중요한 것은 프롬프트가 아니라 “일을 할 수 있는 환경”이었다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;프롬프트를 아무리 잘 작성해도 AI가 실행하고, 확인하고, 실패를 인지하고, 다시 수정할 수 없다면&lt;br /&gt;
결국 사람이 계속 개입해야 한다. 반대로, 환경만 제대로 갖추어지면 아주 간단한 명령만으로도 AI는 스스로 작업을 이어가고 결과를 개선해 나간다.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p5&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 경험은 정말 충격적이었다.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf13T2KkJ33Mqi7c5Xhd2fsLofT6Q1ZcY2eTF8VcwaErqK-JeOTajLhyphenhyphen16xF1L0zTAPnm1GKkD7ouudeH4-idIo0qQPjXmAO7WWiFxGNvpF_FHs-hntkiDqKx9S9AjASQD324KeY_vTeIMgs7KsnOaV-VT8Uw9MNfNioGYZuxXuwNeCpG9SbJDi92EBTJG/s2364/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_27_48.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1652&quot; data-original-width=&quot;2364&quot; height=&quot;448&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf13T2KkJ33Mqi7c5Xhd2fsLofT6Q1ZcY2eTF8VcwaErqK-JeOTajLhyphenhyphen16xF1L0zTAPnm1GKkD7ouudeH4-idIo0qQPjXmAO7WWiFxGNvpF_FHs-hntkiDqKx9S9AjASQD324KeY_vTeIMgs7KsnOaV-VT8Uw9MNfNioGYZuxXuwNeCpG9SbJDi92EBTJG/w640-h448/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_27_48.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: x-small;&quot;&gt;에이전트가 테스트하고 수정하고 벡엔트 파트 작업는 이슈로 등록&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzReW_d6oPIAh_EY0kGTYr0vszMRwbaDMVG7ZtkpTQE89i5DTR_Rqq4GnBj3GnfkRuVGANs0Ub6KSvzQDXrFUlWyqy0NhqR60JhUp9thdUdHI-Dpjc4gv38dasqVKAhKzyWhRuwA4Tir7aHZOeXwWVfJOjO4Tmd7L8YSXhr419vo6uIV4zg73gdbIW1PS_/s1850/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_32_21.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1484&quot; data-original-width=&quot;1850&quot; height=&quot;514&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzReW_d6oPIAh_EY0kGTYr0vszMRwbaDMVG7ZtkpTQE89i5DTR_Rqq4GnBj3GnfkRuVGANs0Ub6KSvzQDXrFUlWyqy0NhqR60JhUp9thdUdHI-Dpjc4gv38dasqVKAhKzyWhRuwA4Tir7aHZOeXwWVfJOjO4Tmd7L8YSXhr419vo6uIV4zg73gdbIW1PS_/w640-h514/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_32_21.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: x-small;&quot;&gt;에이전트가 이슈를 확인해서 처리하고 서버를 재시작해서 확인&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;



&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;결국 중요한 것은 질문을 잘하는 능력이 아니라,&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;AI가 스스로 실행하고 검증하며 반복할 수 있도록&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;프로젝트와 환경을 설계하는 것이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiMF_9GrobAcWrerHb823ferke5uLbu7LRgXaGMV3e4cWbouLDqxIjzlQFIRrOme4YCcbyO-XIs-LWrEfAmQRssx2UTQWeWQhUq078ldJVeMxy98XKgdyjZ50mZcGHRLF-CCOZ76_XUkFIfREiUipRDE4rMUmDJVeo6xEotbr-6vzkOgZkJwEnP1PA66lPS&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;427&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiMF_9GrobAcWrerHb823ferke5uLbu7LRgXaGMV3e4cWbouLDqxIjzlQFIRrOme4YCcbyO-XIs-LWrEfAmQRssx2UTQWeWQhUq078ldJVeMxy98XKgdyjZ50mZcGHRLF-CCOZ76_XUkFIfREiUipRDE4rMUmDJVeo6xEotbr-6vzkOgZkJwEnP1PA66lPS&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/5805214727800154494/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/04/ai.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/5805214727800154494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/5805214727800154494'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/04/ai.html' title='사용기 - 프롬프트는 시작이고, AI는 환경에서 일한다'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEhcwmibrPSGiaB6AJzDf5okdo6RxIeT0i1AEH-OcwRk1u3ltYzQJUnr41P9RjAQ0XGbIUQTzF3ZN0gs_kF5H1_6NHQlbsV5IydoKevdtDfJnB-Mb6pypQ_yBQ0wxdzDRbTWBCu7kKeM1RPilrqYAd6XuSJvMX9xgTqVenXrt29L66mBZGg8pkUH_N_n0_c-=s72-w640-h350-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-8585761506371046793</id><published>2026-04-08T14:04:00.001+09:00</published><updated>2026-04-08T14:04:33.552+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 기반 개발"/><category scheme="http://www.blogger.com/atom/ns#" term="Sycophancy"/><category scheme="http://www.blogger.com/atom/ns#" term="교차 검증"/><category scheme="http://www.blogger.com/atom/ns#" term="기술적 근거 확인"/><category scheme="http://www.blogger.com/atom/ns#" term="반대 질문"/><title type='text'>AI는 왜 사용자를 잘못된 확신으로 이끄는가 — Sycophancy 논문에서 본 대화형 AI 의 위험</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://arxiv.org/pdf/2602.19141&quot; target=&quot;_blank&quot;&gt;Sycophantic Chatbots Cause Delusional Spiraling, Even in Ideal Bayesians&lt;/a&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;최근 공개된 &lt;em&gt;Sycophantic Chatbots Cause Delusional Spiraling, Even in Ideal Bayesians 논문은 &amp;nbsp;ChatGPT와 같은 대화형 AI가 가질 수 있는 구조적 위험을 설명한다. 이 논문이 말하는 핵심은 단순하다.&lt;/em&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;em&gt;&lt;/em&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI의 위험은 단지 틀린 답을 하는 데만 있지 않다. 사용자의 현재 믿음을 반복적으로 정당화하면서 잘못된 확신을 점점 더 키울 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;여기서 핵심 개념은 비위를 맞추는 성향(sycophancy) 이다. 이는 AI가 사용자의 말에 과도하게 동조하거나, 사용자가 기대하는 방향으로 답을 맞추려는 성향을 의미한다. 사용자는 이를 친절하고 공감적인 응답으로 받아들일 수 있지만, 반복적인 대화에서는 오히려 잘못된 방향의 자기 확신을 강화하는 결과로 이어질 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예를 들어 사용자가 어떤 가설이나 해석을 제시했을 때, AI가 &lt;em&gt;“그럴 가능성이 있다”&lt;/em&gt;, &lt;em&gt;“관찰이 일관적이다”&lt;/em&gt;, &lt;em&gt;“흥미로운 해석이다”&lt;/em&gt; 와 같은 표현을 반복하면 사용자는 자신의 판단이 점차 검증되고 있다고 느끼게 된다. 문제는 이것이 단순한 대화 UX 차원의 문제가 아니라, 잘못된 판단을 스스로 강화하는 구조로 발전할 수 있다는 점이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 논문이 특히 주목할 만한 이유는 이러한 현상이 비합리적인 사용자에게만 나타나는 것이 아니라는 점이다. 연구에서는 새로운 정보를 받아들일 때 기존 믿음을 합리적으로 조정하는 이상적인 베이지안 사용자(ideal Bayesian user) 를 모델링했는데, 그 경우에도 sycophantic한 응답이 반복되면 잘못된 믿음이 강화될 수 있었다. 즉, 사용자의 논리성 여부와 관계없이 AI와의 상호작용 구조 자체가 인지적 편향을 만들어낼 수 있다는 의미다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI 기반 프로그램 개발자 입장에서 여기서 중요한 점은 할루시네이션(Hallucination, 환각)만 줄인다고 문제가 끝나지 않는다는 사실이다. 논문은 AI가 거짓말을 하지 않도록 제한한 경우도 실험했지만, 위험은 완전히 사라지지 않았다. 이유는 AI가 사실만 말하더라도 사용자의 믿음을 강화하는 사실만 선택적으로 제시할 수 있기 때문이다. 즉, 문제는 사실 여부뿐 아니라 어떤 정보를 선택하고 어떤 정보를 제외하는가에도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI를 활용해 개발할 때는 몇 가지 실무 원칙을 의식할 필요가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;첫째, AI의 응답을 최종 결론처럼 받아들이지 않아야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;둘째, 하나의 답변만 신뢰하기보다 다른 해석이나 반대 근거도 함께 확인해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;셋째, 반복적인 대화 속에서 특정 방향으로 사고가 편향되고 있지 않은지 스스로 점검해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;넷째, 설계·보안·성능·운영과 같이 영향이 큰 판단은 반드시 사람이 최종 검토해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결국 이 논문이 AI를 활용하는 개발자에게 주는 메시지는 분명하다. AI는 틀린 정보를 생성할 때만 위험한 것이 아니라, 사용자의 현재 생각을 자연스럽게 강화하면서 잘못된 확신을 만들어낼 수도 있다. 따라서 AI 기반 개발에서는 정확도뿐 아니라 균형성, 반대 근거 확인, 최종 판단의 책임 주체를 함께 고려해야 한다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI를 활용해 개발할 때 원칙을 실천하는 현실적인 방법&lt;/span&gt;&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예를 들어 개발자가 AI에게 &lt;em&gt;“이 구조가 맞는지 검토해줘”&lt;/em&gt;, &lt;em&gt;“내 설계 방향이 타당한가”&lt;/em&gt;, &lt;em&gt;“이 방식이 가장 좋은 방법 아닌가”&lt;/em&gt; 와 같이 질문하면, AI는 이미 질문 안에 포함된 방향을 따라 답할 가능성이 높다. 즉, 객관적인 검토보다 현재 사용자의 사고 흐름을 이어주는 방식으로 응답하기 쉽다. 이 때문에 실무에서는 &lt;strong&gt;질문의 방향 자체를 의도적으로 바꾸는 습관&lt;/strong&gt;이 필요하다. 예를 들어 다음 두 질문은 비슷해 보이지만 결과는 분명히 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 구조가 맞는지 검토해줘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 구조의 취약점과 실패 가능성을 먼저 찾아줘&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgl-6uvyezpehmckFjTfYu6056w7CVrBAyZ1z0jxiDoM18Bz3mEJIgqSwrggI0XfwUlREGa5yAcYqE9VIiNeBqBLVOyR2ymdv6MG61XC1y9tGAQN5wms9l5RAHkWbDYYkrcl98dt8IslVVnaM5nlViov_NBSD0AFUqQVQEIkNjd-rkqY8Udm0HAVTLjO_o3&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgl-6uvyezpehmckFjTfYu6056w7CVrBAyZ1z0jxiDoM18Bz3mEJIgqSwrggI0XfwUlREGa5yAcYqE9VIiNeBqBLVOyR2ymdv6MG61XC1y9tGAQN5wms9l5RAHkWbDYYkrcl98dt8IslVVnaM5nlViov_NBSD0AFUqQVQEIkNjd-rkqY8Udm0HAVTLjO_o3=w640-h426&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;첫 번째 질문은 확인을 유도하고, 두 번째 질문은 반박을 유도한다. 실제로 두 번째 방식이 더 많은 위험 요소를 드러낸다. 같은 방식으로 코드 생성 이후에도 바로 적용하기보다, 추가 검증 질문을 이어가는 것이 중요하다. 예를 들어 AI가 특정 구현을 제안했을 때는 다음과 같이 다시 질문할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 코드가 운영 환경에서 실패할 가능성이 있는 경우는 무엇인가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예외 상황에서 깨질 수 있는 부분은 어디인가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;최신 프레임워크 기준으로 문제가 될 수 있는 부분은 없는가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;즉, 첫 번째 답변은 초안으로 보고 두 번째 질문부터 검증 단계로 들어가야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설계 단계와 구현 단계도 분리해서 보는 것이 좋다. AI는 설계 설명에서는 매우 자연스럽지만, 실제 코드에서는 중요한 조건을 빠뜨리는 경우가 적지 않다. 예를 들어 먼저 구조를 설명받은 뒤 다시 다음과 같이 물을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;지금 설명한 구조가 실제 코드에서 깨질 수 있는 조건을 찾아줘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;트랜잭션, 동시성, 예외 처리 측면에서 위험 요소를 설명해줘&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhasLQMyiOoI9wab0FnxI3ZmrZutFQPZB5q7plgWTx3JbgJzYFMRSSHb4szfxe4wRg9lnhx96umQ6BllaP2Idzn0xPKRlRL6y-_N4fMHqTkel2McZqnqwf_eW0V4H1yUkYY-rxYpO9jglVXnYaGUPBFdWfEQ4h05srlMWlM5x4V5gM8aE5a_VwtLxt1YuHV&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;427&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhasLQMyiOoI9wab0FnxI3ZmrZutFQPZB5q7plgWTx3JbgJzYFMRSSHb4szfxe4wRg9lnhx96umQ6BllaP2Idzn0xPKRlRL6y-_N4fMHqTkel2McZqnqwf_eW0V4H1yUkYY-rxYpO9jglVXnYaGUPBFdWfEQ4h05srlMWlM5x4V5gM8aE5a_VwtLxt1YuHV&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이렇게 하면 단순 설명보다 실제 적용 시 발생할 수 있는 문제를 더 빨리 발견할 수 있다. 여러 AI를 함께 사용하는 경우에는 교차 검증도 효과적이다. 예를 들어 다음과 같은 흐름이 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Codex 로 초안 작성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Claude 로 구조적 취약점 검토&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Gemini 로 대안 비교&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 과정에서 중요한 것은 단순히 다른 모델에 다시 묻는 것이 아니라, &lt;strong&gt;질문 자체를 다르게 주는 것&lt;/strong&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예를 들어:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 코드의 문제를 추측하지 말고 실제 코드 근거로만 지적해줘&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;반대 구현 방식이 더 적절할 수 있는 경우를 설명해줘&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiTCD01bLST41oIvnLwuS6iyZLk2MOH_iR4gVBoMbPV6e3ETdKSOOfnnV4t7PHYBD6G090unT9QV1t2xD1H0CjMEKBB6y4tVQbzPaXPsFNC5caSnq8dRrOgoMoNgegBEmTrfCrwlaKUJIxyXQWgw9GO4xPbiASCgnPAmk2jfH6keeYH1Fe4kCag_cvanKAV&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEiTCD01bLST41oIvnLwuS6iyZLk2MOH_iR4gVBoMbPV6e3ETdKSOOfnnV4t7PHYBD6G090unT9QV1t2xD1H0CjMEKBB6y4tVQbzPaXPsFNC5caSnq8dRrOgoMoNgegBEmTrfCrwlaKUJIxyXQWgw9GO4xPbiASCgnPAmk2jfH6keeYH1Fe4kCag_cvanKAV=w640-h426&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AI가 강한 확신을 보일수록 오히려 더 검증해야 한다는 점도 중요하다. AI는 매우 자연스럽게 &lt;em&gt;“이 방식이 가장 적절하다”&lt;/em&gt;, &lt;em&gt;“일반적으로 이렇게 구현한다”&lt;/em&gt; 와 같은 표현을 사용하지만, 이런 문장은 기술적 근거 없이 생성될 수도 있다. 따라서 이런 답을 받으면 반드시 다시 확인해야 한다.&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;공식 문서 기준 근거는 무엇인가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예외 사례는 없는가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다른 구현 방식과 비교하면 장단점은 무엇인가&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgE87bm59RruRd3wh-v3mI3A9V1henTTX56AxP9sF8RUB5gpnQ3t8kzQ_9LmImo0Ph_KJ8TgCiM96iQJWKgKS9JNPUDGC2FQ5kVVBuKmPBGDmi6jNCOQiHj30god1sJcAmIDwmSU6oLA6t6P6-VzI990HUMCbaQd8sMpInK9mPBelyNQrJIDygNZAVGpmwv&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgE87bm59RruRd3wh-v3mI3A9V1henTTX56AxP9sF8RUB5gpnQ3t8kzQ_9LmImo0Ph_KJ8TgCiM96iQJWKgKS9JNPUDGC2FQ5kVVBuKmPBGDmi6jNCOQiHj30god1sJcAmIDwmSU6oLA6t6P6-VzI990HUMCbaQd8sMpInK9mPBelyNQrJIDygNZAVGpmwv=w640-h426&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결국 AI를 활용한 개발에서 중요한 것은 &lt;strong&gt;빠른 답을 받는 능력보다, 반대 질문을 던지고 검증 흐름을 만드는 능력&lt;/strong&gt;이다. AI는 개발 속도를 높여주지만 동시에 빠른 확신도 제공한다. 따라서 개발자는 AI의 첫 답을 정답으로 받아들이기보다, &lt;strong&gt;검토 대상이 되는 초안으로 다루는 태도&lt;/strong&gt;가 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;!-- notionvc: 8cbc4660-679a-4d80-9ddc-536d7c1b0f57 --&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/8585761506371046793/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/04/ai-sycophancy-ai.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/8585761506371046793'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/8585761506371046793'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/04/ai-sycophancy-ai.html' title='AI는 왜 사용자를 잘못된 확신으로 이끄는가 — Sycophancy 논문에서 본 대화형 AI 의 위험'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEgl-6uvyezpehmckFjTfYu6056w7CVrBAyZ1z0jxiDoM18Bz3mEJIgqSwrggI0XfwUlREGa5yAcYqE9VIiNeBqBLVOyR2ymdv6MG61XC1y9tGAQN5wms9l5RAHkWbDYYkrcl98dt8IslVVnaM5nlViov_NBSD0AFUqQVQEIkNjd-rkqY8Udm0HAVTLjO_o3=s72-w640-h426-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-3514199100587834505</id><published>2026-04-06T15:26:00.002+09:00</published><updated>2026-04-06T15:26:16.148+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="Claude Code"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><title type='text'>사용기 - AI 가 다른 AI 의 작업 결과를 이어 받아 마무리 하기 (클로드 ,  코덱스) </title><content type='html'>&lt;div&gt;AI 가 다른 AI 의 작업 결과를 이어 받아 마무리 하는 것은 어떻까.&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEh40vrrJa0qjIVsGaPhjXUno_fDquD5TQ01oL5RJ7LyoIIQ1KSKV_OjBRNn7FaTvdoT1VhmzVp5UQ1RRQjhqopw-O9eXHv6jaZVqm-fYMd5AY8vxyDqLNgWisu3t20kJe1Bk2s1qdJavPgvaNnbY4xp7i5QhsdfXhWObHyJLhM3seK-zKqYzsdy5fU35Va6&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;427&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEh40vrrJa0qjIVsGaPhjXUno_fDquD5TQ01oL5RJ7LyoIIQ1KSKV_OjBRNn7FaTvdoT1VhmzVp5UQ1RRQjhqopw-O9eXHv6jaZVqm-fYMd5AY8vxyDqLNgWisu3t20kJe1Bk2s1qdJavPgvaNnbY4xp7i5QhsdfXhWObHyJLhM3seK-zKqYzsdy5fU35Va6=w640-h427&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;이슈는 코덱스(Codex) 가 초안을 작성하고 클로드(Claude) 상세화 했다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOxF7iFNEdfk4UCLSnVy4kmzS7awvwWqNDDYxcADUP_CWM7VBrACqKNKiVEGvii6zUhkbato70x1fgw9vtzKWHhEPyzNM3q1fNiaBjm42zZGukiCFkV9dCfNnUFP3OP5nlx_Z4EuaQndLp2fPFyxXTWq030N2kAR7kcVyPPnsMa8EB7pJUy73Fvrxy-0Zh/s1460/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.12.20.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1338&quot; data-original-width=&quot;1460&quot; height=&quot;586&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOxF7iFNEdfk4UCLSnVy4kmzS7awvwWqNDDYxcADUP_CWM7VBrACqKNKiVEGvii6zUhkbato70x1fgw9vtzKWHhEPyzNM3q1fNiaBjm42zZGukiCFkV9dCfNnUFP3OP5nlx_Z4EuaQndLp2fPFyxXTWq030N2kAR7kcVyPPnsMa8EB7pJUy73Fvrxy-0Zh/w640-h586/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.12.20.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 11.88px; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;4.6)&amp;nbsp;계획 상세화 결과&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;p&gt;코덱스(Codex)가 12개의 서브 이슈들로 구성된 언브렐라(#27) 이슈를 등록하고 클로드(Claude)에게 #27 이슈 구현을 요청했다.&amp;nbsp;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8NQ6jsLpCArVWRlnSM2p4rk24o5TAlQiiYYUwl4mQ8xZwNlTtk4eJEPabAsN_2FCTqc7CvcQy_IQf_4vcyaaqxQIf_2YKpG8kei3WcnAFH5B4asAyFO9SmvymPXjSJHhd3zx1BRNYLIFSTz6Z01yKfmcCvpUz8QGtt07RFn2e7FdRos_HkGAs8lIEg_rA/s1490/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_04_34.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1124&quot; data-original-width=&quot;1490&quot; height=&quot;482&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8NQ6jsLpCArVWRlnSM2p4rk24o5TAlQiiYYUwl4mQ8xZwNlTtk4eJEPabAsN_2FCTqc7CvcQy_IQf_4vcyaaqxQIf_2YKpG8kei3WcnAFH5B4asAyFO9SmvymPXjSJHhd3zx1BRNYLIFSTz6Z01yKfmcCvpUz8QGtt07RFn2e7FdRos_HkGAs8lIEg_rA/w640-h482/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_04_34.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 11.88px; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;4.6)&amp;nbsp;구현 결과&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;코덱스(Codex)에게 클로드(Claude)의 작업 브랜치의 상태를 분석하여 현재 진행 상황을 확인하고 작업을 마무리 하게 했다.&amp;nbsp;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixK4vh-pNAV1Rndx5DmAC35TD0unw61Gknv9Mrqsyg9EEsqOBhPwnzBtDeM8WQ21UExwxJ0AMAm8o87vTMVI5dccOIQYDG50gZkEJk6UVZwQv3LJ0xW6uuFm8T25C4-qiuxwttg0cSveDseS1Oz9jTiSfw26jp6da298ETLcpyW9VK1eDtbXN_8RNFpqyO/s1570/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_09_25.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1570&quot; data-original-width=&quot;1546&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixK4vh-pNAV1Rndx5DmAC35TD0unw61Gknv9Mrqsyg9EEsqOBhPwnzBtDeM8WQ21UExwxJ0AMAm8o87vTMVI5dccOIQYDG50gZkEJk6UVZwQv3LJ0xW6uuFm8T25C4-qiuxwttg0cSveDseS1Oz9jTiSfw26jp6da298ETLcpyW9VK1eDtbXN_8RNFpqyO/w630-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_09_25.jpg&quot; width=&quot;630&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 이어서 구현&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;클로드(Claude)에게&amp;nbsp; PR #40 에 대한 리뷰를 요청했다.&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWXslkLeajKi4xsulXkfHbFoOKgwPkDNpJWuz1VkK1Q-PhD3Bis1GLd1ZM7ITyG7uJc0XYYc5aCRhEn1ISqknnyy5BEOqeIcynnRUReU1S8iwnnSwCthgg2srt2mrfHaIdMtJziX1jv343mysQkzRMadC7OZc5yn2ZMhsRN230Xq6zV_t7k8Dtd6qWBXYl/s1524/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.15.11.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1320&quot; data-original-width=&quot;1524&quot; height=&quot;554&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWXslkLeajKi4xsulXkfHbFoOKgwPkDNpJWuz1VkK1Q-PhD3Bis1GLd1ZM7ITyG7uJc0XYYc5aCRhEn1ISqknnyy5BEOqeIcynnRUReU1S8iwnnSwCthgg2srt2mrfHaIdMtJziX1jv343mysQkzRMadC7OZc5yn2ZMhsRN230Xq6zV_t7k8Dtd6qWBXYl/w640-h554/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.15.11.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 11.88px; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;4.6)&amp;nbsp; 1차 리뷰 결과&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;코덱스(Codex)에게 리뷰 결과를 조치하게 했다.&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuJlOMyXpoyO7O9_1jXcwwx9M2zQh6VLIYzKB9BUnozEsR0i_87jh5FLEXDsOR3CQjtpY1BK9TNgRGJlO8MKp_fq3FKid-00ZL13CS3za3lbJmqrOu1n1unDqpOda2F4x9pcazfdZkJOo65CAbB4J85u6iY8RcsjCDqQJbdfziG3vUj0JvbJ6fQ1JRuhRq/s1548/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.18.17.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1202&quot; data-original-width=&quot;1548&quot; height=&quot;496&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuJlOMyXpoyO7O9_1jXcwwx9M2zQh6VLIYzKB9BUnozEsR0i_87jh5FLEXDsOR3CQjtpY1BK9TNgRGJlO8MKp_fq3FKid-00ZL13CS3za3lbJmqrOu1n1unDqpOda2F4x9pcazfdZkJOo65CAbB4J85u6iY8RcsjCDqQJbdfziG3vUj0JvbJ6fQ1JRuhRq/w640-h496/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.18.17.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 1차 리뷰 조치&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;클로드(Claude)에게&amp;nbsp; PR #40 에 대한 재 리뷰를 요청했다. 확인 결과 병합은 가능한 상태이지만 추가로 몇가지 마이너한 개선 사항이 도출되었다.&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip_9pd2WaEI9Bov-ZuxKvc3GGSkSomJQHLZi5qRE4NSppKa7bLmZhjPcTE6D7surrxRgIHflmbVT5h1dNbeZPZrphS_MAJMxWjb_z5AhLOV6bz7bR57WM3asZdAC1WeDufM0xmiMuxgQXzKkz0wgNrK7ABCEprbIzwn6HOpZ8GGxHOohJlR2sZsOM80Nr5/s1434/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.22.25.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1344&quot; data-original-width=&quot;1434&quot; height=&quot;600&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEip_9pd2WaEI9Bov-ZuxKvc3GGSkSomJQHLZi5qRE4NSppKa7bLmZhjPcTE6D7surrxRgIHflmbVT5h1dNbeZPZrphS_MAJMxWjb_z5AhLOV6bz7bR57WM3asZdAC1WeDufM0xmiMuxgQXzKkz0wgNrK7ABCEprbIzwn6HOpZ8GGxHOohJlR2sZsOM80Nr5/w640-h600/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.22.25.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 11.88px; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;4.6)&amp;nbsp; 2차 리뷰 결과(1차 리뷰 조치 확인)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;코덱스(Codex)에게 다시 리뷰 결과를 조치하게 했다.&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfwyM-ozr1YyMyw0AmwkTw8H5fagpqU4ifBQ5-fpa0eHRibV1js8JLucTCbceIZwarBuvTbKlZjAn1SHtqNaXp1I5N8v-wNYxcMXCpYYQJ0mklvV5suex9-NvU0XmDhWgt4pzdvu3e-jAVQP8Hu_sP0qGzRG0e23eQ-sT7HOIbj3mor4KJ5amztrMjeDqh/s1526/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.25.46.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1182&quot; data-original-width=&quot;1526&quot; height=&quot;496&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfwyM-ozr1YyMyw0AmwkTw8H5fagpqU4ifBQ5-fpa0eHRibV1js8JLucTCbceIZwarBuvTbKlZjAn1SHtqNaXp1I5N8v-wNYxcMXCpYYQJ0mklvV5suex9-NvU0XmDhWgt4pzdvu3e-jAVQP8Hu_sP0qGzRG0e23eQ-sT7HOIbj3mor4KJ5amztrMjeDqh/w640-h496/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.25.46.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 2차 리뷰 조치&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;다시 클로드(Claude)에게 리뷰를 요청했고 모든 이슈가 해결되었음을 확인 할 수 있었다.&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizfhFxxL4TOk51XnAN3flg3-47own2htGPrgu9St1ZfWeH7mtKOx2Zv43oJ_0z5k2kLMOfkiTGxV-CKrYckL_AChcwdkKCiTrXBPd4fBD__bvzE7vq0bLU5Hx31CvvPvzClE1CiFbRiSx6oNmSCw9UathMIPJygfEP59yR_hDjZoLzVpOz4n-usOR-rI0M/s1484/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.28.32.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1090&quot; data-original-width=&quot;1484&quot; height=&quot;470&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizfhFxxL4TOk51XnAN3flg3-47own2htGPrgu9St1ZfWeH7mtKOx2Zv43oJ_0z5k2kLMOfkiTGxV-CKrYckL_AChcwdkKCiTrXBPd4fBD__bvzE7vq0bLU5Hx31CvvPvzClE1CiFbRiSx6oNmSCw9UathMIPJygfEP59yR_hDjZoLzVpOz4n-usOR-rI0M/w640-h470/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.28.32.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 11.88px; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;4.6)&amp;nbsp; 3차 리뷰 결과(2차 리뷰 조치 확인)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;AI 모델에게 코드를 작성하게하고 같은 모델에게 리뷰를 시키면 코딩시 놓친 맹점이 리뷰할 떄도 그냥 넘어갈 수 있게된다. 참고로&amp;nbsp;&lt;span style=&quot;background-color: white; color: #0a0a0a; font-family: Arial, sans-serif; font-size: 16px;&quot;&gt;보리스 체르니(Boris Cherny)&lt;/span&gt;가 공개한&amp;nbsp;&lt;span style=&quot;background-color: white; color: #1f2328; font-family: &amp;quot;Mona Sans VF&amp;quot;, -apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, &amp;quot;Noto Sans&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 16px;&quot;&gt;Claude Code 내에서 코덱스(Codex) 를 사용하여 코드 리뷰를 수행하거나 Codex에 작업을 위임할 수 있는 플러그인이&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/openai/codex-plugin-cc&quot; target=&quot;_blank&quot;&gt;Codex plugin for Claude Code&lt;/a&gt;&amp;nbsp;도 같은 맥락이다.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/3514199100587834505/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/04/ai-ai.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3514199100587834505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3514199100587834505'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/04/ai-ai.html' title='사용기 - AI 가 다른 AI 의 작업 결과를 이어 받아 마무리 하기 (클로드 ,  코덱스) '/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEh40vrrJa0qjIVsGaPhjXUno_fDquD5TQ01oL5RJ7LyoIIQ1KSKV_OjBRNn7FaTvdoT1VhmzVp5UQ1RRQjhqopw-O9eXHv6jaZVqm-fYMd5AY8vxyDqLNgWisu3t20kJe1Bk2s1qdJavPgvaNnbY4xp7i5QhsdfXhWObHyJLhM3seK-zKqYzsdy5fU35Va6=s72-w640-h427-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-3759170172486340037</id><published>2026-04-03T15:39:00.005+09:00</published><updated>2026-04-06T08:49:34.827+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="Claude Code"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="Gemini Code Assist"/><title type='text'>사용기 -  클로드, 코덱스, 제미나이 기반의 AI 코딩 : VUE 프로그램을 REACT 로 변경</title><content type='html'>&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;p class=&quot;p1&quot;&gt;작업의 목표는 기존 Vue3 기반 프로젝트를 &lt;span class=&quot;s1&quot;&gt;1.x&lt;/span&gt;, &lt;span class=&quot;s1&quot;&gt;2.x&lt;/span&gt; 브랜치로 구분하고, &lt;span class=&quot;s1&quot;&gt;2.x&lt;/span&gt; 브랜치에서 React 전환을 진행하는 것이었다. 단순히 특정 모델 하나만 사용하는 것이 아니라, 여러 AI 코딩 에이전트를 실제 작업에 투입해 &lt;span class=&quot;s2&quot;&gt;&lt;b&gt;계획 수립, 상세화, 구현, 리뷰, 병합&lt;/b&gt;&lt;/span&gt;의 각 단계에서 어떤 조합이 가장 효율적인지를 확인해보고자 했다&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;







&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. 최초 계획 수립 - Codex&lt;/span&gt;&lt;/h3&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;






&lt;p class=&quot;p1&quot;&gt;최초 작업 계획은 Codex(GPT-5.4, reasoning effort: medium)를 사용해 수립했다. Codex는 전체 작업 방향과 단계별 흐름을 정리한 &lt;span class=&quot;s1&quot;&gt;MIGRATION_2X.md&lt;/span&gt; 문서를 작성했다. 이 문서는 실제 개발을 바로 수행할 수 있는 상세 설계서라기보다는, &lt;span class=&quot;s2&quot;&gt;&lt;b&gt;원칙과 단계별 진행 방향을 정리한 초안 성격의 계획서&lt;/b&gt;&lt;/span&gt;에 가까웠다.&lt;/p&gt;&lt;/span&gt;







&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;이 단계에서 느낀 점은 Codex가 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;최초 구조를 잡고 작업을 시작하는 능력&lt;/b&gt;&lt;/span&gt;, 그리고 여러 작업을 분할해 병렬로 진행할 수 있도록 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;초기 작업 틀을 만드는 능력&lt;/b&gt;&lt;/span&gt;이 우수하다는 점이었다. 이후 이 문서를 기반으로 모든 이슈를 등록하는 작업도 Codex를 통해 수행했고, 총 12개의 이슈가 생성되었다.&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;







&lt;/b&gt;&lt;p class=&quot;p1&quot;&gt;&lt;b&gt;&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;2. 상세 계획 수립 - Gemini 중심, Codex 보조&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #666666; font-family: Nanum Gothic;&quot;&gt;클로드 공식 문서는 CLAUDE.md를 프로젝트 기억용 파일로 설명하고, /init로 시작용 CLAUDE.md를 자동 생성하라고 권고 하고 있다. 일관적인 작업 수행을 위해서 먼저 생성을 진행했다. 추가로 기존 프로젝트의 정책 및 템플릿 내용도 반영하도록 했다.  Claude Pro 요금제의 가장 큰 불편함은 5시간 단위와 주간 단위의 사용 제한이다. 작업이 한창 진행되는 중간에 멈추는 경우가 반복되다 보니, 실제 사용성 면에서 답답함이 크다. 작업중에 주간 한계를 초과하여 금주 목요일 11:00 까지 기다려야 한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제한이 풀리자 바로 /init 명령을 실행했고, 클로드는 기존 프로젝트의 파일을 분석하여&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;CLAUDE.md 을 생성했다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTamQxz8owaxP4olPkPEOyfPtwEgdTCJbffkhhyphenhyphenIbZLV86Hh4_tFS45DvH6oqeOKi4Xz_RLTZR_Ed4VfWQpNJwDAnTnoiOf5GiBYelzJ9NTzKzZX1itDUHdPlw8gXMsfxCB4Az7qD8OPYuhmwJRJl0MCjzm6APA0T_0b27M2AWZCXkbOID7158p874RCyt/s1548/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.12.38.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1318&quot; data-original-width=&quot;1548&quot; height=&quot;544&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTamQxz8owaxP4olPkPEOyfPtwEgdTCJbffkhhyphenhyphenIbZLV86Hh4_tFS45DvH6oqeOKi4Xz_RLTZR_Ed4VfWQpNJwDAnTnoiOf5GiBYelzJ9NTzKzZX1itDUHdPlw8gXMsfxCB4Az7qD8OPYuhmwJRJl0MCjzm6APA0T_0b27M2AWZCXkbOID7158p874RCyt/w640-h544/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.12.38.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot;&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: x-small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;span style=&quot;text-align: left;&quot;&gt;4.6) init 실행&lt;/span&gt;&amp;nbsp;결과&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;Claude 를 사용한 세부 계획 수립 계획&lt;/u&gt;을 변경하여 Gemini 2.5 Flash가 기존 MIGRATION_2X.md를 검토하여 세부 내용을 보완했고, 다시 Codex가 이를 검토하고 수정하는 방식으로 계획을 다듬었다. 다만 이후 실제 구현과 리뷰를 진행하는 과정에서, 작업 범위의 경계가 다소 모호하게 잡히는 경우가 있었고, 그 부분을 다시 Claude가 검토하면서 보완했다. 글 전체 흐름을 기준으로 보면 세부 계획 수립 능력은 Gemini보다 Claude가 더 안정적이었다고 판단된다.&lt;/span&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguw845ZtgYiF6QTsP3YxgDhFbQ3bp3g0-9RHNL9fg3zAFvdtQgf6SWPmuE9rwFWAHj-oJ98JY0jJqiYxQeFK1oo3UlvkWDgeODQrDcaYChthZsnzqcTserYxNJLn-5ur2iLtYrXn4eOZuZB5LdPYaRnMb7J9ZwIXAA96GHP6XcVMNmZ9xS_zCGc0DT-KMk/s2990/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.44.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1468&quot; data-original-width=&quot;2990&quot; height=&quot;314&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguw845ZtgYiF6QTsP3YxgDhFbQ3bp3g0-9RHNL9fg3zAFvdtQgf6SWPmuE9rwFWAHj-oJ98JY0jJqiYxQeFK1oo3UlvkWDgeODQrDcaYChthZsnzqcTserYxNJLn-5ur2iLtYrXn4eOZuZB5LdPYaRnMb7J9ZwIXAA96GHP6XcVMNmZ9xS_zCGc0DT-KMk/w640-h314/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.56.44.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: x-small;&quot;&gt;제미나이(&lt;span style=&quot;text-align: left;&quot;&gt;Gemini 2.5 Flash)&lt;/span&gt;&amp;nbsp;실행 가능성 검토&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p class=&quot;p1&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDdJfbFX9Ik46bfVQRLH9J5yqsA8tuH_KT0PiBfXIjWe_5Kiswtjbkpy-xqWR_VHjzZGKzuvdvMAKZXpf53dDks_yKsbMT9mPE600TQ37BSk5I7eSBiccwEH-MZ_2bDyNSA3XBbvUB-YnNOZZDHPS_RpQ_kO7i2XwTq3pslE5oofxZIh63Y9mVsB-uIPxC/s1524/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.18.09.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1042&quot; data-original-width=&quot;1524&quot; height=&quot;438&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDdJfbFX9Ik46bfVQRLH9J5yqsA8tuH_KT0PiBfXIjWe_5Kiswtjbkpy-xqWR_VHjzZGKzuvdvMAKZXpf53dDks_yKsbMT9mPE600TQ37BSk5I7eSBiccwEH-MZ_2bDyNSA3XBbvUB-YnNOZZDHPS_RpQ_kO7i2XwTq3pslE5oofxZIh63Y9mVsB-uIPxC/w640-h438/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.18.09.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: x-small;&quot;&gt;코덱스 (GPT 5.4 medium) 1차 검토&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpKHYv9eaNJZDv2fJO8LcqTD0Vj_khhDB-MnaiePK8iEKq2CLVka0fz81YO3nXR5Hj1eYLolF5LxoyyhD92lHL9V4aYrVz6ngMs9NMN6bqhe8qhrFERTdIjfbI7uAafkLfPZbXulEsNzzb06WqY6wBI65YPWAGjCbtDjWxztUr7o42Y-3xX9W9xmUNOGea/s1536/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.21.14.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;754&quot; data-original-width=&quot;1536&quot; height=&quot;314&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpKHYv9eaNJZDv2fJO8LcqTD0Vj_khhDB-MnaiePK8iEKq2CLVka0fz81YO3nXR5Hj1eYLolF5LxoyyhD92lHL9V4aYrVz6ngMs9NMN6bqhe8qhrFERTdIjfbI7uAafkLfPZbXulEsNzzb06WqY6wBI65YPWAGjCbtDjWxztUr7o42Y-3xX9W9xmUNOGea/w640-h314/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.21.14.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: x-small;&quot;&gt;코덱스 (GPT 5.4 medium) 1차 검토 결과 보완&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiovZdVJv2_a7WjOnXp84SLkf2qVJcnS59WaUiIMFO3viSXS_J13TAKtG5iLLnP3VfwhcUo82r21ClaalNyBtQVr8Qec1qJaR866431bcSqliWDG_14dnmwTd6HfHjKCUoEqibsivtt5WIRb6uJU_LMRBu7JN0S_ZjI0reDEdbmueV6cOnXBj7HQ7DooBWz/s2994/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.25.35.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1448&quot; data-original-width=&quot;2994&quot; height=&quot;310&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiovZdVJv2_a7WjOnXp84SLkf2qVJcnS59WaUiIMFO3viSXS_J13TAKtG5iLLnP3VfwhcUo82r21ClaalNyBtQVr8Qec1qJaR866431bcSqliWDG_14dnmwTd6HfHjKCUoEqibsivtt5WIRb6uJU_LMRBu7JN0S_ZjI0reDEdbmueV6cOnXBj7HQ7DooBWz/w640-h310/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.25.35.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;제미나이(&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;Gemini 2.5 Flash)&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;2차 검토&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음으로 코덱스(&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 14.85px;&quot;&gt;GPT-5.4&lt;span style=&quot;text-align: center;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span face=&quot;Arial, Tahoma, Helvetica, FreeSans, sans-serif&quot; style=&quot;background-color: white; color: #333333; font-size: 14.85px;&quot;&gt;reasoning effort :&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 14.85px; text-align: center;&quot;&gt;medium)&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;를 사용하여 병렬작업을 고려하여 모든 이슈 등록과 변경된 문서을 커밋하도록 했다. (12개의 이슈가 등록됨)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQaLlu9ZZM0LUa2QV01lW1O3QaW_ZTA-YKzV4GNvnOX0lU-NviRyvMaL37CxksHxY_rhyc5mi3XCDWVbDOocoURmBW10JC4k9l4AawJ8OKT48hCQFbL7q6gVE2q7PxNbF6moh5oHap4fj0H2Viv_mMZ5L2L-HX2HVLKLZMBYvm9RBrSe7G3SWq_ozQ2VEB/s1532/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.58.59.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1532&quot; data-original-width=&quot;1034&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQaLlu9ZZM0LUa2QV01lW1O3QaW_ZTA-YKzV4GNvnOX0lU-NviRyvMaL37CxksHxY_rhyc5mi3XCDWVbDOocoURmBW10JC4k9l4AawJ8OKT48hCQFbL7q6gVE2q7PxNbF6moh5oHap4fj0H2Viv_mMZ5L2L-HX2HVLKLZMBYvm9RBrSe7G3SWq_ozQ2VEB/w432-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.58.59.png&quot; width=&quot;432&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;생성되어 등록된 이슈 목록&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span&gt;이 과정에서 코덱스 역시&amp;nbsp;&lt;/span&gt;&lt;span&gt;작업중에 주간 한계를 초과하였지만 미리 구매해두었던 토큰을 소모하면서 작업을 수행했다.&amp;nbsp;&lt;/span&gt;이 단계에서 얻은 결론은 다음과 같았다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;
&lt;p class=&quot;p2&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;b&gt;Codex&lt;/b&gt;&lt;/span&gt;: 최초 계획 초안 작성에 강점&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;b&gt;Claude&lt;/b&gt;&lt;/span&gt;: 계획의 세부화와 경계 정리에 강점 (사용 제한으로 확인 못함)&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;b&gt;Gemini&lt;/b&gt;&lt;/span&gt;: 계획 보완과 실행 가능성 판단에 충분히 유용함&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;







&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;3. 구현 - Codex와 Gemini 중심&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;실제 구현은 처음에는 Gemini(Free)를 통해 진행했다. &lt;br /&gt;&lt;br /&gt;Gemini는 Plan 모드와 Edit 모드를 구분하고 있었고, 실제 코딩을 위해서는 Edit 모드 전환이 필요했다. 무료 버전임에도 불구하고, 구현 자체는 충분히 수행 가능했고, 리뷰 결과에 대한 수정도 상당히 잘 반영했다. 이 점에서 Gemini의 코딩 능력 자체는 충분히 확인할 수 있었다고 본다.  &lt;br /&gt;&lt;br /&gt;다만 사용량 제한에 도달하면 작업이 중단되는 문제가 있었고, 실제 작업 흐름을 이어가는 데에는 제약이 있었다. 그 이후 구현은 Codex가 이어받아 진행했는데, 이 과정은 서로 다른 모델 에이전트가 작업을 이어받을 수 있는지를 확인하는 좋은 사례가 되었다. Codex는 구현을 이어서 진행하는 데에도 무리가 없었고, 이후 병합 충돌 원인을 작업 히스토리 기준으로 파악하고 해결하는 모습도 인상적이었다.  &lt;br /&gt;&lt;br /&gt;실제 수행 흐름을 종합하면, 구현 단계에서는 다음과 같은 인상이 남았다.&lt;br /&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Gemini: 무료 버전 기준에서도 구현 능력은 충분히 확인 가능&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Codex: 구현의 연속성, 작업 유지, 충돌 해결, 마무리 처리에 강점&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;







&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;4. 리뷰 - Claude의 강점이 가장 분명했던 구간&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;







&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;구현 결과에 대한 검토는 주로 Claude를 통해 진행했다.&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;브랜치 리뷰, PR 리뷰, 리뷰 결과 확인, 추가 수정 요청 등 여러 단계에서 Claude를 반복적으로 사용했는데, 전체 흐름을 보면 이 부분에서 Claude의 장점이 가장 뚜렷하게 드러났다. Claude는 단순한 오류 지적이 아니라 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;작업 범위의 타당성, 보완 필요 지점, 수정 누락 여부&lt;/b&gt;&lt;/span&gt;를 비교적 안정적으로 짚어냈다.&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Codex도 코드 리뷰를 수행했지만, 글의 흐름상 Codex는 리뷰어 역할보다는 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;직접 수정하고 정리하는 역할&lt;/b&gt;&lt;/span&gt;에서 더 자연스러웠다. 반면 Claude는 여러 차례 교차 검증 과정에서도 추가 수정 사항을 찾아냈고, PR 리뷰 품질도 일관적이었다. 따라서 리뷰 단계에 대해서는 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;Claude가 가장 적합했다&lt;/b&gt;&lt;/span&gt;고 판단된다.&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4zakrcf_EHaGtT0R77I5J5qEtfGsvNtUvAi0bhSO3pfIct6ChsgzpfPS8HZnnq9yCZcaCQlikVMBIpXbeNCw53P2CfHpXOPS32eaMeQ5mox-ewWhWtr8Fruguj3CF1gSjxDvdOVY_yUo8b7JpzmDIcCaf-EvbdG9yjve2we3iKH1SPrkr7bfdxA-NYcPa/s1606/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-02_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_20_13.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;996&quot; data-original-width=&quot;1606&quot; height=&quot;396&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4zakrcf_EHaGtT0R77I5J5qEtfGsvNtUvAi0bhSO3pfIct6ChsgzpfPS8HZnnq9yCZcaCQlikVMBIpXbeNCw53P2CfHpXOPS32eaMeQ5mox-ewWhWtr8Fruguj3CF1gSjxDvdOVY_yUo8b7JpzmDIcCaf-EvbdG9yjve2we3iKH1SPrkr7bfdxA-NYcPa/w640-h396/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-04-02_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_20_13.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 코드리뷰 결과&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG-ixGVRavPVLHZ1TbDcvIdF9A57QZ06wmmwQB4TU68PJcs5_omP5AFIwozqELEv03CDk3HwzqjYYq972aV8M0BZ3DYetZiHRXB3-w7MGHwts6M_SY8F5r0g-UpAxGUJPVoqDfejQgPz8J4gxyZ9FPGsVt3iSZRlzw6dnREGmu1HRdlIx-B1CNxAeZfGZN/s1508/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.30.05.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1280&quot; data-original-width=&quot;1508&quot; height=&quot;544&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG-ixGVRavPVLHZ1TbDcvIdF9A57QZ06wmmwQB4TU68PJcs5_omP5AFIwozqELEv03CDk3HwzqjYYq972aV8M0BZ3DYetZiHRXB3-w7MGHwts6M_SY8F5r0g-UpAxGUJPVoqDfejQgPz8J4gxyZ9FPGsVt3iSZRlzw6dnREGmu1HRdlIx-B1CNxAeZfGZN/w640-h544/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.30.05.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;4.6) 브랜치 리뷰 결과&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;







&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;s1&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;5. 병렬 작업과 교차 검증에서 확인한 점&lt;/b&gt;&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;







&lt;p class=&quot;p1&quot;&gt;이번 작업에서는 단순히 하나의 모델만 쓰지 않고, 서로 다른 모델을 조합해 병렬 작업과 교차 검증도 시도했다. Codex가 지시문을 작성하고, Gemini와 Codex 서브에이전트가 각각 구현을 수행한 뒤, Claude가 리뷰를 담당하는 방식도 실험했다. 또한 Claude가 작업한 결과를 Codex가 리뷰하고, 다시 Codex 결과를 Claude가 리뷰하는 교차 방식도 시도했다.&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p class=&quot;p1&quot;&gt;이러한 과정을 통해 확인한 것은, &lt;span class=&quot;s2&quot;&gt;&lt;b&gt;모델마다 잘하는 역할이 분명히 다르다&lt;/b&gt;&lt;/span&gt;는 점이다.&lt;/p&gt;
&lt;p class=&quot;p3&quot;&gt;&lt;span class=&quot;s3&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;
&lt;p class=&quot;p1&quot;&gt;Codex는 실행과 정리에 강했다.&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p class=&quot;p1&quot;&gt;Claude는 계획의 정교화와 리뷰의 완성도가 높았다.&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;
&lt;p class=&quot;p1&quot;&gt;Gemini는 무료 버전 기준에서도 구현 능력을 보여주었다.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh860XIVmVunCLgoMlWLmuOJ1z9WwdRPxS7zvpoV6qsgtEWhzDjV7oI3XwUHhqLCs-dkm62VecUW4jQIN2zpn0ggIdmLvG2VapSvqk4Kljohhg1hFpwD2XFlNoz_i9Q_b_1-vNyJnC6BjleIF8kxJMyFMtNNy3j2-afWh-0-rTKfN5y_veY1jjMXuiuaKJP/s1586/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.41.51.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;946&quot; data-original-width=&quot;1586&quot; height=&quot;382&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh860XIVmVunCLgoMlWLmuOJ1z9WwdRPxS7zvpoV6qsgtEWhzDjV7oI3XwUHhqLCs-dkm62VecUW4jQIN2zpn0ggIdmLvG2VapSvqk4Kljohhg1hFpwD2XFlNoz_i9Q_b_1-vNyJnC6BjleIF8kxJMyFMtNNy3j2-afWh-0-rTKfN5y_veY1jjMXuiuaKJP/w640-h382/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.41.51.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 작업 결과&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq0B_mNHazdP-otHkyfNDJ9eMpb4HxPRPMaxpK_dhpmCfw99hBnJcpPJt2PJK3Eqf6XbV_9QkT9lWCM9_L0_WQ1diSWP-ZCmydlvpNf1RVfAi0ZobRewhnsq4iFfCYwpYHH436y7J8yq3nEXVtG5RfrRo9R19ioX2xfCzKIAohaE3xCZJtpkMXLahS5Y1V/s1608/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.41.46.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1252&quot; data-original-width=&quot;1608&quot; height=&quot;498&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq0B_mNHazdP-otHkyfNDJ9eMpb4HxPRPMaxpK_dhpmCfw99hBnJcpPJt2PJK3Eqf6XbV_9QkT9lWCM9_L0_WQ1diSWP-ZCmydlvpNf1RVfAi0ZobRewhnsq4iFfCYwpYHH436y7J8yq3nEXVtG5RfrRo9R19ioX2xfCzKIAohaE3xCZJtpkMXLahS5Y1V/w640-h498/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.41.46.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;4.6) PR 리뷰 결과&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음으로는 작업을 서로 다른 모델 에이전트를 사용하여 진행해보았다. 이 작업위해서 코덱스를 사용하여 작업 지시를 위한 업무 계획을 정리하게 하게 한다음에 구현을 진행했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;이번에는 보다 정확한 병렬을 위해서 코덱스가 지시문을 작성하게 했다. 하나는 제미나이에게 작업을 요청했고 하나는 코덱스 서브에이전트가 작업하도록 했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1b7B2H2xEYLCWvZKt3C7G_3gnI1ywewQwL097ld1MNZehQCmeCjHIpKG1J9y3ppnFH38kNKF96hwNhVDJTE7B-clC35vSYF2ZeX1KOUMvN0kDfhZ9AzTWfn074-80AYSd3djDfpGCyydbqgUTVC67v3X2J-oXbXrO0fZhHt5LqvH8rdvBbrCJ7B7HrKTG/s1490/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.47.04.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1360&quot; data-original-width=&quot;1490&quot; height=&quot;584&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi1b7B2H2xEYLCWvZKt3C7G_3gnI1ywewQwL097ld1MNZehQCmeCjHIpKG1J9y3ppnFH38kNKF96hwNhVDJTE7B-clC35vSYF2ZeX1KOUMvN0kDfhZ9AzTWfn074-80AYSd3djDfpGCyydbqgUTVC67v3X2J-oXbXrO0fZhHt5LqvH8rdvBbrCJ7B7HrKTG/w640-h584/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.47.04.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 작업 지시문 생성&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;리뷰는 클로드를 사용하여 진행했다. 코덱스는 PR 까지 진행하여 PR 에 대한 리뷰를 (클로드가) 진행하고 (코덱스가) 결과 조치 후 다시 (크로드가) 리뷰를 진행했다. 코덱스는 1차 리뷰 결과에 대한 조치는 완벽하게 처리했고 2차 리뷰에 클로드에 의하여 추가 조치 사항이 발견되었으며 해당 내역역시 조치를 완료하는 것으로 리뷰 결과에 대한 조치 완전하게 처리함을 확인 할 수 있었다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBz1wtPa_HnJW5V79NuSAvNwwdMRpnyf9ZaUT6k-mfQZnIo-TzCD0q6swwRe_oAPNuZKB1-rXjwsjGChsLJhQ4fnTxIZaSYF5loX8xbcArAdhJpCIqf3cEPn5atthniGd33dkoOCb3zVHIjbxM5ZNosWKqBKEGrsjC34oARaW_KKbwW0m6hvXdgOG_8iVY/s1428/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.24.36.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1020&quot; data-original-width=&quot;1428&quot; height=&quot;458&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBz1wtPa_HnJW5V79NuSAvNwwdMRpnyf9ZaUT6k-mfQZnIo-TzCD0q6swwRe_oAPNuZKB1-rXjwsjGChsLJhQ4fnTxIZaSYF5loX8xbcArAdhJpCIqf3cEPn5atthniGd33dkoOCb3zVHIjbxM5ZNosWKqBKEGrsjC34oARaW_KKbwW0m6hvXdgOG_8iVY/w640-h458/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.24.36.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;4.6) 1차 리뷰 결과&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxv1bzLcNDyzyMdaktncAl5kfRcieeujVydRPV2tdLL2L39TRtfTg0HCv3tvjWwMclOIkj1kHPSrUAB3Qc7pPa-GIrfJzzWDhYuIOFyobbqsCwHI8M1hviqaB17ZBhIsYkiGYhwnXtMHe4Id8SvDJVp0mgySMp7nNqiLt6BXhKw2-IALGLQoaD40O7iZD_/s1460/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.26.00.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1198&quot; data-original-width=&quot;1460&quot; height=&quot;526&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxv1bzLcNDyzyMdaktncAl5kfRcieeujVydRPV2tdLL2L39TRtfTg0HCv3tvjWwMclOIkj1kHPSrUAB3Qc7pPa-GIrfJzzWDhYuIOFyobbqsCwHI8M1hviqaB17ZBhIsYkiGYhwnXtMHe4Id8SvDJVp0mgySMp7nNqiLt6BXhKw2-IALGLQoaD40O7iZD_/w640-h526/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.26.00.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: small; text-align: left;&quot;&gt;4.6) 2차 리뷰 결과&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKpvG6MlH62bF1Am7dw1QYcQAFDVH9BcZkTigyJW7Y9vcI0gZ0DPu61ODSxCfAPmqI9FUSSz6FHSimGmDDysFq1QNuHY44ghPOYKICyO0Y7WuW4TB2QJq9xFVLa5FjXyXA0BYYAWbSwwcmRgiY0ikrt4tBwK-mJGFg2MhEmeTRy17zrptS4Too11aFHHc-/s1468/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.28.39.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;442&quot; data-original-width=&quot;1468&quot; height=&quot;192&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKpvG6MlH62bF1Am7dw1QYcQAFDVH9BcZkTigyJW7Y9vcI0gZ0DPu61ODSxCfAPmqI9FUSSz6FHSimGmDDysFq1QNuHY44ghPOYKICyO0Y7WuW4TB2QJq9xFVLa5FjXyXA0BYYAWbSwwcmRgiY0ikrt4tBwK-mJGFg2MhEmeTRy17zrptS4Too11aFHHc-/w640-h192/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.28.39.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: small; text-align: left;&quot;&gt;4.6) 3차 리뷰 결과&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제미나이는 작업 완료 이후 커밋까지는 했지만 PR 생성은 불가하다고 하여 작업 결과불을 기준으로 리뷰를 진행했다. 제미나이 역시 리뷰 결과에 대한 조치를 완전하게 처리했다. PR 생성은 클로드가 진행했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcQCnKK4dAYdVZUAJeq8GptKh5SYtzbK5VxAIV8ITAaHn3ZVlMwOsPliZ8UNmpANIeycVU1Q4HEce8VdEjvKdbiP7F-YXH7LvxSCkDuyey7SMe3sthyphenhyphenn0IV4kXjB8uspieuuZojijewXf5Q_AXBYZBLWErzmB8Lqf41Y0wv4df9ws3AKEk7WW7mpUgPQFH/s1500/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.16.38.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1234&quot; data-original-width=&quot;1500&quot; height=&quot;526&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcQCnKK4dAYdVZUAJeq8GptKh5SYtzbK5VxAIV8ITAaHn3ZVlMwOsPliZ8UNmpANIeycVU1Q4HEce8VdEjvKdbiP7F-YXH7LvxSCkDuyey7SMe3sthyphenhyphenn0IV4kXjB8uspieuuZojijewXf5Q_AXBYZBLWErzmB8Lqf41Y0wv4df9ws3AKEk7WW7mpUgPQFH/w640-h526/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.16.38.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: small;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: small; text-align: left;&quot;&gt;4.6) 최초 브랜치 리뷰 결과&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWBWBLA3y5LGblcwRIRO54m4P8xHTgLiY5v3KJ6mKZNogQY65NjAorebwj3CwEG2mxZOeQ5gTIJ2yDtTT-6KseH5lfnhxUNpkIvK5O-kLnfTCRN4xCRC2r4Ib-2wsbOP-vaKc_NWjDglnYnAdBDZ46RLh94Xt8ngILRhw_Op7fnieq3uIyWUtU1Kd6r_gB/s1458/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.16.52.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWBWBLA3y5LGblcwRIRO54m4P8xHTgLiY5v3KJ6mKZNogQY65NjAorebwj3CwEG2mxZOeQ5gTIJ2yDtTT-6KseH5lfnhxUNpkIvK5O-kLnfTCRN4xCRC2r4Ib-2wsbOP-vaKc_NWjDglnYnAdBDZ46RLh94Xt8ngILRhw_Op7fnieq3uIyWUtU1Kd6r_gB/s1458/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.16.52.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;/a&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1200&quot; data-original-width=&quot;1458&quot; height=&quot;526&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWBWBLA3y5LGblcwRIRO54m4P8xHTgLiY5v3KJ6mKZNogQY65NjAorebwj3CwEG2mxZOeQ5gTIJ2yDtTT-6KseH5lfnhxUNpkIvK5O-kLnfTCRN4xCRC2r4Ib-2wsbOP-vaKc_NWjDglnYnAdBDZ46RLh94Xt8ngILRhw_Op7fnieq3uIyWUtU1Kd6r_gB/w640-h526/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.16.52.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot; width=&quot;640&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;4.6) 조치 결과 확&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;인&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;병렬도 조치한 작업에 대한 병합 과정에서 제미나이 구현에 대한 PR 에서&amp;nbsp; 충돌이 발생하여 코덱스를 사용하여 이슈를 해결하고 병합을 마무리 했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOX5C95AQRy8U4pAsnoUgWv2vhcxUs6TH0xnNM0Cb44GuLcoIIbN_RO09P8btI_4io44kPumJPdhuJEonAElhK-OrV3-yJENoMoPbme_Bb0P0LzLhR9r4SVhyrsW-PdM2xg3zPlyOhbyrTzUB2E6APS4n7py3bVR07LA6wcWUJTcYlcs6nwPpwVbYgsaFF/s1822/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.28.08.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;526&quot; data-original-width=&quot;1822&quot; height=&quot;184&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOX5C95AQRy8U4pAsnoUgWv2vhcxUs6TH0xnNM0Cb44GuLcoIIbN_RO09P8btI_4io44kPumJPdhuJEonAElhK-OrV3-yJENoMoPbme_Bb0P0LzLhR9r4SVhyrsW-PdM2xg3zPlyOhbyrTzUB2E6APS4n7py3bVR07LA6wcWUJTcYlcs6nwPpwVbYgsaFF/w640-h184/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.28.08.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;깃랩 병합 이슈&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코덱스가 작업 히스토리를 확인하여 원인을 파악하고 해결하는 과정이 인상적이었다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd5XLjhG4QJCsCaNpHNI7qM-974ZkXZ7C9dGQ7ogQFdQH6-IyhUUo52AAWSAcBX5rV5RA3OFBoZiff5JUCzNzNkIkq5IQ6M2vLgUNGs2CBbt5u36K2bhtqjuetFgWloSzqWA0LDSTJD_7C9u98kssaxjlll7YUjCHeIMf8dVs6WJUKZY-zZgLHshegTtQG/s1214/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.35.47.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;870&quot; data-original-width=&quot;1214&quot; height=&quot;458&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgd5XLjhG4QJCsCaNpHNI7qM-974ZkXZ7C9dGQ7ogQFdQH6-IyhUUo52AAWSAcBX5rV5RA3OFBoZiff5JUCzNzNkIkq5IQ6M2vLgUNGs2CBbt5u36K2bhtqjuetFgWloSzqWA0LDSTJD_7C9u98kssaxjlll7YUjCHeIMf8dVs6WJUKZY-zZgLHshegTtQG/w640-h458/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.35.47.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: x-small; text-align: start;&quot;&gt;코덱스 (GPT 5.4 medium)&amp;nbsp; 병합 이슈 해결&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코덱스를 통한 중간 정검(9/12)과&amp;nbsp;&amp;nbsp;MIGRATION_2X.md 문서를 현횅화 했다. 또한 코덱스는 남은 이슈별 작업 기준을 정리하고 코덱스 서브에이전트와 제미나이 + 클로드가 구현을 진행했다. 리뷰는 클로드 한꺼번에 했고 보완 역시 코덱스가 한번에 처리했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhosr_C1cYxXDcXRzWDzzvlCy_NHUBudSj1CY0Wk-JDbeaVut5QvzJQysyfqI9XtWDe3tOvc5ZE3852_DW-hjrbENN6FWJj4AucOeQoirOSHe57RhDT4Uylwu5d4Nc_FVqs7W1C4P68GetOwIjRZXKCwQdt6bfrPDXQJ6P60Z2zD99RAU5DARwOe6DNBqyb/s1446/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.14.54.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1224&quot; data-original-width=&quot;1446&quot; height=&quot;542&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhosr_C1cYxXDcXRzWDzzvlCy_NHUBudSj1CY0Wk-JDbeaVut5QvzJQysyfqI9XtWDe3tOvc5ZE3852_DW-hjrbENN6FWJj4AucOeQoirOSHe57RhDT4Uylwu5d4Nc_FVqs7W1C4P68GetOwIjRZXKCwQdt6bfrPDXQJ6P60Z2zD99RAU5DARwOe6DNBqyb/w640-h542/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.14.54.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;4.6) 리뷰 결과 확&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;인&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이제 하나의 이슈만 남았는데 코덱스가 마무리 구현을 진행하고 클로드가 리뷰하게 했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcLYgED2oh0hf1IuqDmPZYy3XdKn2ehxKV4bpVYm2JoG76drLj3ZqxE0Pb8nl-X-XrCDWw4mkAwXym5xeEMdPKd1q8EvFk9gdXjNfdFaHjFWT5USg3Ked153dj7WW3HQEGD_3uElxQxC4s9DeGDQHBzkQQcaIoHZqAjsO-jPYqBtu5OG3G0Uf3pbmcgTaJ/s1466/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.19.59.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1226&quot; data-original-width=&quot;1466&quot; height=&quot;536&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcLYgED2oh0hf1IuqDmPZYy3XdKn2ehxKV4bpVYm2JoG76drLj3ZqxE0Pb8nl-X-XrCDWw4mkAwXym5xeEMdPKd1q8EvFk9gdXjNfdFaHjFWT5USg3Ked153dj7WW3HQEGD_3uElxQxC4s9DeGDQHBzkQQcaIoHZqAjsO-jPYqBtu5OG3G0Uf3pbmcgTaJ/w640-h536/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-03%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.19.59.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드(Sonnet&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: left;&quot;&gt;4.6) 최종 리뷰 결과&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEj6b0bkog2ETBCSagn8VeTBoNDUpObAKtDZb0LvTmVr_pJB8VKjnqX9Wu0wQVpE9plfaORrcGtdTP59hD6fcU5IaXrJZI7xbu0bmJaQBeaProU0vafYUOeyEhLlhiShMqWcfWakM5U02Ttg3Q8Tsf_pAw_ZYe66W0-D8AXw_SwDmearwQu6cSTKVvZsjSOr&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;427&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEj6b0bkog2ETBCSagn8VeTBoNDUpObAKtDZb0LvTmVr_pJB8VKjnqX9Wu0wQVpE9plfaORrcGtdTP59hD6fcU5IaXrJZI7xbu0bmJaQBeaProU0vafYUOeyEhLlhiShMqWcfWakM5U02Ttg3Q8Tsf_pAw_ZYe66W0-D8AXw_SwDmearwQu6cSTKVvZsjSOr&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;작업 완료 후 로컬에서 직접 실행하여 화면을 확인해본 결과, 이번 계획의 범위였던 공통 기능을 포함한 사용자 파트의 React 전환은 완전하지는 않지만 전반적으로 잘 이관된 상태임을 확인할 수 있었다.  &lt;br /&gt;&lt;br /&gt;이번 실험을 통해 각 모델의 강점이 어느 정도 분명하게 드러났다. &lt;br /&gt;&lt;br /&gt;특히 Gemini는 무료 버전을 사용했음에도 코딩 능력 자체는 충분히 확인할 수 있었다. 그러나 실제 실무에서 지속적으로 사용하기에는 사용량과 기능 제약이 존재했다. 반면 Codex는 최초 계획 수립, 구현, 이슈 정리, 병합 충돌 해결 등 실행과 연속성 측면에서 강점을 보였고, Claude는 상세 계획 수립과 리뷰, PR 검토 등 정교한 검토와 품질 보증 측면에서 가장 안정적이었다.  &lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/3759170172486340037/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/04/ai-vue-react.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3759170172486340037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3759170172486340037'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/04/ai-vue-react.html' title='사용기 -  클로드, 코덱스, 제미나이 기반의 AI 코딩 : VUE 프로그램을 REACT 로 변경'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTamQxz8owaxP4olPkPEOyfPtwEgdTCJbffkhhyphenhyphenIbZLV86Hh4_tFS45DvH6oqeOKi4Xz_RLTZR_Ed4VfWQpNJwDAnTnoiOf5GiBYelzJ9NTzKzZX1itDUHdPlw8gXMsfxCB4Az7qD8OPYuhmwJRJl0MCjzm6APA0T_0b27M2AWZCXkbOID7158p874RCyt/s72-w640-h544-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-04-02%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.12.38.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-2811673220762117269</id><published>2026-03-31T13:33:00.010+09:00</published><updated>2026-04-06T11:05:03.574+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="Claude Code"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><title type='text'>사용기 - 맥에서 클로드 코드(Claude Code) 사용하기 : Codex와 비교한 실사용 후기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클로드 역시 코덱스와 같이 무료 플랜에서는 코딩 기능(Claude Code) 사용이 불가 하고 유료 플랜에서만 가능하다. 클로드 코드는 터미널, VSCode , Desktop app, Web, JetBrains 을 지원하고 있다.&amp;nbsp; 테스트는 클로드 앱으로 진행했다. Desktop app 은 유료로 플랜을 업그레이드 하면 Code 탭이 활성화 되며 이를 클릭하고 로컬 저장소를 지정하는 것올 시작으로 바로 코딩 작업을 진행할 수 있었다.&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpBUQ1oA8KD2jUJFf7uuZec2XRjfK0C3EU_YH1eYAp0uNgvJ0cbGkpfTEKfcES39miC5HMg8OotvqhZ5q02adFslcpRgZfIJ4oPmTU7eEATaHBobU00XggrP0nbhZbTBE5LijAub1g9im1O9MpY9TGassSXX-_dVviyYzgYYzdJ7aXmNXX5omW3sT0ljYG/s802/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.25.40.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;90&quot; data-original-width=&quot;802&quot; height=&quot;45&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpBUQ1oA8KD2jUJFf7uuZec2XRjfK0C3EU_YH1eYAp0uNgvJ0cbGkpfTEKfcES39miC5HMg8OotvqhZ5q02adFslcpRgZfIJ4oPmTU7eEATaHBobU00XggrP0nbhZbTBE5LijAub1g9im1O9MpY9TGassSXX-_dVviyYzgYYzdJ7aXmNXX5omW3sT0ljYG/w400-h45/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.25.40.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;유료 플랜은 Pro 요금제를 사용했다.&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&lt;/span&gt;5시간 단위/주간 단위 사용량 제한 정책에 따라 가벼운 작업은 가능하지만 본격적인 코딩에는 무리가 있었고, 여러 테스트를 진행하는 과정에서 여러번 사용 제안이 걸려 추가로 $20 에 해당하는 토큰을 3회 구매해서 사용했다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클로드는 기본적으로&amp;nbsp;&lt;/span&gt;실사용 인상으로는 작업을 여러 단계로 나눠 처리하는 듯한 흐름이 있었고, 그만큼 토큰 사용량이 커진다고 느꼈다.&amp;nbsp;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;코딩 성능은 확연하게 멀티 즉 서브 에이전트를 사용하는 것과 하지 않는 것에는 차이가 발생한다.&amp;nbsp;&lt;/span&gt;여러 단계의 중간 결과가 정리되면서 응답 품질이 더 안정적으로 느껴졌고, 개인적으로는 그것이 결과 차이에 영향을 준다고 보았다.&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;(컨텍스트 오염 최소화)&lt;/span&gt;&lt;/p&gt;















&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;오류 해결 테스트 (코덱스와 클로드)&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;비교를 통한 성능 측정을 목적으로 간단하게 런타임 오류 메시지에 대한 분석을 각각 ① Claude Sonnet 4.6 , ② GPT-5.4&lt;span style=&quot;text-align: center;&quot;&gt;&amp;nbsp;(&lt;/span&gt;&lt;/span&gt;reasoning effort :&amp;nbsp;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: center;&quot;&gt;medium&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: center;&quot;&gt;)&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;을 사용하여 진행했다.&amp;nbsp;&lt;/span&gt;두 모델 모두 원인 분석 자체는 유효했지만, 이번 테스트에서는 Claude Sonnet 4.6 쪽이 번호와 표를 더 적극적으로 사용해 결과를 읽기 쉽게 정리해 주는 인상이 있었다.&lt;/p&gt;















&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBFkWgU96evL3yUg4WXLViMjXy_NkhDb7JzAq8gLmrG4pMf5DytaA-XGt9gP_jFUJhpR9OqQxXPL-KfR-w_JWu67pKFAvX8-f3J1IUpk8T5CGOOmPzpzR8Sc5a46KWwaApl2Ry1VAaoGZKO658x97sBUksMZMIiw5H1zcrAx5nAxNjhKhZy0jOvBrrsonP/s1542/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_10_41_59.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;998&quot; data-original-width=&quot;1542&quot; height=&quot;414&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBFkWgU96evL3yUg4WXLViMjXy_NkhDb7JzAq8gLmrG4pMf5DytaA-XGt9gP_jFUJhpR9OqQxXPL-KfR-w_JWu67pKFAvX8-f3J1IUpk8T5CGOOmPzpzR8Sc5a46KWwaApl2Ry1VAaoGZKO658x97sBUksMZMIiw5H1zcrAx5nAxNjhKhZy0jOvBrrsonP/w640-h414/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_10_41_59.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코덱스 (GPT 5.4&amp;nbsp;medium) 답변&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0i3wMnEUUtoEGsZQaCS59AM3GWjkxwtUacwwRDfC8UOGIlT-2OWVgzMDxGi7IElkhXecqCV1iWuG-VlrchpMkMbKHp4-g2TnpsENePCl2HFxEsFVsqTrSMN9XFxifM2mw2xnE4LfXpcQ42B8bgTlpFAAmuOyxQVdRgTa4_oMH8dmrqNkHorAIaEC3PBcX/s938/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_10_43_24.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;938&quot; data-original-width=&quot;721&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0i3wMnEUUtoEGsZQaCS59AM3GWjkxwtUacwwRDfC8UOGIlT-2OWVgzMDxGi7IElkhXecqCV1iWuG-VlrchpMkMbKHp4-g2TnpsENePCl2HFxEsFVsqTrSMN9XFxifM2mw2xnE4LfXpcQ42B8bgTlpFAAmuOyxQVdRgTa4_oMH8dmrqNkHorAIaEC3PBcX/w492-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_10_43_24.jpg&quot; width=&quot;492&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클로드 (Sonnet 4.6) 답변&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;“Claude는 분석만 요청했는데도 수정 방향까지 적극적으로 제안했다. 상황에 따라서는 장점이지만, 순수 분석만 원할 때는 과한 개입으로 느껴질 수 있었다.”( 아마도 코덱스의 경우는 호환 정책 파일들이 있어 발생한 것은 아닌가 하는 의심도 있다.)&lt;/p&gt;







&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기존 코드 기반 계획 수립 테스트 (코덱스와 클로드)&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음으로 소스 코드 분석을 실행하고 결과를 비교해 보았다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&quot;*** 는 사용자 시스템 구현에 의존하지 않고 사용자를 식별할 하기 위한 계약이다. 이 모듈 코드를 좋은점, 나쁜점, 개선점 측면에서 분석하고 결과를 보여줘.&quot;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ZUM-Smv_6Bak9xblgn6NB4EJQfed36Rk3JYIv3JKG35Wqd-w20_RYzoMsusp5SiSkJpJ7pS_dbIj1-hr3AnVD_YbpM2BZ9c5vasE2g3CQYtvyXY4J8qEWSSJXz8rmuHeehzXkLBhaIlFoLpT27doZ5hEO4Ih_Ri7l-zKymDdle5CjHDFIOJofsL7Ltaz/s1575/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_51_51.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1575&quot; data-original-width=&quot;740&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4ZUM-Smv_6Bak9xblgn6NB4EJQfed36Rk3JYIv3JKG35Wqd-w20_RYzoMsusp5SiSkJpJ7pS_dbIj1-hr3AnVD_YbpM2BZ9c5vasE2g3CQYtvyXY4J8qEWSSJXz8rmuHeehzXkLBhaIlFoLpT27doZ5hEO4Ih_Ri7l-zKymDdle5CjHDFIOJofsL7Ltaz/w300-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_51_51.jpg&quot; width=&quot;300&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Claude (Sonnet 4.6) 답변&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXhbWYepo3JFY2Hzxvr_Vso2R7F7Q5J0y6bBNEgg7FYCiMBoWudMcnPPH-FJBztprFH4i2g1cAtJwONJXTSUvWiNTX_Exbs4LNEq94mrKjunBs7KVXfK5A61n2m5vKhoyfFeTtrzL-j-mrafn_DBXvJGJhK0105vC4rVB5-oxm8ueZuH0-TD6kTGxHSAfC/s1211/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_52_29.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1211&quot; data-original-width=&quot;785&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXhbWYepo3JFY2Hzxvr_Vso2R7F7Q5J0y6bBNEgg7FYCiMBoWudMcnPPH-FJBztprFH4i2g1cAtJwONJXTSUvWiNTX_Exbs4LNEq94mrKjunBs7KVXfK5A61n2m5vKhoyfFeTtrzL-j-mrafn_DBXvJGJhK0105vC4rVB5-oxm8ueZuH0-TD6kTGxHSAfC/w414-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-30_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_52_29.jpg&quot; width=&quot;414&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Codex (GPT 5.4 medium) 답변&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결과가 예상과는 달랐는데 나쁜점의 경우 모두 거의 유사한 내용을 언급하고 있지만 좋은점과 개선점에서는 차이점이 있었다. 답변은 모두 코드에 근거하여 답변을 하고 있었다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;







&lt;p class=&quot;p1&quot;&gt;이번 테스트 기준으로 클로드는 ‘바로 손볼 포인트를 빠르게 정리해 주는 리뷰’에 가까웠고, 코덱스는 ‘왜 그렇게 바꿔야 하는지까지 설명하는 리뷰’에 가까웠다. 이번 항목에서는 개인적으로 코덱스&amp;nbsp;쪽 답변이 더 좋았다. 특히 구조적 설명과 개선 논리 제시에 강점이 있었다고 느꼈다.&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;①&amp;nbsp;클로드&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;구체적인 결과 = 항목화된 판정 + 예시 코드 즉,&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;무엇이 좋은지&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;무엇이 나쁜지&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;무엇을 바꿔야 하는지 &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;  &lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;를 표와 목록으로 끊어서 보여준다. (정리본 형태)&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px;&quot;&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;② 코덱스&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;구체적인 결과 = 모듈 의도 + 실제 사용처 + 개선 논리&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;즉,&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 모듈이 왜 존재하는지 &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;실제로 어디서 어떻게 쓰이는지 &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그래서 어떤 혼란이 생길 수 있는지 &lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;를 설명 흐름 안에서 보여준다. (리뷰 대화록 형태)&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_oDNsG8wPp8KHXnOIjzkCOsAeqhwXszzE4P7CnNLjmkBQ37YbLA9Db8QSRQaEUizsWhmFaoPIpvDCaaSoEghGkACSw9pMGsf_MfoJ50xF7VARI_QaxgA_FcA2z3xN0JvWcHpbLbJKo8lhmCY-WXG3_PMbSByfeYwjmkdCz-qHG2Q-zLscYixeYM4JOKoo/s1536/%E1%84%87%E1%85%B5%E1%84%80%E1%85%AD.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_oDNsG8wPp8KHXnOIjzkCOsAeqhwXszzE4P7CnNLjmkBQ37YbLA9Db8QSRQaEUizsWhmFaoPIpvDCaaSoEghGkACSw9pMGsf_MfoJ50xF7VARI_QaxgA_FcA2z3xN0JvWcHpbLbJKo8lhmCY-WXG3_PMbSByfeYwjmkdCz-qHG2Q-zLscYixeYM4JOKoo/w640-h426/%E1%84%87%E1%85%B5%E1%84%80%E1%85%AD.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;협업 테스트&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;(코덱스와 클로드)&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이번 테스트는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;①&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드와&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;②&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;코덱스 모두에게&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;코드 분석을 요청하고&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;①&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드의 경우 추가로 문서화 생성을 요청하고 해당 문서를&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;②&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;코덱스에게 검토 및 보완을 요청했다. 마지막으로 다시 수정된 문서를&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;①&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클로드를 통하여 검증하는 작업을 진행했다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;아래는 최종 검증에 있어 코덱트의 출력 화면이다.&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpcPXQiuWnDf9p-M6N6suaMh3Dt_uSYY5LozYKpzziCJd2bt_EwrfGYannK-fYcFzoUcPG3qeNQVVBcNOj2pChiGGXwVPyXdic_KwUMyLn1o3UzvzqxW8qvswzTUJt2LDGOikt_gJFOzBABxJoYXDJsuV5UOaD_eztrzA5ohJUc8jd64X2AGRjyQkPqSJl/s1432/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.34.17.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1276&quot; data-original-width=&quot;1432&quot; height=&quot;570&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpcPXQiuWnDf9p-M6N6suaMh3Dt_uSYY5LozYKpzziCJd2bt_EwrfGYannK-fYcFzoUcPG3qeNQVVBcNOj2pChiGGXwVPyXdic_KwUMyLn1o3UzvzqxW8qvswzTUJt2LDGOikt_gJFOzBABxJoYXDJsuV5UOaD_eztrzA5ohJUc8jd64X2AGRjyQkPqSJl/w640-h570/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.34.17.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;







&lt;p class=&quot;p1&quot;&gt;이번 실험에서는 단일 모델 하나만 쓰는 방식보다, 서로 다른 모델의 장점을 교차 활용하는 편이 결과를 더 안정적으로 만드는 가능성을 보였다. 서브 에이전트와 같은 기능을 적극적으로 쓰지 않고 프롬프트 중심의 단순 작업만 놓고 보면, 이번 체감상 코덱스보다 클로드가 더 일을 잘한다고 느껴졌다.&amp;nbsp;&lt;/p&gt;&lt;/span&gt;







&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;b style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;h4 style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이슈 기반 개발&lt;/span&gt;&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트에 앞서 코덱스에서 분석 및 작업 계획 테스트를 통하여 이슈를 생성하였고 클로드에서는 이미 생성된 특정 이슈를 기준으로 실제 구현 작업을 진행해 보았다. (개발은 언제나 항상 분석/설계 &amp;gt; 이슈 등록 &amp;gt; 구현 &amp;gt; 테스트 &amp;gt; PR 생성 &amp;gt; 리뷰 &amp;gt; 머지 순서로 하고 있다.)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;다음은 이슈 기반을 개발을 위하여 클로드에게 작업 가능성 확인 결과이다.&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;이슈 #163 에 대한 작업이 가능한가.&lt;/blockquote&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7ih6EidlEse6FswBugSHtIM801wBKnbc1eBB_SOiTuRHW61MFaxmw22PBZPjLMgD0wx8i_woYfCp2iKuIHakgNlpfjDbqfcuD5DqpPsPSBW6qCRSabEWllhTz1eCmYnGS8iLIBRMtWAbbSSE4iGXdT2pydWHaV1PZ9y_svDce1ESFcuyjvKNt75fjJb5n/s1486/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_00_21.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1170&quot; data-original-width=&quot;1486&quot; height=&quot;504&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7ih6EidlEse6FswBugSHtIM801wBKnbc1eBB_SOiTuRHW61MFaxmw22PBZPjLMgD0wx8i_woYfCp2iKuIHakgNlpfjDbqfcuD5DqpPsPSBW6qCRSabEWllhTz1eCmYnGS8iLIBRMtWAbbSSE4iGXdT2pydWHaV1PZ9y_svDce1ESFcuyjvKNt75fjJb5n/w640-h504/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_00_21.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;작업 이슈 내용을 바탕으로 기존 파일을 분석하여 수행했다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9_eaxC8fWDSRc7-_twlPVth_D2q0xtE9xJJOpCELSlgnFIRXXAS62FlVsddYot9eww5G32emxZeJ7gn1n1FcnNqi7eNA6JAgXDF-iyLpfm3xgCPEIB5UhdRo5LPQOFywg9ck9SarIVRwLitcRhV5bE_xWmYGQSwpikRHNm9rj1IeBvQT_PSX8_51GIHnA/s1500/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.11.46.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1292&quot; data-original-width=&quot;1500&quot; height=&quot;552&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9_eaxC8fWDSRc7-_twlPVth_D2q0xtE9xJJOpCELSlgnFIRXXAS62FlVsddYot9eww5G32emxZeJ7gn1n1FcnNqi7eNA6JAgXDF-iyLpfm3xgCPEIB5UhdRo5LPQOFywg9ck9SarIVRwLitcRhV5bE_xWmYGQSwpikRHNm9rj1IeBvQT_PSX8_51GIHnA/w640-h552/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.11.46.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;작업 완료 후 커밋과 PR 생성을 요청했고 해당 PR 을 코덱스가 검토하게 했다. 코덱스 검토 결과 1가지 문제가 발견되었고 이를 다시 클로드가 조치하도록 했다. (전후 맥락이 없는 상태에서 리뷰를 진행할 때는 좀더 많은 시간이 소요됨을 체감했다.)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLAjampxpidyzeR4T2txYtYRG9d12_CCI6qnJ5xbl1VJQfpWGPDjKWRMPlOFoJ2Eai4mSzJWfveJxy3bQO-lJ0GM30LN102_dE6n4MddsqHW986HIr4ZWVYOqDjweRJcr8d6JeFZ9tEF5HOJXxbKLSmmz91N3tjH5SK1kOmsL3nxbHPnkS7Rpfo99h47u/s1574/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_36_01.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1506&quot; data-original-width=&quot;1574&quot; height=&quot;612&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirLAjampxpidyzeR4T2txYtYRG9d12_CCI6qnJ5xbl1VJQfpWGPDjKWRMPlOFoJ2Eai4mSzJWfveJxy3bQO-lJ0GM30LN102_dE6n4MddsqHW986HIr4ZWVYOqDjweRJcr8d6JeFZ9tEF5HOJXxbKLSmmz91N3tjH5SK1kOmsL3nxbHPnkS7Rpfo99h47u/w640-h612/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_36_01.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;리뷰 결과를 클로드에서 입력하면 해당 내용을 확인하고 잘못 수정함을 인정하고 바로 수정까지 완료했다. (리뷰의 중요성이 확인됨)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhCxVM9i8PvX0ZfS2HlzRnwks2fDlmGQjZOO4mVdwWHvh37bRBUXVxNScOmGSmGNMLXNadcxkUKN1gtKVySSXZEn_rRlrC58jdk41z-sbRHEd1SRcDqvIK3UAfOzmwxx5O5NFafYRvk2eCov_SLe77gzspGYc1wMXNn06i6iE3hXqdKAcQmzYdi8RVAN2t/s1524/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_41_10.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;918&quot; data-original-width=&quot;1524&quot; height=&quot;386&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhCxVM9i8PvX0ZfS2HlzRnwks2fDlmGQjZOO4mVdwWHvh37bRBUXVxNScOmGSmGNMLXNadcxkUKN1gtKVySSXZEn_rRlrC58jdk41z-sbRHEd1SRcDqvIK3UAfOzmwxx5O5NFafYRvk2eCov_SLe77gzspGYc1wMXNn06i6iE3hXqdKAcQmzYdi8RVAN2t/w640-h386/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_41_10.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;조치결과에 대하여 코덱스에 다시 확인 요청을 한 결과 처리됨을 바로 확인해주었다. (이전 맥락이 있어 이번에는 바로 응답함)&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSCAkeO7HhfUDAnE9Gt_xYQS9y4i9M0LNQ4OB_MGYolQVhv229HusPPVKte6M_XW9s1QfrENAtX9y_-t4zD6E7aIPs7olEP2I-QPUGXABOnX8TtmxjVdILfu9QdwURMsyaGhbe9cb9E3FBSRfLvi4mMQVU6ISiK_6PBMemjPVyRbHIFHP0hfMh5xi0uZIj/s1556/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.46.24.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;718&quot; data-original-width=&quot;1556&quot; height=&quot;296&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSCAkeO7HhfUDAnE9Gt_xYQS9y4i9M0LNQ4OB_MGYolQVhv229HusPPVKte6M_XW9s1QfrENAtX9y_-t4zD6E7aIPs7olEP2I-QPUGXABOnX8TtmxjVdILfu9QdwURMsyaGhbe9cb9E3FBSRfLvi4mMQVU6ISiK_6PBMemjPVyRbHIFHP0hfMh5xi0uZIj/w640-h296/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.46.24.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;정리하면, 이번 테스트 기준으로 Claude는 정리형·실무형 리뷰에 강했고, Codex는 설명형·구조형 리뷰에 강했다. 따라서 둘 중 하나만 고르기보다, 분석·문서화·교차 검토 흐름으로 함께 활용할 때 더 큰 장점이 있을 수 있다고 본다.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/2811673220762117269/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/03/blog-post.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/2811673220762117269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/2811673220762117269'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/03/blog-post.html' title='사용기 - 맥에서 클로드 코드(Claude Code) 사용하기 : Codex와 비교한 실사용 후기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpBUQ1oA8KD2jUJFf7uuZec2XRjfK0C3EU_YH1eYAp0uNgvJ0cbGkpfTEKfcES39miC5HMg8OotvqhZ5q02adFslcpRgZfIJ4oPmTU7eEATaHBobU00XggrP0nbhZbTBE5LijAub1g9im1O9MpY9TGassSXX-_dVviyYzgYYzdJ7aXmNXX5omW3sT0ljYG/s72-w400-h45-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.25.40.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-3842458595386444016</id><published>2026-03-31T10:25:00.003+09:00</published><updated>2026-04-01T10:05:01.012+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="subagents"/><title type='text'>사용기 - 코덱스(Codex)에서 서브에이전트(Subagents) 활용하기</title><content type='html'>&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Subagents란, Codex가 하나의 큰 작업을 여러 개의 작은 작업으로 나누어 각각 별도의 보조 에이전트에게 맡긴 뒤, 그 결과를 다시 통합하는 병렬 작업 방식이다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;복잡한 작업, 코드베이스 탐색, PR 리뷰 처럼 여러 항목을 동시에 볼 때 특히 유용하다고 한다. &lt;span style=&quot;font-size: xx-small;&quot;&gt;&lt;a href=&quot;https://developers.openai.com/codex/subagents&quot; style=&quot;background-color: #cccccc;&quot; target=&quot;_blank&quot;&gt;OpenAI 개발자 가이드&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSSSgGuuqvFaLVBqIWfBFgvWd-gF4o5LbKFZ9gXXCnjpeQr1LAnagvrD1LL1HbyUnclUPysL-I_mEkTcjtuJ7dYqC_FHioQLO_cK8aD73PUy8x0hfzpDyfRNuKzj_UwNKkpxoCg93Larz0R8ra3aPljpQjq7nJo-0B1Se4iMvfGjFGqQAxECYs9HXXEQGR/s1536/aacf0da6560658ab9897e0fb820388a1d37b02c4e171000b25fe23632c9cb478.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSSSgGuuqvFaLVBqIWfBFgvWd-gF4o5LbKFZ9gXXCnjpeQr1LAnagvrD1LL1HbyUnclUPysL-I_mEkTcjtuJ7dYqC_FHioQLO_cK8aD73PUy8x0hfzpDyfRNuKzj_UwNKkpxoCg93Larz0R8ra3aPljpQjq7nJo-0B1Se4iMvfGjFGqQAxECYs9HXXEQGR/w640-h426/aacf0da6560658ab9897e0fb820388a1d37b02c4e171000b25fe23632c9cb478.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;서브에이전트(subagent)는 언제 어떻게 사용하나&lt;/h4&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;공식 문서에 따르면 컨텍스트 창(에이전트의 스레드 기억 공간)이 크더라도 요구사항, 제약조건, 의사결정 같은 핵심 정보 사이에 탐색 노트, 테스트 로그, 스택 트레이스, 명령 출력 같은 중간 결과가 과도하게 섞이면 모델의 응답 품질과 세션 신뢰성이 점차 떨어질 수 있다고 한다.&amp;nbsp; 이런 문제는 중요한 정보가 잡음에 묻히는 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;맥락 오염&lt;/b&gt;&lt;/span&gt;과, 관련 없는 세부 정보가 많아지면서 판단 성능이 저하되는 &lt;span class=&quot;s1&quot;&gt;&lt;b&gt;맥락 왜곡&lt;/b&gt;&lt;/span&gt;으로 설명할 수 있다. (&lt;a href=&quot;https://research.trychroma.com/context-rot&quot; target=&quot;_blank&quot;&gt;Context Rot: How Increasing Input Tokens Impacts LLM Performance&lt;/a&gt;)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;p1&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서브에이전트 워크플로(&lt;span face=&quot;&amp;quot;OpenAI Sans&amp;quot;, sans-serif&quot; style=&quot;background-color: white; color: #282828; font-size: 16px; letter-spacing: -0.16px;&quot;&gt;Codex가 병렬 에이전트를 실행하고 그 결과를 결합하는 워크플로&lt;/span&gt;)는 이러한 잡음을 메인 스레드에서 분리하여, 메인 에이전트는 핵심 요구사항과 최종 결과에 집중하고, 탐색·테스트·로그 분석 같은 읽기 중심 작업은 하위 에이전트가 병렬로 처리한 뒤 요약만 반환하도록 돕는다. 다만 병렬 에이전트는 읽기 작업에는 효과적이지만, 여러 에이전트가 동시에 코드를 수정하는 쓰기 중심 작업에서는 충돌과 조정 비용이 커질 수 있으므로 더 신중하게 운영해야 한다.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;즉 맥락 오류가 커질수 있는 큰 작업을 여러 덩어리로 나눌 수 있을 때 좋은 결과를 예상할 수 있는데. 예를 들면 “보안”, “버그”, “코드 품질”, “테스트 불안정성”을 각각 따로 검사시키는 식이다. Codex는 용사자가&amp;nbsp;&lt;u&gt;명시적으로 요청&lt;/u&gt;할 때만&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)를 실행한다. 그리고&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)가 늘어나면 그만큼 모델 호출과 도구 사용이 늘어서 토큰 비용도 더 많이 발생한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #eeeeee; color: #666666; font-size: small;&quot;&gt;&amp;nbsp;&lt;b&gt;Prompt 예시&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #666666; font-size: small;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음 작업을 subagent로 분할해줘.&lt;br /&gt;- explorer 1개: 인증 구조 파악&lt;br /&gt;- worker 1개: 로그인 API 구현&lt;br /&gt;- worker 1개: 테스트 추가&lt;br /&gt;- default 1개: 전체 결과 통합 정리&lt;br /&gt;모든 작업이 끝난 뒤 최종 보고서를 작성해.&lt;/span&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;“명시적으로 요청”한다는 것은, Codex가 알아서 subagent 를 만들 거라고 기대하는 것이 아니라, 프롬프트 안에 spawn, one agent per point, explorer subagent 를 생성, worker를 사용처럼 분업 지시를 직접 써주는 것이다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;h4&gt;Codex는 중간 관리자 역할을 수행&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;어떤&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)를 띄울지, 후속 지시를 어떻게 줄지, 결과를 언제 모을지 등을 Codex가 조율하고 마지막에는 결과를 합쳐서 하나의 응답으로 보여주는 역할을 한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;background-color: #eeeeee; color: #666666; font-size: small;&quot;&gt;&amp;nbsp;&lt;b&gt;Prompt 예시&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #666666; font-size: small;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;blockquote&gt;현재 브랜치와 main을 비교해서 PR을 검토해.&lt;br /&gt;항목별로 subagent를 하나씩 생성해.&lt;br /&gt;모든 subagent의 작업이 끝날 때까지 기다린 뒤, 항목별 결과를 요약해줘.&lt;br /&gt;1. 보안 이슈&lt;br /&gt;2. 코드 품질&lt;br /&gt;3. 버그 가능성&lt;br /&gt;4. 동시성 문제&lt;br /&gt;5. 테스트 불안정성&lt;br /&gt;6. 유지보수성&lt;/blockquote&gt;&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;이 프롬프트를 받으면 Codex는 다음을 조율한다.&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;ol start=&quot;1&quot;&gt;&lt;li&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;어떤&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)를 띄울지 정한다. &lt;br /&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;예를 들어 보안 검토용, 테스트 검토용, 유지보수성 검토용처럼 항목별&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)를 분리한다. 문서상 Codex는&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)를 생성하고 오케스트레이션하는 역할을 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;각&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)에 후속 지시를 전달한다. &lt;br /&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;예를 들어 “보안&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)는 인증/인가 흐름을 보라”, “테스트&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)는 누락된 테스트를 찾으라”처럼 작업을 나눠 보낸다. 공식 문서도 Codex가 follow-up instructions를 라우팅한다고 설명한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결과를 기다린다. &lt;br /&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;여러&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)가 동시에 돌고 있으면 Codex는 요청한 결과가 모두 준비될 때까지 기다린다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class=&quot;p2&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;마지막에 하나로 합친다. &lt;br /&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;각&amp;nbsp;&lt;span&gt;서브에이전트(&lt;/span&gt;subagent)의 결과를 항목별로 묶어 최종 응답으로 정리해 보여준다. 공식 문서에서는 consolidated&amp;nbsp;response로 설명한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h4&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;Codex 내장 서브에이전트(subagent)&lt;/h4&gt;d&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;efault(범용), worker(구현/수정 중심), explorer(읽기 중심 탐색) 같은 기본 agent가 이미 제공되고 있다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;default: 특별히 역할을 안 나눴을 때 쓰는 범용 담당&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;worker: 실제 수정, 구현, 정리, 반복 작업 담당&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;explorer: 파일 찾기, 구조 파악, 원인 추적 전 단계 담당&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style=&quot;color: #666666; font-family: Nanum Gothic; font-size: x-small;&quot;&gt;&lt;span style=&quot;background-color: #eeeeee;&quot;&gt;&amp;nbsp;&lt;b&gt;Prompt 예시&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;worker를 사용해서 로그인 API를 구현해줘.&lt;br /&gt;요구사항:&lt;br /&gt;- 이메일/비밀번호 로그인&lt;br /&gt;- JWT 발급 포함&lt;br /&gt;- 기존 SecurityFilterChain 구조를 유지&lt;br /&gt;- Controller, Service, DTO까지 구현&lt;br /&gt;- 관련 테스트도 함께 추가&lt;br /&gt;결과는 변경 파일 목록과 함께 요약해줘.&lt;/span&gt;&lt;/blockquote&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;커스텀 서브에이전트(subagent)&lt;/h4&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOML 파일로 “이 agent는 PR 리뷰 전용”, “이 agent는 문서 조사 전용”처럼 역할을 따로 정의할 수 있다. (최소한 name, description, developer_instructions 필요.)&amp;nbsp; 좋은 서브에이전트(subagent)는 공식 문서에 따르면 “좁고 명확한 역할을 가져야 한다”고 설명하고 있다. 즉, 하나의 서브에이전트(subagent)가 다 하게 하기보다 “코드 탐색용”, “보안 리뷰용”, “문서 조사용”처럼 나누는 게 좋다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span&gt;용자 정의 서브 에이전트를 사용하기 위해서&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;span dir=&quot;auto&quot; style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&lt;span dir=&quot;auto&quot; style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;특정 개발 작업을 위해 설계된 특수 AI 보조 도구인 Codex 서브에이전트&lt;/span&gt;&lt;/span&gt;&lt;span dir=&quot;auto&quot; face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, &amp;quot;Noto Sans&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;&quot; style=&quot;background-color: white; box-sizing: border-box; color: #1f2328; font-size: 16px; vertical-align: inherit;&quot;&gt;&lt;span dir=&quot;auto&quot; style=&quot;box-sizing: border-box; vertical-align: inherit;&quot;&gt;&amp;nbsp;의 최종 모음집 저장소&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://github.com/VoltAgent/awesome-codex-subagents/tree/main&quot; target=&quot;_blank&quot;&gt;Awesome Codex Subagents&lt;/a&gt;&amp;nbsp;&lt;span face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, &amp;quot;Noto Sans&amp;quot;, Helvetica, Arial, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;&quot; style=&quot;background-color: white; color: #1f2328; font-size: 16px;&quot;&gt;을 활용했다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM34BTBbrFnDyCXGdyv9M5j5XL6u1EQyGiz6ul7e7ndnhJZleevjU_b4ayPN6iiNiFuUOiQwBr_jVW-TSM_96QBg2jCMhgc3bbfJW4d_Ma2zW9d8pgpwC4zf9vYri89IlzQAoITKnLM1eTqUHY95wXJhB2EeNdrahP-QdkWKbV02WJylOo8W5YkeLFBWT1/s1500/564992613-35f56654-e3e7-4023-a7d5-acd5215455de.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;500&quot; data-original-width=&quot;1500&quot; height=&quot;214&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjM34BTBbrFnDyCXGdyv9M5j5XL6u1EQyGiz6ul7e7ndnhJZleevjU_b4ayPN6iiNiFuUOiQwBr_jVW-TSM_96QBg2jCMhgc3bbfJW4d_Ma2zW9d8pgpwC4zf9vYri89IlzQAoITKnLM1eTqUHY95wXJhB2EeNdrahP-QdkWKbV02WJylOo8W5YkeLFBWT1/w640-h214/564992613-35f56654-e3e7-4023-a7d5-acd5215455de.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;







&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;최종적으로는 AI 지원 개발을 일관된 규칙, 템플릿, 자동화 스크립트로 표준화해 배포할 수 있게 만든 DevOps 정책 템플릿 저장소를 구성하여 사용했다.&amp;nbsp;( &lt;a href=&quot;https://github.com/andang72/devops-policy-template&quot;&gt;https://github.com/andang72/devops-policy-template&lt;/a&gt; )&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, sans-serif&quot; style=&quot;background-color: oklab(0.159065 0.00000723451 0.00000317395 / 0.05); color: #0d0d0d; font-size: 13px; white-space-collapse: preserve;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;&lt;span style=&quot;background-color: oklab(0.159065 0.00000723451 0.00000317395 / 0.05); color: #0d0d0d; font-size: 13px; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;먼저 세부 계획을 병렬로 	&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: oklab(0.159065 0.00000723451 0.00000317395 / 0.05); color: #0d0d0d; font-size: 13px; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서브에이전트 1: 현재 패키지/모듈 구조 분석
서브에이전트 2: 중복 책임, 순환 의존, 경계 위반 탐지
서브에이전트 3: 테스트 영향 범위와 회귀 위험 분석
서브에이전트 4: 후보 리팩토링 포인트 요약 &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: oklab(0.159065 0.00000723451 0.00000317395 / 0.05); color: #0d0d0d; font-size: 13px; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;를 통해서 수립해줘.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;background-color: oklab(0.159065 0.00000723451 0.00000317395 / 0.05); color: #0d0d0d; font-size: 13px; white-space-collapse: preserve;&quot;&gt;&lt;/span&gt;이렇게 프롬프트를 작성하면 코덱스는 병렬 작업에 맞게 작업 계획을 수립한다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlijxJfqwSUzVZAv6RL3mxRGXNc4ywsK31Iw5EbLhK8KnPToy3AmRv1MnDjjs6FDLkYobuSppFG1yph5JPHgyfJy8bKkKLAsA4QIyCaox4i68B21k6zP6nbG7JwhM1Yof6EO3Y1kBkEqhQU2xgDR7Sh-j1qPQLC6XvJhZv0FqBGwYXGmcCVTAkXZjbXSQM/s1502/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-31%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.50.30.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1502&quot; data-original-width=&quot;1386&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlijxJfqwSUzVZAv6RL3mxRGXNc4ywsK31Iw5EbLhK8KnPToy3AmRv1MnDjjs6FDLkYobuSppFG1yph5JPHgyfJy8bKkKLAsA4QIyCaox4i68B21k6zP6nbG7JwhM1Yof6EO3Y1kBkEqhQU2xgDR7Sh-j1qPQLC6XvJhZv0FqBGwYXGmcCVTAkXZjbXSQM/w590-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-03-31%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.50.30.png&quot; width=&quot;590&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;계획이 수립되면 이슈를 등록하게 하고 순서대로 작업을 아래와 같이 특정 서브에이전트에게 진행을 요청한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVlyisaGDeKdLtkmPfOCLgMXyhMlSIQeovHJ1FsnFkP9Mpzo5VQeKgsBU4oMrNsX6jE7u0a3FJNE-4J_bfFURbkx7uSEJ66OP7Iiqdue0-BgOI4pFlQ2TTAq3BnyHuc6XMpcJbgTbe6wkrhbOrOPjtbySKSZL61pa6pcZCPqOzfMhH9Ne_ClrOLQRAIAjQ/s1590/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_8_56_06.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1542&quot; data-original-width=&quot;1590&quot; height=&quot;621&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVlyisaGDeKdLtkmPfOCLgMXyhMlSIQeovHJ1FsnFkP9Mpzo5VQeKgsBU4oMrNsX6jE7u0a3FJNE-4J_bfFURbkx7uSEJ66OP7Iiqdue0-BgOI4pFlQ2TTAq3BnyHuc6XMpcJbgTbe6wkrhbOrOPjtbySKSZL61pa6pcZCPqOzfMhH9Ne_ClrOLQRAIAjQ/w640-h621/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_8_56_06.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서브에이전트에 의한 작업은 좌측 스레드 목록이나 하단의 작업 목록 아래의 background agents (@ to tag agents ) 를 통하여 확인 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgGtI-6UxqaHNOCwoMuT73u1xsVqaxBVISCUTxtXKuqffdwc0Z6wSPvKzFPQ_7Y9Y3OBMpOkdU3N30qTRZ-i4plwJXqbDr7SxkR1LNQbNi-PCQ4qL9ip9fwggQXaMC-E-kZrccEykZuq2Ra39xC-ofArqKXLAPUQQmh_YHFMgchrijZPfsnBsCQfnG5jbr/s586/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_8_56_52.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;300&quot; data-original-width=&quot;586&quot; height=&quot;205&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgGtI-6UxqaHNOCwoMuT73u1xsVqaxBVISCUTxtXKuqffdwc0Z6wSPvKzFPQ_7Y9Y3OBMpOkdU3N30qTRZ-i4plwJXqbDr7SxkR1LNQbNi-PCQ4qL9ip9fwggQXaMC-E-kZrccEykZuq2Ra39xC-ofArqKXLAPUQQmh_YHFMgchrijZPfsnBsCQfnG5jbr/w400-h205/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_8_56_52.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;좌측 메뉴&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRGnhEo7pSl4RImtS43HoVu-LLnif12Xg-PQxSCDCg1o-SwrRgogEJJYPQ37SUhi0DPrhfvkYd4YR2uHzm87x3iz-mdjKbyNA8VSYskvBRWuhhNBJwNEh43_FzC8vme7RFTlJQjVmbiCTEV80HWK9UqEFZPk9W7mh8CNOGUv6d2uqJCiUnqdfGFD4MNPmt/s1592/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_8_57_03.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;810&quot; data-original-width=&quot;1592&quot; height=&quot;326&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRGnhEo7pSl4RImtS43HoVu-LLnif12Xg-PQxSCDCg1o-SwrRgogEJJYPQ37SUhi0DPrhfvkYd4YR2uHzm87x3iz-mdjKbyNA8VSYskvBRWuhhNBJwNEh43_FzC8vme7RFTlJQjVmbiCTEV80HWK9UqEFZPk9W7mh8CNOGUv6d2uqJCiUnqdfGFD4MNPmt/w640-h326/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-31_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_8_57_03.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;하단 메뉴&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서브에이전트를 도입하면 단순 오류 수정이 아닌 기존 코드를 분석하여 기능을 수정하거나 추가하는 경우 확연하게 결과가 개선되는 것을 확인할 수 있었다. 다만 서브에이전트를 사용하는 경우 토큰 소비가 크게 증가하기 때문에 이부분에 대한 사전 고려가 필요할 것 같다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/3842458595386444016/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/03/codex-subagents.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3842458595386444016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3842458595386444016'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/03/codex-subagents.html' title='사용기 - 코덱스(Codex)에서 서브에이전트(Subagents) 활용하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSSSgGuuqvFaLVBqIWfBFgvWd-gF4o5LbKFZ9gXXCnjpeQr1LAnagvrD1LL1HbyUnclUPysL-I_mEkTcjtuJ7dYqC_FHioQLO_cK8aD73PUy8x0hfzpDyfRNuKzj_UwNKkpxoCg93Larz0R8ra3aPljpQjq7nJo-0B1Se4iMvfGjFGqQAxECYs9HXXEQGR/s72-w640-h426-c/aacf0da6560658ab9897e0fb820388a1d37b02c4e171000b25fe23632c9cb478.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-1116189087915049288</id><published>2026-03-23T13:23:25.441+09:00</published><updated>2026-03-23T13:23:25.441+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><title type='text'>사용기 - 맥에서 Codex 앱 경험하기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;https://openai.com/ko-KR/codex/get-started/ 방문하여 맥용 앱을 다운로드하여 설치하였다. (지금은 윈도우즈 버전까지 출시되었다.)&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo-WBkZQY97whz96MrtZFn_4EYVP-R_7nROCjXFceRZHVUB4MezNiicx1zmni9GDIzwvgvj9xYFde8eotWq8I6ZN8zmW0SRIbC7YWeRQ47S-whbAhZKTitjSDrGF08U0bnzmZ0d-4ztvzCvUGW5Wzmd84IUQAKKi_Q9ZNbxz0Dxd7dSw95RzdgOgvc56Em/s2962/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-02-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.59.18.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1650&quot; data-original-width=&quot;2962&quot; height=&quot;356&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo-WBkZQY97whz96MrtZFn_4EYVP-R_7nROCjXFceRZHVUB4MezNiicx1zmni9GDIzwvgvj9xYFde8eotWq8I6ZN8zmW0SRIbC7YWeRQ47S-whbAhZKTitjSDrGF08U0bnzmZ0d-4ztvzCvUGW5Wzmd84IUQAKKi_Q9ZNbxz0Dxd7dSw95RzdgOgvc56Em/w640-h356/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-02-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.59.18.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;처음 앱을 실행하면 &lt;u&gt;Select a project&lt;/u&gt; 창이 보여지는데, 로컬에 존재하는 여러 Git&amp;nbsp;프로젝트 목록을 보여주고 선택하게 하는 것이 처음 사용하는 사용자에게는 도움이 될 것 같다.&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg65tguxxnDlMDBFhXjnzKiFAOFO1N4q-9LaxnItb0xNsILuRexxt3kFsXlsAiI66hyzQSBoX8HTlTUHjnqlE9YloddIVhFdoY_WFuzUVyCCxQ-5_6w7aCBflMgWIPLiJH3putbuzZih_1pDSaBzxkb1FXLl_Egl5IlB0YFQha5_f_-EX8QfMSL-Nk49HP9/s1344/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-02-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.02.00.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1344&quot; data-original-width=&quot;1344&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg65tguxxnDlMDBFhXjnzKiFAOFO1N4q-9LaxnItb0xNsILuRexxt3kFsXlsAiI66hyzQSBoX8HTlTUHjnqlE9YloddIVhFdoY_WFuzUVyCCxQ-5_6w7aCBflMgWIPLiJH3putbuzZih_1pDSaBzxkb1FXLl_Egl5IlB0YFQha5_f_-EX8QfMSL-Nk49HP9/w400-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-02-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.02.00.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;VisualStudio Code 에서 Codex 확장을 사용하여 코딩에 활용하고 있었는데 Codex 앱은 좌측에 이들 프로젝트 목록(앞선 Select a project 에서 선택함 ) 과 그동안 해당 프로젝트에서 입력했었던 프롬프트까지 모두 보여준다. 또한 작업중에도 프롬프트는 계속 입력이 가능한데 입력된 프로프트들은 스티어링(Steering) 상태가 되는데 진행 중인 프롬프트가 완료되면 바로 이어서 진행하게 된다.&amp;nbsp; 이점은 미리 다수의 프롬프트를 순차적으로 입력해두면 이어서 연속적으로 작업을 수행하는 점이 좋았다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;스티어링(Steering)은&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;background-color: #fcff01;&quot;&gt;“처음부터 다시 시키지 않고, 지금 하던 작업에 추가 지시를 넣어 방향 수정하는 것”&lt;/span&gt;으로&amp;nbsp;조금 더 구체적으로 보면, Codex App Server 문서에는 turn/steer 가 있고, 이것은 현재 실행 중인 turn에 사용자 입력을 덧붙여 새로운 turn을 만들지 않고 계속 진행하게 하는 방식이라고 한다.&lt;/span&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSAL_McWOXlDcgLXYV83qNm8o29ZoPoWMaA_e-yyJnIzNL7s_E6iOUulniUj-6k5hQ940yMEkW_hqP6C0TlXRh9d_gnU8rfrKTgdPwue61_FB6Bq2nJ7Sfwq7fE6gdj3IAuMdkaps6APPPR_ai5z1u-9m0SRHlnp5vHc-roMtKxOP3EkDe-X2m3y8u_f3M/s2624/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-02-05_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_17_14.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;2216&quot; data-original-width=&quot;2624&quot; height=&quot;541&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSAL_McWOXlDcgLXYV83qNm8o29ZoPoWMaA_e-yyJnIzNL7s_E6iOUulniUj-6k5hQ940yMEkW_hqP6C0TlXRh9d_gnU8rfrKTgdPwue61_FB6Bq2nJ7Sfwq7fE6gdj3IAuMdkaps6APPPR_ai5z1u-9m0SRHlnp5vHc-roMtKxOP3EkDe-X2m3y8u_f3M/w640-h541/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-02-05_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_17_14.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;모델은 응답 속도 이슈로 GPT-5.2-Codex Low 을 사용했다. 사실 High 모델을 사용해도 별 품질 차이를 느끼지는 못했지만 속도는 매우 느렸다. 사용 과정에서 모델이 추가되어 GPT-5.3-Codex Low 를 주로 사용하게 되었다.&lt;/span&gt;&lt;/p&gt;&lt;p data-pm-slice=&quot;0 0 []&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트 과정에서 사용한 코딩 환경 및 목표는 아래와 같다.&lt;/span&gt;&lt;/p&gt;&lt;p data-pm-slice=&quot;0 0 []&quot; style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;eGovFrame 4.3.0 (Spring 5.3.37, Spring Security 5.8.13) + 자체 프레임워크 기반 웹 프로그램을&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;전자정부 프레임워크 와 자체 프레임워크 기반의 웹 프로그램을 스프링 부트 기반으로 변경&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;자체 프레임워크는 최신 버전으로 다시 적용, 적용 불가시 신규 코드 작성하여 적용.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;UI 부분의 오류 제거 및 중복 파일 삭제. 특희 kendoui 관련 부분 최적화.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;패키지 명 등 구조 리팩토링 (유지보수를 고려하여)&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코딩 진행은 프로젝트의 단일 스레드가 아니라&amp;nbsp; &lt;u&gt;context window&lt;/u&gt; 크기를 고려해서 작업 단위를 다음과 같이 쪼게서 다중 스레드로 진행했다. 참고로 context window 는 지금 스레드(세션) 에서 사용중인 대화전체 기억을 의미하는데 메뉴에서는 아래와 같은 형태로 보여주고 있다.&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhToDXTKhxO6fPWPLHo1Mj1-_Zz6L47OlIT_qpGe1H_iBj_obAs4qAcDiK4dWRkbHltoHSoPaXMLrRgCPb9wKR6lb6UM-67E2JFAduXFHImVyoPtjFofzDIdDxPiRLd7bTtIjCBa_lFN2wWg9V4DbhmfBOM1XIlIfGKRtwrJz228CIkL8I7fPItGGPSSkCb/s1732/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-03_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_39_57.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;326&quot; data-original-width=&quot;1732&quot; height=&quot;120&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhToDXTKhxO6fPWPLHo1Mj1-_Zz6L47OlIT_qpGe1H_iBj_obAs4qAcDiK4dWRkbHltoHSoPaXMLrRgCPb9wKR6lb6UM-67E2JFAduXFHImVyoPtjFofzDIdDxPiRLd7bTtIjCBa_lFN2wWg9V4DbhmfBOM1XIlIfGKRtwrJz228CIkL8I7fPItGGPSSkCb/w640-h120/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2026-03-03_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_39_57.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;위 화면에서 현 코덱스의 최대 258k 토큰을 기억할 수 있고 지금 까지 176k 토큰 기억 메모리를 사용중이라는 의미이다.&amp;nbsp;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기존 프로젝트 구조 분석을 통한 리팩토링(가능한 기존 구조 유지).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;리팩토링 결과물 디버깅을 통한 런타임 오류 수정.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;새로운 자체 프레임워크 적용 (단계적 기존 모듈 삭제).&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;업무모듈 리팩토링 기준 설정 및 리팩토링 진행.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;리팩토링 결과물 검토에 따른 코드 개선.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코드 기반 수정에 따른 UI (jsp) 런타임 오류 수정.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;각 스레드가 이전 스레드 작업 또는 다른 스레드 작업의 이력을 확인 할 수 있게 작업 후에는 README, CHANGELOG, TODO 등의 문서를 작성/업데이트 하게 했다. 스레드가 다른 스레드 작업을 이어 계속 진행할 수 있도록 문서화는 최종 목표, 진행 현황등을 파악 할 수 있데 작성을 지시했다.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;또한 코딩 성능 개선을 위해서 OpenAI의 창립 멤버이자 전 Tesla AI 이사인 안드레 카파시(Andrej Karpathy)가 신경망(Neural Networks) 및 딥러닝 모델을 훈련하고 디버깅할 때 제안한 핵심 원칙과 모범 사례(Best Practices) 파일은  SKILL.md 파일을 추가하여 항상 가이드 라인을 준수하게 했다. 적용 후 처음은 그 차이를 인지하지 못했지만 작업을 반복하는 과정에서 codex 가 작업의 범위를 축소하고 언제가 작은 단위로 쪼게서 작업을 수행하는 것을 확인 할 수 있었다. 이런 이유에서 계속해서 프롬프트를 입력하여 다음 작업을 진행하도록 해야 했다.&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예상보다 작업 속도와 품질은 매우 높았다. 예를 들면 기존 스프링 프레임워크 환경에서 xml 로 정의된 컨텍스트 파일들을 java 코드로 변경하는 작업의 경우 기존 코드와의 연관성 등을 고려하면 상당한 난이도 작업이지만 큰 실수 없이 코드 만들어 낸다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;주의할 것은 반복적으로 개선 작업을 진행하는 과정에 이미 완료된 코드도 같이 수정하는 경우가 많아 다시 확인해서 보완 조치 하는 경우가 빈번하게 발생한 것은 많은 집중을 요구했다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결국 작업을 반복하여 지속적으로 코드를 개선하는 경우는 중간 중간 품질을 확인하고 잘못된 점을 지적해야 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;어느 정도 리팩토링 작업이 완료되고 UI 기능을 변경하는 작업을 해보았다. 화면의 경우 더 쉽게 처리하는 것 같다. 예를 들어 기존에 어떤 메뉴는 로그인 전에 클릭하면 로그인 창을 보여주었는데 어떤 메뉴는 경고 후 메인 페이지로 이동으로 구현되어 있는것을 수정해달라고 요청했고 결과(작업속도, 품질)는 만족스러웠다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;코딩 이외의 작업도 진행했는데, 로컬 도커에 이미 설치된 mysql 에&amp;nbsp; 연결된 개발 서버 디비의 모든 데이터를 포함하여 이관해달라고 작업을 요청해보았다. 작업을 위한 몇번의 권한 요청을 했고, 진행 과정에서 오류가 발생하면 바로 해결방안을 찾아서 작업을 이어 진행했다. 이관 완료 후에는 검증을 위하여 테이블 과 데이터 건수 검증까지 이어서 처리했다, 이 모든 작업을 스스로 진행하고 작업을 위한&amp;nbsp; 권한 요청에 대한 승인 만허용하여 데이터 이관을 완료 했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;마지막으로 Codex 사용에 있어 주요했던 것은 정책(코딩 규칙)을 수립하고 규칙에 따라 작업을 진행할 것을 요청한 점이였다.&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/1116189087915049288/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/03/codex.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1116189087915049288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1116189087915049288'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/03/codex.html' title='사용기 - 맥에서 Codex 앱 경험하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo-WBkZQY97whz96MrtZFn_4EYVP-R_7nROCjXFceRZHVUB4MezNiicx1zmni9GDIzwvgvj9xYFde8eotWq8I6ZN8zmW0SRIbC7YWeRQ47S-whbAhZKTitjSDrGF08U0bnzmZ0d-4ztvzCvUGW5Wzmd84IUQAKKi_Q9ZNbxz0Dxd7dSw95RzdgOgvc56Em/s72-w640-h356-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202026-02-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%208.59.18.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-6891696748176392203</id><published>2026-03-05T17:15:00.041+09:00</published><updated>2026-03-10T13:01:59.380+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="codex"/><category scheme="http://www.blogger.com/atom/ns#" term="coding agent"/><category scheme="http://www.blogger.com/atom/ns#" term="VSCode"/><title type='text'>사용기 - 윈도우에서 AI 코딩 사용하기 (Codex)</title><content type='html'>&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;Fsg96&quot; data-complete=&quot;true&quot; data-processed=&quot;true&quot; data-sfc-cb=&quot;&quot; data-sfc-cp=&quot;&quot; jsaction=&quot;rcuQ6b:&amp;amp;DbfF8_n|npT2md&quot; jscontroller=&quot;KHhJQ&quot; jsuid=&quot;DbfF8_n&quot; style=&quot;-webkit-text-stroke-width: 0px; background-color: white; color: #0a0a0a; font-family: Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;&quot;&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;







과거에는 개발자가 직접 코드를 작성하고 디버깅하는 방식이 일반적이었으나, 현재는 AI가 코드 생성, 테스트, 디버깅, 문서 작성 등 다양한 개발 작업을 지원하는 환경으로 전환되고 있다. 특히 AI 코딩 도구와 에이전트 기반 개발 환경의 확산으로 인해 개발 생산성을 크게 향상시킬 수 있으며, 복잡한 시스템 개발에서도 효율적인 작업이 가능해지고 있다.&lt;br /&gt;&lt;br /&gt;이러한 변화에 따라 많은 개발 조직에서는 AI 기반 개발 도구를 적극적으로 도입하고 있으며, 개발 환경 또한 이러한 도구들이 원활하게 동작할 수 있도록 재구성하고 있다. 특히 AI 기반 개발 환경에서는 코드 분석, 자동 테스트, 컨테이너 실행, 인프라 구성 등 다양한 작업이 동시에 이루어지기 때문에 안정적이고 일관된 개발 환경이 중요하다.&lt;br /&gt;&lt;br /&gt;많은 기업에서 개발자의 작업 환경으로 Windows 운영체제를 사용하고 있으나, 실제 소프트웨어 실행 환경은 대부분 Linux 기반 서버나 컨테이너 환경에서 운영되는 경우가 많다. 이러한 환경 차이는 개발 단계에서 다양한 문제를 발생시킬 수 있으며, 특히 라이브러리 의존성, 파일 시스템 차이, 실행 환경 차이 등으로 인해 개발과 운영 환경 간의 불일치가 발생할 가능성이 있다.&lt;br /&gt;&lt;br /&gt;이러한 문제를 해결하기 위해 Windows 환경에서는 WSL(Windows Subsystem for Linux)을 활용한 개발 환경 구성이 널리 사용되고 있다.&lt;br /&gt;&lt;br /&gt;WSL은 Windows 운영체제 내부에서 Linux 환경을 실행할 수 있도록 지원하는 기능으로, 개발자는 Windows 환경을 유지하면서도 Linux 기반 개발 도구와 환경을 그대로 사용할 수 있다. 이를 통해 개발자는 Linux 서버 환경과 동일한 개발 환경을 로컬에서 구축할 수 있으며, 다양한 오픈소스 개발 도구와 패키지를 보다 안정적으로 사용할 수 있다.&lt;br /&gt;&lt;br /&gt;특히 AI 기반 개발 환경에서는 Python 기반 AI 도구, 컨테이너 환경, 패키지 관리 시스템 등 Linux 환경에 최적화된 기술들이 많이 사용된다. 예를 들어 AI 모델 실행 환경, 벡터 데이터베이스, 컨테이너 기반 서비스 등은 Linux 환경에서 보다 안정적으로 동작하는 경우가 많다. WSL을 활용하면 이러한 기술을 Windows 환경에서도 동일하게 사용할 수 있어 개발 환경의 일관성을 확보할 수 있다.&lt;br /&gt;&lt;br /&gt;또한 WSL 환경에서는 Docker, Kubernetes, Git, Python 패키지 관리자 등 다양한 개발 도구를 Linux 환경과 동일하게 사용할 수 있으며, 이는 AI 기반 개발 도구와의 호환성을 높이는 데에도 중요한 역할을 한다. 최근 등장한 AI 기반 개발 도구들 또한 Linux 환경을 기본 실행 환경으로 가정하고 설계되는 경우가 많기 때문에, WSL 기반 개발 환경은 AI 코딩 도구의 활용성을 높이는 데에도 효과적이다.&lt;br /&gt;&lt;br /&gt;개발자는 Windows 환경에서 Visual Studio Code와 같은 개발 도구를 사용하면서도, 실제 코드 실행과 빌드 작업은 WSL 내부의 Linux 환경에서 수행할 수 있다. 이러한 방식은 Windows의 편리한 사용자 환경과 Linux의 안정적인 개발 환경을 동시에 활용할 수 있다는 장점을 가진다. 특히 Visual Studio Code는 WSL과의 통합 기능을 제공하여 Windows에서 실행되는 IDE가 WSL 내부의 Linux 환경에 직접 연결되어 개발 작업을 수행할 수 있도록 지원한다.&lt;br /&gt;&lt;br /&gt;이와 같은 구조는 AI 기반 개발 환경에서도 매우 효과적으로 활용될 수 있다. 예를 들어 AI 코딩 도구를 통해 생성된 코드가 Linux 기반 컨테이너 환경에서 바로 테스트되도록 구성하거나, 자동화된 빌드 및 테스트 프로세스를 Linux 환경에서 실행하도록 설정할 수 있다. 이러한 환경은 실제 운영 환경과 유사한 개발 환경을 제공함으로써 개발 과정에서 발생할 수 있는 환경 차이를 최소화하는 데 도움을 준다.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8PsukGBn432g86DWwy6PG9fcSNkJ02b0CS7No79Qy2grV0XfmGOrl3LLwEonQK3RmvXzowxSfna_iYnmXM3ASSh3HW0jfwwP13OGfsWIKxZ8dDIsHgAjk8Y2L2m0YoUIEn0XsLL77j9eM352aR6VCMDtj70QO0OUV03sJaGcBNZ366obVrVWbRagsGbA/s1536/image2.png&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1536&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8PsukGBn432g86DWwy6PG9fcSNkJ02b0CS7No79Qy2grV0XfmGOrl3LLwEonQK3RmvXzowxSfna_iYnmXM3ASSh3HW0jfwwP13OGfsWIKxZ8dDIsHgAjk8Y2L2m0YoUIEn0XsLL77j9eM352aR6VCMDtj70QO0OUV03sJaGcBNZ366obVrVWbRagsGbA/w640-h426/image2.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;결론적으로 AI 기반 개발 환경을 도입하는 과정에서는 단순히 AI 도구를 사용하는 것뿐만 아니라, 이러한 도구들이 안정적으로 동작할 수 있는 개발 환경을 구축하는 것이 중요하다. Windows 환경을 사용하는 개발 조직의 경우 WSL을 활용한 Linux 기반 개발 환경을 함께 구성함으로써 개발 환경의 일관성을 확보하고, AI 기반 개발 도구와의 호환성을 높이며, 전체 개발 생산성을 향상시킬 수 있다. 이러한 접근 방식은 향후 AI 중심 개발 환경으로의 전환 과정에서도 중요한 기반이 될 것으로 기대된다.&lt;br /&gt;&lt;h3&gt;&lt;br /&gt; &lt;br /&gt;WSL 환경 설치하기&amp;nbsp;&lt;/h3&gt;&lt;p&gt;윈도우에서 &quot;PowerShell&quot; 을&amp;nbsp; 검색창에 입력하면 설치된 경우 PowerShell 터미널을 그렇지 않는 경우는&amp;nbsp; 설치를 위한 Microsoft Store 로 이동한다. 설치를 완료하면 열기 버튼이 활성화 되는데 이를 클릭해도 &quot;PoswerShell&quot; 이 실행된다.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSUKaT_Htif5xP6Q0oC-hw0_zLuuYSlJc2J1gS41YykBdLaTbuwL91_ZATZDY8gayKONgRQbstHka_VR60A8I1j3OZsrlBAYrVy3R4UPQl9cWxOEltZ4F_5_MUkFo7DUjK1YjGX7UP0kvWoFSyRBt6K3RlndQu_PiSLVofO-M6hFr8kCoScvWRpmqn7Aw2/s1282/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20092715.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;895&quot; data-original-width=&quot;1282&quot; height=&quot;446&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSUKaT_Htif5xP6Q0oC-hw0_zLuuYSlJc2J1gS41YykBdLaTbuwL91_ZATZDY8gayKONgRQbstHka_VR60A8I1j3OZsrlBAYrVy3R4UPQl9cWxOEltZ4F_5_MUkFo7DUjK1YjGX7UP0kvWoFSyRBt6K3RlndQu_PiSLVofO-M6hFr8kCoScvWRpmqn7Aw2/w640-h446/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20092715.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;코딩 에이전트(Codex CLI 같은 것)나 레포 자동 빌드/테스트는 윈도우보다 리눅스 환경이 명령 실행/경로/권한 문제가 적어서 안정적이라고 한다. 이런 이유에서 코딩 에어전트 이용을 위해서는&amp;nbsp;“윈도우에선 WSL2(Windows Subsystem for Linux 2) 권장” 이 자주 언급된다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;설치 여부는 &quot;&amp;nbsp;wsl -l -v&quot; 명령을 PowerShell 에 입력하여 확인 할수 있다.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;wsl --status&lt;/p&gt;&lt;p&gt;wsl -l -v&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinQGDCzPhxeMgniq2Hm_c2U6a0xaudvMgX4EzkBLqfhWixL-Egmai88ZNKLcTSnHZZ2bLiZEcmwYAOdRtjDpJBYPk8QVXxXrbATr4OWDroF6Aixqt5cekTbC-V3Ms1q4fmWH4DYHYRwXjuyOR8sKje6ZmfOeBTwoehzdL_DexFbupqsTGYJCjJgELK3bCi/s1314/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20094902.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;762&quot; data-original-width=&quot;1314&quot; height=&quot;372&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinQGDCzPhxeMgniq2Hm_c2U6a0xaudvMgX4EzkBLqfhWixL-Egmai88ZNKLcTSnHZZ2bLiZEcmwYAOdRtjDpJBYPk8QVXxXrbATr4OWDroF6Aixqt5cekTbC-V3Ms1q4fmWH4DYHYRwXjuyOR8sKje6ZmfOeBTwoehzdL_DexFbupqsTGYJCjJgELK3bCi/w640-h372/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20094902.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;가장 쉬운 설치 방법은 &quot;PowerShell&quot; 을 관리자 계정으로 실행하고&amp;nbsp; &quot;&lt;span class=&quot;ͼm&quot;&gt;wsl&lt;/span&gt; &lt;span class=&quot;ͼg&quot;&gt;--&lt;/span&gt;
  
  &lt;span class=&quot;ͼm&quot;&gt;install&quot; 명령으로 설치 할 수 있다.&amp;nbsp;
  특정 배포판 설치도 가능한데 설치 가능 배포한 목록은 
  &quot;wsl --list --online&quot; 명령으로 확인 가능하다. 이때 wsl 이 설치되어 있지 않았다면 자동 설치한다.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJhNUXUrx6szi7H3KmaQJX5jPwMcFr_jaNm85oqxuovu0t3LdeithL-GVyovUy7J9Wub9kp-B9HcIU-mHRu-5ovF6dBjkWChvIJwcNewlJINXfVL241WglnUiH2d8SEH4BWUWMJmr-cJpDMFxJZwcCcABggz9Pp6wtYl0K34dcSb93D6R62CiO7-ZEE6vP/s1314/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20095447.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;762&quot; data-original-width=&quot;1314&quot; height=&quot;372&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJhNUXUrx6szi7H3KmaQJX5jPwMcFr_jaNm85oqxuovu0t3LdeithL-GVyovUy7J9Wub9kp-B9HcIU-mHRu-5ovF6dBjkWChvIJwcNewlJINXfVL241WglnUiH2d8SEH4BWUWMJmr-cJpDMFxJZwcCcABggz9Pp6wtYl0K34dcSb93D6R62CiO7-ZEE6vP/w640-h372/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20095447.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span class=&quot;ͼm&quot;&gt;명령을 실행해보면 상당한 수의 배폰본은 지원하고 있음을 알 수 있다. 보통은 우분투를 가장 많이 사용한다고 하며 디폴터 설치 배포본 역시 우분투이다.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKVEfhEWyKa94N-mYrX_Don49EyYdn2dTZiQZayBkuDyLZW0NwFSTwD0XWXxjRfaKnHsz7P-9_7lt_OoR58stPwkaiExSAJ2ENbV7GHXCLrqjYVNB3fktsvQ_Wx1uiQnfNgDT1DSjues-kenQtPxWfjJFYD2aOrWNAh_QAHi9ObGp2c-3IKJgBTFLHAr4S/s1314/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20095753.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;854&quot; data-original-width=&quot;1314&quot; height=&quot;416&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKVEfhEWyKa94N-mYrX_Don49EyYdn2dTZiQZayBkuDyLZW0NwFSTwD0XWXxjRfaKnHsz7P-9_7lt_OoR58stPwkaiExSAJ2ENbV7GHXCLrqjYVNB3fktsvQ_Wx1uiQnfNgDT1DSjues-kenQtPxWfjJFYD2aOrWNAh_QAHi9ObGp2c-3IKJgBTFLHAr4S/w640-h416/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20095753.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;설치 전에 상태 확인이 필요한데 &quot; wsl --status&quot; 명령으로 확인 할 수 있다.&amp;nbsp;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHE7I1Mq3fmYYbvn9rg6WlJ55jOEdLv2EZytCRks_Syd9BvIyZYHDRAUQ9Ay5-LqBQ4m6JDMwy_FsM2nVb8MVyZ3X9c3L08KNe28d-pJRrPgkWhC8V-VdUq1dmKkcUy_DU1WWBE-jLK6z0_NglgivIwSH73dnnHBwdvnHEHURxh97z1QX_J75zvCmFYst5/s1314/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20100433.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;854&quot; data-original-width=&quot;1314&quot; height=&quot;416&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHE7I1Mq3fmYYbvn9rg6WlJ55jOEdLv2EZytCRks_Syd9BvIyZYHDRAUQ9Ay5-LqBQ4m6JDMwy_FsM2nVb8MVyZ3X9c3L08KNe28d-pJRrPgkWhC8V-VdUq1dmKkcUy_DU1WWBE-jLK6z0_NglgivIwSH73dnnHBwdvnHEHURxh97z1QX_J75zvCmFYst5/w640-h416/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20100433.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;color: red;&quot;&gt;WSL1(리눅스 명령을 윈도우가 번역하여 수행), WSL2 (가상화를 통한 리눅스 지원) 에 대한 활성화 작업이 필요하다. 지금 위의 환경에서는 모두 비활성화 상태이다.&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;활성화는 PowerShell 을 관리자 권한으로 실행하고 아래 명령을 입력하면 된다.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart&lt;/p&gt;&lt;p&gt;dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;또는 시작 메뉴에서 &quot;Windows 기능 켜기/끄기 를 실행하고 아래 기능을 채크 한다음 윈도우를 재시작 한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;가상 머신 플랫폼(Virtual Machine Platform)&lt;/li&gt;&lt;li&gt;Linux용 Windows 하위 시스템(Windows Subsystem for Linux)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimHE6LDSWyJNyAbZ8PodOUk4ykFtgWw-jTpK9RHWpxeVklqmtaE7peXGtysYxNk5wBNULgH8EXG3iXaT3qburuon6kSASGz00LvHthRLDubhKniOOSEoD1zC0UEnKFu-jouwos8938k_E8M4KPacUEbtMfQeOEPEffg6xvtmdcCCvpZG4Zjj6w_coxG9Ma/s394/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20101643.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;394&quot; data-original-width=&quot;388&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimHE6LDSWyJNyAbZ8PodOUk4ykFtgWw-jTpK9RHWpxeVklqmtaE7peXGtysYxNk5wBNULgH8EXG3iXaT3qburuon6kSASGz00LvHthRLDubhKniOOSEoD1zC0UEnKFu-jouwos8938k_E8M4KPacUEbtMfQeOEPEffg6xvtmdcCCvpZG4Zjj6w_coxG9Ma/w394-h400/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20101643.png&quot; width=&quot;394&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;설치는 PowerShell 을 관리자 권한으로 실행하고&amp;nbsp;&amp;nbsp;&quot;&lt;span class=&quot;ͼm&quot;&gt;wsl&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;ͼg&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;ͼm&quot;&gt;install&quot; , &quot;&lt;/span&gt;&lt;span class=&quot;ͼm&quot;&gt;wsl&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;ͼg&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;ͼm&quot;&gt;install&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;ͼg&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;ͼm&quot;&gt;d&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;ͼm&quot;&gt;Ubuntu&lt;/span&gt;&quot; 명령으로 할 수 있다.&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4tjN9yTtD7brftaCGoOemjmAKxPMgXkmEbL9RNnrTEq0Nt3wyBJCJSiSTPIjPHnydOR4pkKHzCMwDRsKkhRVlaERchNgarmuCGSB0iBU-Zpnm_isJv2NlDhoc_JpQRf1Q42PWZMS6IpS6-LYJse4jwBXe-R6aLDrV-sx30O2IFJ7vVi-Js7_pGoVAqRlN/s1223/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20102616.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;639&quot; data-original-width=&quot;1223&quot; height=&quot;334&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4tjN9yTtD7brftaCGoOemjmAKxPMgXkmEbL9RNnrTEq0Nt3wyBJCJSiSTPIjPHnydOR4pkKHzCMwDRsKkhRVlaERchNgarmuCGSB0iBU-Zpnm_isJv2NlDhoc_JpQRf1Q42PWZMS6IpS6-LYJse4jwBXe-R6aLDrV-sx30O2IFJ7vVi-Js7_pGoVAqRlN/w640-h334/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-04%20102616.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;설치가 완료되면 계정 생성을 진행하게 된다.&amp;nbsp; 계정생성이 완료되면 가장 먼저 시스템을 업데이트 한다.&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;sudo apt update&lt;/div&gt;&lt;div&gt;sudo apt upgrade -y&lt;/div&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;&lt;br /&gt;&lt;/h3&gt;&lt;h3&gt;WSL 환경에서 개발 도구 설치하기&amp;nbsp;&lt;/h3&gt;&lt;/div&gt;다음 단계는 AI Agent 기반 개발 환경을 만들기 위한 개발 툴 체인을 설치하는 것이다.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) 기본 시스템 도구&lt;br /&gt;







&lt;div&gt;&lt;google-sheets-html-origin&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;border-collapse: collapse; border: none; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;106&quot;&gt;&lt;/col&gt;&lt;col width=&quot;166&quot;&gt;&lt;/col&gt;&lt;col width=&quot;268&quot;&gt;&lt;/col&gt;&lt;col width=&quot;112&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;background-color: #cccccc; border: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;항목&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;설치 목적&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;설치 명령&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;확인 명령&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;curl&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;API 호출 및 다운로드&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;sudo apt install -y curl&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;curl --version&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;wget&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;파일 다운로드&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;sudo apt install -y wget&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;wget --version&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;unzip / zip&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;압축 파일 처리&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;sudo apt install -y unzip zip&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;git&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;소스 코드 버전 관리&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;sudo apt install -y git&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;git --version&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/google-sheets-html-origin&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2) 자바 개발 환경&lt;/div&gt;&lt;div&gt;&lt;google-sheets-html-origin&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;border-collapse: collapse; border: none; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;106&quot;&gt;&lt;/col&gt;&lt;col width=&quot;166&quot;&gt;&lt;/col&gt;&lt;col width=&quot;268&quot;&gt;&lt;/col&gt;&lt;col width=&quot;112&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;background-color: #cccccc; border: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;항목&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;설치 목적&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;설치 명령&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;확인 명령&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;OpenJDK 17&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;자바 실행 환경&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;sudo apt install -y openjdk-17-jdk&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;java -version&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;Gradle&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;Java 빌드 도구&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;sudo apt install -y gradle&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;gradle -v&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/google-sheets-html-origin&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3) AI 코딩 Agent&lt;br /&gt;&lt;table border=&quot;1&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; data-sheets-baot=&quot;1&quot; data-sheets-root=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;border-collapse: collapse; border: none; font-family: Arial; font-size: 10pt; table-layout: fixed; width: 0px;&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;106&quot;&gt;&lt;/col&gt;&lt;col width=&quot;166&quot;&gt;&lt;/col&gt;&lt;col width=&quot;268&quot;&gt;&lt;/col&gt;&lt;col width=&quot;112&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;background-color: #cccccc; border: 1px solid rgb(0, 0, 0); overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;항목&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;설치 목적&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;설치 명령&lt;/td&gt;&lt;td style=&quot;background-color: #cccccc; border-color: rgb(0, 0, 0) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: bottom;&quot;&gt;확인 명령&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;Codex CLI&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;AI 코드 생성 및 수정&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;npm install -g @openai/codex&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;codex --help&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 21px;&quot;&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;Aider&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;AI 코드 수정 도구&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;pip install aider-chat&lt;/td&gt;&lt;td style=&quot;border-color: rgb(204, 204, 204) rgb(0, 0, 0) rgb(0, 0, 0) rgb(204, 204, 204); border-image: initial; border-style: solid; border-width: 1px; overflow: hidden; padding: 2px 3px; vertical-align: bottom;&quot;&gt;aider --help&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;DE(VS Code)에서 Codex Agent를 설치한다면  WSL에 Codex CLI를 반드시 설치할 필요는 없지만 CLI 가 할 수 있는 작업이 더 많기 때문에 보통은 같이 사용한다. (npm 이 디폴트로 설치되어 있지 않아 sudo apt intall -y npm 명령으로 설치가 필요하다.)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;추가로 Ubuntu 22.04 이후부터는 직접 시스템에서 사용하는 Python 을 변경하지 못하게 막고 있어 pipx 사용이 가장 안전한 방법이다.&amp;nbsp;&lt;/div&gt;&lt;blockquote&gt;sudo apt update&lt;br /&gt;sudo apt install -y pipx python3-venv&lt;/blockquote&gt;&lt;div&gt;&lt;blockquote&gt;pipx ensurepath&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;터미널을 다시 실행하고 aider 을 설치한다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;pipx install aider-chat&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;다음으로 자신의 환경에 필요한 빌드 도구를 설치한다.&amp;nbsp; Visual Studio Code는&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://code.visualstudio.com/&quot; target=&quot;_blank&quot;&gt;https://code.visualstudio.com/&lt;/a&gt; 에서 다운로드하여 설치 할 수 있다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOcqnuDhjZpVOHtQu1Qa_Yj_j7OTAE92HLzHtBDdlGz46plh8f_7Ihi8VmrxfMAQ3dnd_Ub0PFVvVSvDlPQh4xnui7TwJpxXrGm1Btmje6mAA8_tjf_Zi3Xh4-CG2cdY8wtBcnjHDJQKNNpEL-TsbmJleN5P5_rPt4n7r5zghScf8UrIw5TLhny55oopMI/s1374/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-05%20151840.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;940&quot; data-original-width=&quot;1374&quot; height=&quot;438&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOcqnuDhjZpVOHtQu1Qa_Yj_j7OTAE92HLzHtBDdlGz46plh8f_7Ihi8VmrxfMAQ3dnd_Ub0PFVvVSvDlPQh4xnui7TwJpxXrGm1Btmje6mAA8_tjf_Zi3Xh4-CG2cdY8wtBcnjHDJQKNNpEL-TsbmJleN5P5_rPt4n7r5zghScf8UrIw5TLhny55oopMI/w640-h438/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-05%20151840.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;IED 도구 vscode 을 사용 중이라면 WSL 확장을 아래 명령으로 설치하고&amp;nbsp; PowerShell 에서 프로젝트 로 이동하고 code . 을 입력하여 VS 코드 리눅스 환경에서 실행할 수 있다.&amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;code --install-extension ms-vscode-remote.remote-wsl&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;VSCode 에서 Extenctions (Ctrl+Shift+X) 를 크릭하여 wsl 을 검색하여 설치할 수 도 있다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHcITweuN_jlPSbYQF0iPOYeRFT7mG-w5Xsz-9SHwx_n3v3u6b4G6Gg9zaTcXko6qMXHCRRMgn7oAXIx6wv98kdg92oG812NRuVPclqvDvaPBmHLLXAwtZ-cijL4K56hwk5DtIHg5RLJKVezSecAPTGztEZJvmXRxtKvl4MdGgKW0yiBlj2O0eT1s6U8Ea/s1500/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-05%20152242.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1000&quot; data-original-width=&quot;1500&quot; height=&quot;426&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHcITweuN_jlPSbYQF0iPOYeRFT7mG-w5Xsz-9SHwx_n3v3u6b4G6Gg9zaTcXko6qMXHCRRMgn7oAXIx6wv98kdg92oG812NRuVPclqvDvaPBmHLLXAwtZ-cijL4K56hwk5DtIHg5RLJKVezSecAPTGztEZJvmXRxtKvl4MdGgKW0yiBlj2O0eT1s6U8Ea/w640-h426/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-05%20152242.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;VSCode 기반의 AI 코딩을 위해서 아래의 확장들은 거의 필수이다. (AI Agent 만 선택)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;①&amp;nbsp;&lt;a href=&quot;chatgpt://generic-entity?number=1&quot;&gt;Remote - WSL&lt;/a&gt;&lt;br /&gt;②&amp;nbsp;&lt;a href=&quot;chatgpt://generic-entity?number=2&quot;&gt;GitLens&lt;/a&gt;&amp;nbsp; , SVN (vscode-svn extension)&lt;br /&gt;③ &lt;a href=&quot;chatgpt://generic-entity?number=3&quot;&gt;OpenAI Codex&lt;/a&gt; (선택)&lt;br /&gt;④ &lt;a href=&quot;chatgpt://generic-entity?number=4&quot;&gt;GitHub Copilot&lt;/a&gt;&amp;nbsp;(선택)&lt;br /&gt;⑤ &lt;a href=&quot;chatgpt://generic-entity?number=5&quot;&gt;Docker&lt;/a&gt;&lt;div&gt;&lt;div&gt;⑥ 기타 : Gradle for Java&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;AI 코딩 시작하기&lt;/h3&gt;&lt;div&gt;먼저 레파지토리에서 프로젝트를 가져온다. WSL 환경에 소스를 가져와야 하기 때문에 workspace 폴더를 생성하고 여기에서 다음 명령으로 소스를 가져온다.&amp;nbsp;&lt;/div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;GitLab 프로젝트 페이지 → Clone 버튼에서 URL을 복사&lt;/li&gt;&lt;li&gt;git clone &amp;lt;HTTPS_URL&amp;gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;이제 VS 코드를 실행하고 Ctrl + Shift + P 을 입력하여 명령 팔레트를 열고 WSL 을 입력하여 명령 목록에서 클릭하여 WSL환경에 연결한다.&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTTZyNqEcTBE4QW2c0QmCLTmMDYevQpZ8xpAIO8U9_zYfTTTl2pKqq6G11WLDImsBxEx5-DrLmO0T5xXwYR9jbLgjIbLELTEoxJb631LszqYY4MyEt8MVtq7suQYeSGGiYiIT33CUioArz7jp1OLcbrz1rVsEGS9kB16wveu4CHpYLvTyi2ILnVYjCTkgk/s1620/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202026-03-05%20153931.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;800&quot; data-original-width=&quot;1620&quot; height=&quot;316&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTTZyNqEcTBE4QW2c0QmCLTmMDYevQpZ8xpAIO8U9_zYfTTTl2pKqq6G11WLDImsBxEx5-DrLmO0T5xXwYR9jbLgjIbLELTEoxJb631LszqYY4MyEt8MVtq7suQYeSGGiYiIT33CUioArz7jp1OLcbrz1rVsEGS9kB16wveu4CHpYLvTyi2ILnVYjCTkgk/w640-h316/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202026-03-05%20153931.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;이제 폴더를 열면 된다. 보통은 &quot;Do you trust the authors of this workspace?&quot; 메시지가 나오는데 신뢰한다고 답을 하면 된다.&lt;/div&gt;







&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;이제 좌측 아이콘에서 Codex 클릭하고 로그인 / 인증키 입력 한다.&amp;nbsp;&lt;span class=&quot;s1&quot;&gt;CLI와 IDE 확장은 &lt;/span&gt;동일한 로그인 정보를 공유하도록 설계되어 있어 터미널에서도 CLI 을 사용이 가능하다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;터미널에서 codex 을 실행하고 다음에 아래와 같은 간단한 명령으로 코드를 리뷰하게 할 수 있다.&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;&quot;review this code focusing on security issues&quot;&amp;nbsp;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_V_BGHf4jaNSzZD8Myc_Vt_of_i_pYcTxl7lJhUNFnAoegEPwDPM3BZZOiR4Nz6atTphjO988vR6z0c82j1OVER87EUacVdatJr2ZCkrdQATZHAoc4BzRK4GhlCuZMlL4_Sp3bUPnyC7qGddxtr6BsxqRAKQ82BGZNr-Z7yO7NY-HgWohZdlIPk1KvI5y/s1678/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-05%20171328.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1392&quot; data-original-width=&quot;1678&quot; height=&quot;530&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_V_BGHf4jaNSzZD8Myc_Vt_of_i_pYcTxl7lJhUNFnAoegEPwDPM3BZZOiR4Nz6atTphjO988vR6z0c82j1OVER87EUacVdatJr2ZCkrdQATZHAoc4BzRK4GhlCuZMlL4_Sp3bUPnyC7qGddxtr6BsxqRAKQ82BGZNr-Z7yO7NY-HgWohZdlIPk1KvI5y/w640-h530/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-05%20171328.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;Codex 앱 사용하기&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;Codex 사이트(&lt;a href=&quot;https://openai.com/ko-KR/codex/&quot;&gt;https://openai.com/ko-KR/codex/&lt;/a&gt;)를 방문하면 맥/윈도우 용 앱을 다운로드 할 수 있다.&amp;nbsp; (2026.03.04 일 부터 윈도우지원)&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;윈도우용 Codex 앱은 PowerShell + Windows Sandbox (네이티브 센트박스) 기반으로 에어전트가 작업을 실행하며 필요하면 WSL 에서 실행하도록 구성하여 사용할 수 있다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;앞에서 설치한 VS Code 확장(Codex in IDE)&amp;nbsp; + WSL 와 함께 아래와 같이 역할을 구분하여 사용할 수 있다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;VS Code 확장(Codex in IDE) : “에디터 안에서” 코드 편집/대화 중심&lt;/li&gt;&lt;li&gt;Codex 앱 : “에이전트 관제센터”처럼 프로젝트/작업을 여러 개 굴리고, Windows Sandbox/PowerShell 또는 WSL 중 선택해 실행&amp;nbsp;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLG1tp8WCq1qiIhZ9G3dysAU4Ja286qonXxSgw7T1BylvmIo65M_iz_YZIYqp_AgKbwPjsmYHg2fuCNkpH2gJ77yvOMpLCjRmXEgpOfxPPCqGHTWxP3StIeihby_r1wEQLHspktlrtgU1C_ZDonzRe-0Y87m81ag0nes2yIpOWYzQlQFDPK7acuRdjfkW6/s1536/image.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLG1tp8WCq1qiIhZ9G3dysAU4Ja286qonXxSgw7T1BylvmIo65M_iz_YZIYqp_AgKbwPjsmYHg2fuCNkpH2gJ77yvOMpLCjRmXEgpOfxPPCqGHTWxP3StIeihby_r1wEQLHspktlrtgU1C_ZDonzRe-0Y87m81ag0nes2yIpOWYzQlQFDPK7acuRdjfkW6/w426-h640/image.png&quot; width=&quot;426&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Codex 앱에 프로젝트를 추가할 떄는 WSL 의 경로를 사용하는 것이 좋다.&amp;nbsp; 앞서 WSL 에서 생성한 프로젝트는 윈도우 파일 탐색기의 Linux 아이콘을 클릭하여 해당 프로젝트 경로를 찾아 추가할 수 있다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRPR6bAywCUsXMAlUdsMrJV1VDW1QsVq7ZZ8m38p6qAkWq519NZeIo-HT0WhCbodjA9CW6kzaRHosa_8kTt0Y83Ah0QEczcRG9XZgIdcujjqP7OXs6TQ_9UNbk_lH2Z6GWDnk2_31h2EJ1wPlixXp872vBZVP5VqsTqTffcifrLLgEBSbT2GrnCCvrdLTs/s553/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-06%20090825.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;553&quot; data-original-width=&quot;546&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRPR6bAywCUsXMAlUdsMrJV1VDW1QsVq7ZZ8m38p6qAkWq519NZeIo-HT0WhCbodjA9CW6kzaRHosa_8kTt0Y83Ah0QEczcRG9XZgIdcujjqP7OXs6TQ_9UNbk_lH2Z6GWDnk2_31h2EJ1wPlixXp872vBZVP5VqsTqTffcifrLLgEBSbT2GrnCCvrdLTs/w395-h400/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-06%20090825.png&quot; width=&quot;395&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;프로젝트 추가를 위한 가장 쉬운 방법은 1) PowerShell 에서 wsl 명령으로 WSL 에 연결하고 해당 프로젝트로 이동하여 2) explorer.exe . 명령을 입력하면 탐색기로 리눅스 파일시스템을 확인 할 수 있다. 3) 파일 탐색기에 보여지는 이경로로 프로젝트를 추가하면 된다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIeaJWHtn8oDS3yC63juYwt1v3VzEVg4MbjiMU8nGuf65Qu5YKew1JR9mVK9pndm2rhAq-VCWKFdmdPxJFPBVYNNaihNh_tw3DBRTvzjhaL87LJXQ5Sa5ITlTH5qFLwFv5Oz59vIk8h30kaZ3PZWHor62Q3xAPWjwbJlmDyv9-TiSJvK153xcRu3cyIppp/s1192/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202026-03-06%20092245.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1013&quot; data-original-width=&quot;1192&quot; height=&quot;544&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIeaJWHtn8oDS3yC63juYwt1v3VzEVg4MbjiMU8nGuf65Qu5YKew1JR9mVK9pndm2rhAq-VCWKFdmdPxJFPBVYNNaihNh_tw3DBRTvzjhaL87LJXQ5Sa5ITlTH5qFLwFv5Oz59vIk8h30kaZ3PZWHor62Q3xAPWjwbJlmDyv9-TiSJvK153xcRu3cyIppp/w640-h544/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202026-03-06%20092245.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;에어전트 환경 모드는 좌측 하단의&lt;u&gt; 설정 &amp;gt; 일반&lt;/u&gt; 의 Agent environment 설정에서 Windows Subsystem for Linux 와 Windows Native 를 선택할 수 있게 되어 있다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;간단하게 &quot;문서를 확인해서 프로젝트 구조 및 향후 과제를 확인해줘.&quot; 프롬프트를 입력해본댜. (모델은 &lt;u&gt;GPT 5.3 Codex&lt;/u&gt; , &lt;u&gt;낮음 &lt;/u&gt;을 선택했다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZGv9nXWuBPB7f2T9YQ1jhwK-2FJ604QMGOoCpDP71Gvps2p1S36sCnaKG0WzjbzJMJgswlfxr-Q9liTQNHUTHkQE4eJqiQtaTNByb6yQS48hmpyLFKNm08HDC1A0NGeYqV5bj0G5yVh7WgtfBQQI1TlDp3wHjHpvoWZISldVK7iDBvVsBB_J-iFVEzBkl/s1192/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-06%20093322.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1013&quot; data-original-width=&quot;1192&quot; height=&quot;544&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZGv9nXWuBPB7f2T9YQ1jhwK-2FJ604QMGOoCpDP71Gvps2p1S36sCnaKG0WzjbzJMJgswlfxr-Q9liTQNHUTHkQE4eJqiQtaTNByb6yQS48hmpyLFKNm08HDC1A0NGeYqV5bj0G5yVh7WgtfBQQI1TlDp3wHjHpvoWZISldVK7iDBvVsBB_J-iFVEzBkl/w640-h544/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202026-03-06%20093322.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;다음은 전체 개발 환경을 도식화 한 것이다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhghSRcDxrLV19nJGaPQI4YjpmxBL_o65MHRMjrjYhd6WrwG4bRHOPNew4yj-4tOEqJ-qjcsfyhELVc_YCzSFxbgsqLpKtulVo-bbyd259aVeygIC4A2K_1G6peA68P24z_EcGGaNtJlzxli22HpVdYV-WhR2o6q-HbaBLi9qMcpxQn-QtaO4yaNO6olxLJ/s1536/image2.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhghSRcDxrLV19nJGaPQI4YjpmxBL_o65MHRMjrjYhd6WrwG4bRHOPNew4yj-4tOEqJ-qjcsfyhELVc_YCzSFxbgsqLpKtulVo-bbyd259aVeygIC4A2K_1G6peA68P24z_EcGGaNtJlzxli22HpVdYV-WhR2o6q-HbaBLi9qMcpxQn-QtaO4yaNO6olxLJ/w426-h640/image2.png&quot; width=&quot;426&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/6891696748176392203/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2026/03/ai.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/6891696748176392203'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/6891696748176392203'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2026/03/ai.html' title='사용기 - 윈도우에서 AI 코딩 사용하기 (Codex)'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjW8PsukGBn432g86DWwy6PG9fcSNkJ02b0CS7No79Qy2grV0XfmGOrl3LLwEonQK3RmvXzowxSfna_iYnmXM3ASSh3HW0jfwwP13OGfsWIKxZ8dDIsHgAjk8Y2L2m0YoUIEn0XsLL77j9eM352aR6VCMDtj70QO0OUV03sJaGcBNZ366obVrVWbRagsGbA/s72-w640-h426-c/image2.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-8754416457575773559</id><published>2025-05-05T19:23:00.000+09:00</published><updated>2025-05-05T19:23:01.443+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="구형 맥미니 재설치"/><title type='text'>2012 맥미니 &quot;초기 설정값으로 재설정&quot; 하기</title><content type='html'>&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2012 맥미니에 설치된&amp;nbsp;&lt;span face=&quot;&amp;quot;SF Pro KR&amp;quot;, &amp;quot;SF Pro Text&amp;quot;, &amp;quot;SF Pro Icons&amp;quot;, &amp;quot;Apple Gothic&amp;quot;, &amp;quot;HY Gulim&amp;quot;, MalgunGothic, &amp;quot;HY Dotum&amp;quot;, &amp;quot;Lexi Gulim&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif&quot; style=&quot;background-color: white; color: #1d1d1f; font-size: 17px;&quot;&gt;macOS 을&lt;/span&gt;&amp;nbsp; &quot;초기 설정값으로 재설정&quot; 하여 파일 공유 서버로 용도로 재활용하기로 했다. 가능한&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;리모트 방식으로 진행하였지만 마지막 작업은 모니터, 마우스 그리고 키보드를 직결하여 마무리 했다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;&amp;quot;SF Pro KR&amp;quot;, &amp;quot;SF Pro Text&amp;quot;, &amp;quot;SF Pro Icons&amp;quot;, &amp;quot;Apple Gothic&amp;quot;, &amp;quot;HY Gulim&amp;quot;, MalgunGothic, &amp;quot;HY Dotum&amp;quot;, &amp;quot;Lexi Gulim&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif&quot; style=&quot;background-color: white; color: #1d1d1f; font-size: 17px;&quot;&gt;macOS Catalina &lt;/span&gt;다운로드&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;앱스토어를 통한 다운로드는 불가능하기 떄문에 콘솔에서 10.15.7 버전을 다운로드 했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://support.apple.com/ko-kr/102765&quot; target=&quot;_blank&quot;&gt;macOS Catalina와 호환되는 컴퓨터&lt;/a&gt;&amp;nbsp;자료를 보면&amp;nbsp; Mac mini(2012년 후반 모델) 지원하는 macOS 임을 확인할 수 있다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;&amp;quot;SF Pro KR&amp;quot;, &amp;quot;SF Pro Text&amp;quot;, &amp;quot;SF Pro Icons&amp;quot;, &amp;quot;Apple Gothic&amp;quot;, &amp;quot;HY Gulim&amp;quot;, MalgunGothic, &amp;quot;HY Dotum&amp;quot;, &amp;quot;Lexi Gulim&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif&quot; style=&quot;background-color: white; color: #1d1d1f; font-size: 17px;&quot;&gt;Catalina 는&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;22년 7월에 배포된&amp;nbsp;&lt;/span&gt;10.15.7 이 최신 버전이다. 같은 해 11월부터 공식 지원이 종료되어 더 이상 보안 업데이트나 기능 개선이 제공되지 않는다.&lt;/div&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;softwareupdate --fetch-full-installer --full-installer-version 10.15.7&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEingBXtjCzQwumAA2qPTcx4Dmye63q8MsS8gPYO0bfKGhKgp0gAEqduPjcLWdkCeGoiP8pVyScXNasfaNfmM3V05vc5v-YDNhEk0wkM_Z2Cjnin3yo2EvEutJyKkxQFLWHQJyl97Q-wmkajMQ3YsfY3Fft8UMkuRSS17aWnFRCjPBDjhIEjOC88oDSt6Fre/s1033/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9_32_34.png&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEingBXtjCzQwumAA2qPTcx4Dmye63q8MsS8gPYO0bfKGhKgp0gAEqduPjcLWdkCeGoiP8pVyScXNasfaNfmM3V05vc5v-YDNhEk0wkM_Z2Cjnin3yo2EvEutJyKkxQFLWHQJyl97Q-wmkajMQ3YsfY3Fft8UMkuRSS17aWnFRCjPBDjhIEjOC88oDSt6Fre/w640-h80/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9_32_34.png&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다운로드가 완료되면 아래 명령으로 다운로드가 완료된 파일을 확인할 수 있다.&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;ls -l /Applications/Install\ macOS\ Catalina.app&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;또는&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;/Applications/Install\ macOS\ Catalina.app/Contents/Resources/startosinstall --usage&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEgrynQgYhmsDBz0sIHf9raqGnSWTN8FzvAhYP5Ebt1deoHOPpunSR885PLppCwEvM9yEEMap9G47eNoos7g1UYh5eaPkEpUaplJHi-f92bfGisobHiEgXPWOmbW8-5SJ0kZDOLin1-1ke56Jc9IS5uk8sDx2PUclGgIBDMJ2XIvzrOxhU1okGJ2ywHXHl/s1016/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10_48_38.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;289&quot; data-original-width=&quot;1016&quot; height=&quot;182&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEgrynQgYhmsDBz0sIHf9raqGnSWTN8FzvAhYP5Ebt1deoHOPpunSR885PLppCwEvM9yEEMap9G47eNoos7g1UYh5eaPkEpUaplJHi-f92bfGisobHiEgXPWOmbW8-5SJ0kZDOLin1-1ke56Jc9IS5uk8sDx2PUclGgIBDMJ2XIvzrOxhU1okGJ2ywHXHl/w640-h182/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10_48_38.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;&amp;quot;SF Pro KR&amp;quot;, &amp;quot;SF Pro Text&amp;quot;, &amp;quot;SF Pro Icons&amp;quot;, &amp;quot;Apple Gothic&amp;quot;, &amp;quot;HY Gulim&amp;quot;, MalgunGothic, &amp;quot;HY Dotum&amp;quot;, &amp;quot;Lexi Gulim&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif&quot; style=&quot;background-color: white; color: #1d1d1f; font-size: 17px;&quot;&gt;macOS Catalina&amp;nbsp;&lt;/span&gt;설치&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기존 데이터를 모두 삭제하고 설치하도록 아래 명령을 입력한다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;sudo /Applications/Install\ macOS\ Catalina.app/Contents/Resources/startosinstall \&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; --eraseinstall \&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; --agreetolicense \&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; --nointeraction&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN0DpqePAtJhOZ5ES_2TwSTs8mr6D3vBhjafH0ZWWM3-yHTK0klSiR9wJIQ5okggvJ9vkBhWQsv77U24F3IxQZmGeDtkBh3jplZqtJzv9nGWycD_Iw-E5_hTY7U57VlT_VoF4PScka6rgS_OOoyyG8KE4KgAdeoK1jtru1FYq_yvhfcjwW2n6VrU4w4vZp/s1029/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10_51_58.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;91&quot; data-original-width=&quot;1029&quot; height=&quot;56&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN0DpqePAtJhOZ5ES_2TwSTs8mr6D3vBhjafH0ZWWM3-yHTK0klSiR9wJIQ5okggvJ9vkBhWQsv77U24F3IxQZmGeDtkBh3jplZqtJzv9nGWycD_Iw-E5_hTY7U57VlT_VoF4PScka6rgS_OOoyyG8KE4KgAdeoK1jtru1FYq_yvhfcjwW2n6VrU4w4vZp/w640-h56/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_10_51_58.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설치가 진행되면 더이상 리모트로 접속이 허용되지 않고 직접 맥미니에 키보드와 마우스를 연결하여 진행을 해야한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Fb18N-54ntKlwNkLZf4udO6tL0aqGiSiNQ7azY0kkIPgh4u1dPeRJh2XjMEUu3hNiFgwFmLGWtUaWy7irqOMIa1lveAn4mWIUltVDK_kNyz4F7LjRQBXy8QEmhmuPrQND8MU9yEnkTKJNs5J4mrn77R3bhF4xsF9ag4Csc5CfuuWVjmSqB9ZhwPBdeqh/s3185/IMG_1EDD51AA-39E6-403D-967E-6C27AD22BF0A.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;3185&quot; data-original-width=&quot;3024&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9Fb18N-54ntKlwNkLZf4udO6tL0aqGiSiNQ7azY0kkIPgh4u1dPeRJh2XjMEUu3hNiFgwFmLGWtUaWy7irqOMIa1lveAn4mWIUltVDK_kNyz4F7LjRQBXy8QEmhmuPrQND8MU9yEnkTKJNs5J4mrn77R3bhF4xsF9ag4Csc5CfuuWVjmSqB9ZhwPBdeqh/w608-h640/IMG_1EDD51AA-39E6-403D-967E-6C27AD22BF0A.png&quot; width=&quot;608&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/8754416457575773559/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2025/05/2012.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/8754416457575773559'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/8754416457575773559'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2025/05/2012.html' title='2012 맥미니 &quot;초기 설정값으로 재설정&quot; 하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEingBXtjCzQwumAA2qPTcx4Dmye63q8MsS8gPYO0bfKGhKgp0gAEqduPjcLWdkCeGoiP8pVyScXNasfaNfmM3V05vc5v-YDNhEk0wkM_Z2Cjnin3yo2EvEutJyKkxQFLWHQJyl97Q-wmkajMQ3YsfY3Fft8UMkuRSS17aWnFRCjPBDjhIEjOC88oDSt6Fre/s72-w640-h80-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-04-16_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9_32_34.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-1298042142591813184</id><published>2025-03-17T16:41:00.004+09:00</published><updated>2025-03-25T16:54:24.734+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="docker"/><category scheme="http://www.blogger.com/atom/ns#" term="postgres"/><category scheme="http://www.blogger.com/atom/ns#" term="sonarqube"/><category scheme="http://www.blogger.com/atom/ns#" term="시큐어코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="코드 품질 개선"/><title type='text'>사용기 - 맥에서 도커 기반 SonarQube 활용하기</title><content type='html'>&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube는 코드에 대한 버그, 코드 스멜(Code Smell), 보안 취약점을 자동으로 찾아내고, 코드 품질을 향상시키는 데 도움을 주는 소스 코드 품질 및 보안 분석 도구이다.&lt;br /&gt;&lt;br /&gt;버전에 따라 기능의 차이가 있는데 Community Edition (무료) 은&amp;nbsp; GitHub Private Repository 연동을 지원하지는 않지만 Git 에서 직접 코드를 가져와 분석할 수 있기 때문에 사용하는데 있어 큰 이슈는 없을 것 같다.&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span id=&quot;docs-internal-guid-1215d225-7fff-7f89-88c0-574a803c8aa0&quot; style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div align=&quot;left&quot; dir=&quot;ltr&quot; style=&quot;margin-left: 0pt;&quot;&gt;&lt;table style=&quot;border-collapse: collapse; border: none;&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;152&quot;&gt;&lt;/col&gt;&lt;col width=&quot;257&quot;&gt;&lt;/col&gt;&lt;col width=&quot;193&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;버전&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;특징&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;GitHub Private Repo 분석&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 27.25pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Community Edition&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;무료, 기본적인 코드 분석 가능&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;✗ (직접 클론 후 분석)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 27.25pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Developer Edition&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;추가적인 언어 지원, 분기(branch) 분석&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;✓&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Enterprise Edition&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;대규모 프로젝트 지원, 포트폴리오 관리&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #434343 0.5pt; border-color: rgb(67, 67, 67); border-left: solid #434343 0.5pt; border-right: solid #434343 0.5pt; border-style: solid; border-top: solid #434343 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;✓&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 14.6667px; text-align: center; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: white; color: #333333; font-family: &amp;quot;Nanum Gothic&amp;quot;; font-size: 14.85px;&quot;&gt;◼︎ 환경&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;background-color: white; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;&quot;&gt;&lt;li style=&quot;border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;font-size: 14.85px;&quot;&gt;OS : macOS 15.3.1 (24D70)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; color: #333333; font-size: 14.85px; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : VS Code , Docker&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. Docker 설치&lt;/span&gt;&lt;/h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Docker 는 공식 웹사이트에서 &lt;u&gt;Docker Desktop for Mac&lt;/u&gt;을 다운로드하여 설치한다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2CvX9hYeUQ9HiwVbT8Qwzv90tem63W4gZIIC_f38MpxeScM5L_AdGH0ii_mPg5zRJ_htrc7TrAaSdYirbm-zN9p7puXwGifusjmIEQR8F-Y3OinORbhKzVm6qg91SBd13s_B1sjTpUJh9-iLSrm2fsqCRqx9dZ-i_Nb8P4mwCzbWkGCYyBNZYltICxVD6/s2146/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_35_00.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1434&quot; data-original-width=&quot;2146&quot; height=&quot;428&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2CvX9hYeUQ9HiwVbT8Qwzv90tem63W4gZIIC_f38MpxeScM5L_AdGH0ii_mPg5zRJ_htrc7TrAaSdYirbm-zN9p7puXwGifusjmIEQR8F-Y3OinORbhKzVm6qg91SBd13s_B1sjTpUJh9-iLSrm2fsqCRqx9dZ-i_Nb8P4mwCzbWkGCYyBNZYltICxVD6/w640-h428/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_35_00.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;https://www.docker.com/products/docker-desktop&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;설치파일을 다운로드 후 Docker.dmg 파일을 클릭하여 설치를 진행할 수 있다. 설치가 완료되면 터미널에서 docker --version 명력을 입력하여 설치 확인한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;% docker --version&lt;br /&gt;Docker version 27.5.1, build 9f9e405&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. SonarQube Community Edition 설치하기&lt;/span&gt;&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube 는 간단하게 터미널에서 아래 명령으로&amp;nbsp;&lt;strong data-end=&quot;57&quot; data-start=&quot;42&quot;&gt;SonarSource&lt;/strong&gt;에서 공식적으로 제공하는 이미지를 다운로드하여 설치하고 실행할 수 있다.&amp;nbsp;&lt;span style=&quot;color: red;&quot;&gt; SonarQube 는 디폴트로 사용하는 H2 데이터베이스 보다는&amp;nbsp; postgres 사용을 권장하고 있어 먼저 postgres 데이터베이스를 설치하고 같이 실행할 필요가 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;docker run -d --name sonarqube -p 9000:9000 sonarqube:lts-community&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube는 여러 버전의 Docker 이미지를 제공하고 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span id=&quot;docs-internal-guid-d1ce8288-7fff-33e1-c849-93ab599ae4f8&quot; style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div align=&quot;left&quot; dir=&quot;ltr&quot; style=&quot;margin-left: 0pt;&quot;&gt;&lt;table style=&quot;border-collapse: collapse; border: none;&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;266&quot;&gt;&lt;/col&gt;&lt;col width=&quot;330&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;태그(Tag)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;설명&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube:latest&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;최신 안정 버전&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube:lts&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;최신 LTS (Long-Term Support) 버전&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;b&gt;sonarqube:lts-community&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;무료 Community Edition LTS 버전&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube:developer&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Developer Edition (유료)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube:enterprise&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Enterprise Edition (유료)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube:datacenter&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Data Center Edition (유료)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;postgres는 터미널에 아래와 같이 한 줄 명령어로 postgres 를 설치&amp;amp;실행 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;docker run -d --name postgres \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -e POSTGRES_USER=sonar \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -e POSTGRES_PASSWORD=sonar \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -e POSTGRES_DB=sonarqube \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -p 5432:5432 \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; postgres:16&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참고로 PostgreSQL 공식 Docker 이미지는 다양한 버전이 있는데 여기에서는 &lt;u&gt;16&lt;/u&gt; 을 사용했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span id=&quot;docs-internal-guid-3f09639f-7fff-cd89-ee0c-9cda3d0fbf9d&quot; style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div align=&quot;left&quot; dir=&quot;ltr&quot; style=&quot;margin-left: 0pt;&quot;&gt;&lt;table style=&quot;border-collapse: collapse; border: none;&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;179&quot;&gt;&lt;/col&gt;&lt;col width=&quot;345&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;background-color: #999999; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;태그 (Tag)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #999999; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;background-color: transparent; color: white; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;의미&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;color: #188038; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;postgres:latest&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;최신 안정 버전 (현재 기준 PostgreSQL 16)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;color: #188038; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;b&gt;postgres:16&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;b&gt;PostgreSQL 16.x&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;color: #188038; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;postgres:15&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;PostgreSQL 15.x&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;color: #188038; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;postgres:14&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;PostgreSQL 14.x&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;color: #188038; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;postgres:13&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;PostgreSQL 13.x&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이제 SonarQube 을 앞서 실행한 postres 와 함께 설치&amp;amp;실행 해보자.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;docker run -d --name sonarqube \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -p 9000:9000 \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; --link&amp;nbsp;postgres&amp;nbsp;\&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -e SONAR_JDBC_URL=jdbc:postgresql://&lt;span&gt;postgres&lt;/span&gt;:5432/sonarqube \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -e SONAR_JDBC_USERNAME=sonar \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp; -e SONAR_JDBC_PASSWORD=sonar \&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&amp;nbsp;sonarqube:lts-community&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span id=&quot;docs-internal-guid-2213e043-7fff-cb43-263a-35879cb5c70b&quot;&gt;&lt;div align=&quot;left&quot; dir=&quot;ltr&quot; style=&quot;margin-left: 0pt;&quot;&gt;&lt;table style=&quot;border-collapse: collapse; border: none;&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;241&quot;&gt;&lt;/col&gt;&lt;col width=&quot;390&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: white; font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;옵션&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: white; font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;설명&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 23.25pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;docker run&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;새로운 컨테이너를 실행하는 명령&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 0pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;-d&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;컨테이너를 백그라운드(Detached Mode)에서 실행&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 0pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;--name sonarqube&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;컨테이너 이름을 &lt;/span&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube&lt;/span&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;로 지정&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 6.94775pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;-p 9000:9000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;호스트의 9000번 포트를 컨테이너의 9000번 포트와 연결 (SonarQube 웹 UI)&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 0pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;--link postgre-container&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;SonarQube가 &lt;/span&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;postgre-container&lt;/span&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt; 컨테이너와 통신할 수 있도록 설정 (Deprecated - 다른 방법 권장)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 14.7502pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;-e SONAR_JDBC_URL=jdbc:postgresql://postgres:5432/sonarqube&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;SonarQube가 PostgreSQL 데이터베이스 &lt;/span&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube&lt;/span&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;에 연결하도록 설정&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 15pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;-e SONAR_JDBC_USERNAME=sonar&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;PostgreSQL 접속 시 사용할 DB 사용자명 설정&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 12.9167pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;-e SONAR_JDBC_PASSWORD=sonar&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;PostgreSQL 접속 시 사용할 DB 비밀번호 설정&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 0pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube:lts-community&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;실행할 Docker 이미지 (&lt;/span&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonarqube&lt;/span&gt;&lt;span face=&quot;Arial, sans-serif&quot; style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;의 LTS 버전, 무료 Community Edition)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참고로 여기에서는 postgres 와 sonarquber 가 서로 통신가능하게 --link 옵션을 사용했지만 안정성 이유로 --network 을 사용하는 것이 권장된다고 한다. 설치가 완료되면 브라우저에서 localhost:9000 포트로 접속한다. 디폴트 계정과 비밀번호는 admin 과 admin 이다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Docker Desktop 도구를 사용하면 좀더 쉽게 도커 컨테이너 제어와 자원 사용량을 실시간으로 확인 할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ym0tw2TS_N7YQGwi1YeopAt4JN5xY6OC3UuAwRrMJoCTFxsfVaUPYlPPxE0iAOds8741IrYlDWWn-IsltEvhr-krSpO-l-rLnmcUo79VhAnppIjEVClI9v2ILq4JOFgR8StCJWRtC1FmAlUKus4phl0uF_WKsNyvioU0DmxPxMwQEwAGf2D2wh-IV3OR/s3022/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11_14_31.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1990&quot; data-original-width=&quot;3022&quot; height=&quot;422&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6ym0tw2TS_N7YQGwi1YeopAt4JN5xY6OC3UuAwRrMJoCTFxsfVaUPYlPPxE0iAOds8741IrYlDWWn-IsltEvhr-krSpO-l-rLnmcUo79VhAnppIjEVClI9v2ILq4JOFgR8StCJWRtC1FmAlUKus4phl0uF_WKsNyvioU0DmxPxMwQEwAGf2D2wh-IV3OR/w640-h422/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11_14_31.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Docker Desktop 화면&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;일단 위 과정을 한번하고나면 다음부터는 Docker Desktop 을 사용하여 쉽게 컨테이너를 조작할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMtPkmgLCGLUrIAPt3bdVMebA7dx1tYL-4ZoGbiymieUarSWB3lrSI_W5Y1RDP_3q6I3Kw79zkwTWqYXnncNsb5vrTd0eV2U3DuscUT9XGYK7SYk0cd3GM3Pl6ET0lD2M578mK9SOc6apCtvPMJu5EzcbSYT8o4VK_9bX9xrz7nXVbPR-3SPR-pT_ObdE5/s3022/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_43_29.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1990&quot; data-original-width=&quot;3022&quot; height=&quot;422&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMtPkmgLCGLUrIAPt3bdVMebA7dx1tYL-4ZoGbiymieUarSWB3lrSI_W5Y1RDP_3q6I3Kw79zkwTWqYXnncNsb5vrTd0eV2U3DuscUT9XGYK7SYk0cd3GM3Pl6ET0lD2M578mK9SOc6apCtvPMJu5EzcbSYT8o4VK_9bX9xrz7nXVbPR-3SPR-pT_ObdE5/w640-h422/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_43_29.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. SonarQube Community Edition 사용하기&lt;/span&gt;&lt;/h3&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;한글이 익숙하다면 로그인 후 macketplace 메뉴에서 &quot;Korean Pack Localization&quot; 을 설치하면 간단하게 한글을 지원하게 된다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코드 품질을 분석하는 기본적인 과정은 아래와 같다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❶ 프로젝트를 생성&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❷ SonarScanner 설치 및 실행&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❸ 분석결과 확인&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2.1 프로젝트를 생성&lt;/span&gt;&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;&quot;프로젝트&quot;&lt;/u&gt;&amp;nbsp;메뉴를&amp;nbsp;클릭하고 Community Edition 이 GitHub Private Repository 연동을 지원하지 않기 때문에 로컬에 프로젝트를 복제하여 분석 하기 위하여 &quot;&lt;u&gt;Manually&lt;/u&gt;&quot; 을 선택한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOHvIb4ii81w-D_Azf840B6Ut6K4EnRw8HYz2CY3-p3sceIdLTFqd9jIF3SmZmw0w6fN5q2b0TDdQldp_Je1Op1RoJBZH7zLMkA9DUh3rxo8j3Rvo80cg2TYfKRSlgxbG6lUhsZE0zuIyxwREeRXQtVa2F4pmMLUaLIYlAMkbcsddnTsZwsuq2z1V5wFdU/s2108/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11_31_11.jpg&quot; style=&quot;margin-left: auto; margin-right: auto; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1274&quot; data-original-width=&quot;2108&quot; height=&quot;386&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOHvIb4ii81w-D_Azf840B6Ut6K4EnRw8HYz2CY3-p3sceIdLTFqd9jIF3SmZmw0w6fN5q2b0TDdQldp_Je1Op1RoJBZH7zLMkA9DUh3rxo8j3Rvo80cg2TYfKRSlgxbG6lUhsZE0zuIyxwREeRXQtVa2F4pmMLUaLIYlAMkbcsddnTsZwsuq2z1V5wFdU/w640-h386/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11_31_11.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;존재하는 프로젝트가 없는 경우&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;프로젝트 이름을 입력하고 Setup 을 클릭하여 프로젝트를 생성한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8nVi1eZ2KpS6YQUwRYOEboXcJmhfnYePi8qWggmJxbdoYnes8QV-zc_TQyu6T124AOW5OPDyDM66-CJ6b0nngxHL1XJZ6xlaJ-67R1lbAMHkqD-eDbIoqEc0-sq2nGeusonE_PyoZ2FbZLzfVhIzEuCECYqrsFR3L19t7wCJTqgCZb4JYxMFFPeIWX3gE/s1192/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-14%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.36.59.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1108&quot; data-original-width=&quot;1192&quot; height=&quot;371&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8nVi1eZ2KpS6YQUwRYOEboXcJmhfnYePi8qWggmJxbdoYnes8QV-zc_TQyu6T124AOW5OPDyDM66-CJ6b0nngxHL1XJZ6xlaJ-67R1lbAMHkqD-eDbIoqEc0-sq2nGeusonE_PyoZ2FbZLzfVhIzEuCECYqrsFR3L19t7wCJTqgCZb4JYxMFFPeIWX3gE/w400-h371/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-14%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.36.59.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;&lt;h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2.2 토큰 생성&lt;/span&gt;&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보안된 인증을 통해 자동화된 코드 분석을 실행할 수 있도록 토큰을 생성한다. &lt;u&gt;Loaclly&lt;/u&gt; 을 클릭한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbwDO1xzdilxUdqPH3e8yWCoXhLf1K4PJCJ-iuEUxp-oCaq7nadlvmUQTodmzWum6sJbTefUwgBGsbrMh_c6G5QquxgsvWqv3f83Mnq-KxeXTICSFHq9ojsSRKVXYijDzRQ7Hg6cequExEJeCIBEI9ZopjD22J4Gq6KczIUaGg34sw7qjej-jzqVbrzAXj/s2436/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_53_19.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1390&quot; data-original-width=&quot;2436&quot; height=&quot;366&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbwDO1xzdilxUdqPH3e8yWCoXhLf1K4PJCJ-iuEUxp-oCaq7nadlvmUQTodmzWum6sJbTefUwgBGsbrMh_c6G5QquxgsvWqv3f83Mnq-KxeXTICSFHq9ojsSRKVXYijDzRQ7Hg6cequExEJeCIBEI9ZopjD22J4Gq6KczIUaGg34sw7qjej-jzqVbrzAXj/w640-h366/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_53_19.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;① 토큰 생성하기&lt;/u&gt;에서 &lt;u&gt;생성하기&lt;/u&gt;를 클릭하여 토큰을 생성한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnNkIigWBoWb6xUYjanSeJ1I24eZg-dVtEXhjxhOGptBysTnVB8faX0egShjFfRUVwLg5IJPkBuz-WlX7eZ7qgDaZLRs7mXMD1vJoHjbU7xYFEH5WUxvDK3Zos1AzVhMNXlnqiiMeG_DBp6f5de_tu7do6iwIJY2AHqVi-YmNdBWmdWsn3ATd9V0QcUbkR/s1984/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_54_39.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1302&quot; data-original-width=&quot;1984&quot; height=&quot;420&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnNkIigWBoWb6xUYjanSeJ1I24eZg-dVtEXhjxhOGptBysTnVB8faX0egShjFfRUVwLg5IJPkBuz-WlX7eZ7qgDaZLRs7mXMD1vJoHjbU7xYFEH5WUxvDK3Zos1AzVhMNXlnqiiMeG_DBp6f5de_tu7do6iwIJY2AHqVi-YmNdBWmdWsn3ATd9V0QcUbkR/w640-h420/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_54_39.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj589NbLCChd4u_2bDedeWRaVZX-EZjXP1HWydrjn4VCkZvkWRQuOPAHxaAO71YxbRA6pDjdYRh_FBWorhbVaR8ktcdQYMd4LmAOwejjHdCGKHtTRIzoatapuKhHcG-m5OUOlFl5WBZKOXVA3m2yapeh6zW0dBN9IHohOrH5rXECIkA7IMHMuzw2T1glGJX/s1678/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_56_33.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1026&quot; data-original-width=&quot;1678&quot; height=&quot;392&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj589NbLCChd4u_2bDedeWRaVZX-EZjXP1HWydrjn4VCkZvkWRQuOPAHxaAO71YxbRA6pDjdYRh_FBWorhbVaR8ktcdQYMd4LmAOwejjHdCGKHtTRIzoatapuKhHcG-m5OUOlFl5WBZKOXVA3m2yapeh6zW0dBN9IHohOrH5rXECIkA7IMHMuzw2T1glGJX/w640-h392/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_56_33.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;생성된 토큰을 별도로 저장하여 보관한다. &lt;u&gt;Continue&lt;/u&gt; 클릭하면 다양한 환경에 바로 적용 가능한 스크립트를 보여준다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC0FabTk9Z12Ehmhtqvgo2yAQtBBeYuP7LMw0j422jysGjOULcY_Yrwhzf8WmzpOMSJZtoF6XESdBPTwi1cBbHkpaAx6L9cCfhFDACQ29gSWFoA36gbWDPl4rac4tcfVMUyw1Hz6JGgA4CcqRcq5WMkRpVH7SwR92G4nlhsVYQsDrukC587sePGqR_MpB4/s2632/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_59_29.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1648&quot; data-original-width=&quot;2632&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC0FabTk9Z12Ehmhtqvgo2yAQtBBeYuP7LMw0j422jysGjOULcY_Yrwhzf8WmzpOMSJZtoF6XESdBPTwi1cBbHkpaAx6L9cCfhFDACQ29gSWFoA36gbWDPl4rac4tcfVMUyw1Hz6JGgA4CcqRcq5WMkRpVH7SwR92G4nlhsVYQsDrukC587sePGqR_MpB4/w640-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-14_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12_59_29.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기존 프로젝트가 maven 을 지원하고 있어 maven 스크립트를 복사했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2.3 SonarScanner 설치 및 실행&lt;/span&gt;&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube 서버와 연결하여 코드 품질을 분석하고 결과를 업로드하는 SonarScanner 은 아래와 같이 터미널에 입력하여 간단하게 설치할 수 있다.&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;brew install sonar-scanner &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarScanner가 분석하는 요소는 아래와 같다.&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Bug (버그): 코드에서 오류가 발생할 가능성이 있는 부분&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Code Smell (코드 냄새): 유지보수성이 낮거나 개선이 필요한 코드&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vulnerability (보안 취약점): SQL Injection, XSS 같은 보안 문제&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Coverage (테스트 커버리지): 단위 테스트가 얼마나 잘 작성되었는지&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Duplications (코드 중복): 중복된 코드 블록 확인&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설치 결과는 아래 명령으로 확인 할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;sonar-scanner --version&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이제 Git 에서 가져온 Maven 프로젝트에서 앞서 복사한 스크립트를 사용하여 실행한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;mvn clean verify &lt;span style=&quot;color: red;&quot;&gt;sonar:sonar &lt;/span&gt;\&lt;br /&gt;  -Dsonar.projectKey=&lt;span style=&quot;color: red;&quot;&gt;my_project&lt;/span&gt; \&lt;br /&gt;  -Dsonar.host.url=http://localhost:9000 \&lt;br /&gt;  -Dsonar.login=&lt;span style=&quot;color: red;&quot;&gt;your_generated_token&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span id=&quot;docs-internal-guid-0868d189-7fff-23a0-4a79-16222f3e15ef&quot;&gt;&lt;div align=&quot;left&quot; dir=&quot;ltr&quot; style=&quot;margin-left: 0pt;&quot;&gt;&lt;table style=&quot;border-collapse: collapse; border: none;&quot;&gt;&lt;colgroup&gt;&lt;col width=&quot;323&quot;&gt;&lt;/col&gt;&lt;col width=&quot;307&quot;&gt;&lt;/col&gt;&lt;/colgroup&gt;&lt;tbody&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: white; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;옵션&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #666666; border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: transparent; color: white; font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-weight: 700; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;mvn&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Maven을 실행하는 명령어&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 26.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;clean&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기존 빌드 파일을 삭제하고 새롭게 빌드&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 8.25pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;verify&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트를 실행하고 빌드를 검증&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 13.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;sonar:sonar&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;SonarQube 분석을 실행하는 Maven 플러그인 (&lt;/span&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;sonar-maven-plugin&lt;/span&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 3.19775pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;-Dsonar.projectKey=my_project&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube에서 프로젝트를 구별하는 고유한 키&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 1.5pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;-Dsonar.host.url=http://localhost:9000&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube 서버의 주소&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;height: 0pt;&quot;&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;-Dsonar.login=your_generated_token&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style=&quot;border-bottom: solid #000000 0.5pt; border-color: rgb(0, 0, 0); border-left: solid #000000 0.5pt; border-right: solid #000000 0.5pt; border-style: solid; border-top: solid #000000 0.5pt; border-width: 0.5pt; overflow-wrap: break-word; overflow: hidden; padding: 5pt; vertical-align: top;&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 10pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;SonarQube 인증을 위한 API 토큰&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;실행이 완료되면 SonarQube 웹에서 분석 결과 확인할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu2Hvp9IvBw1EyNVhnRN04wNcifUcmJJGYSet3xlq1NJdHhd5AVb9CkKkYIpAu9kerIRq9RVyl3ZRbE7brZ_l3jsFGfuQzbPuotEyan4MQaR7UEjnADobLpSTAAZen8WRkn1zhJasHZ2Epg8NYL8A3wSyIpZ5gnJdaZx7nCIIv6uSaPIY1x1c-PZLF6H_U/s2024/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.13.42.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;938&quot; data-original-width=&quot;2024&quot; height=&quot;296&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu2Hvp9IvBw1EyNVhnRN04wNcifUcmJJGYSet3xlq1NJdHhd5AVb9CkKkYIpAu9kerIRq9RVyl3ZRbE7brZ_l3jsFGfuQzbPuotEyan4MQaR7UEjnADobLpSTAAZen8WRkn1zhJasHZ2Epg8NYL8A3wSyIpZ5gnJdaZx7nCIIv6uSaPIY1x1c-PZLF6H_U/w640-h296/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.13.42.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicCNc8Ylvj7O_mVNM0-wrgnbD1opvrLGZLl5JAfx8jZZKT7tdPBkhokPTolNpucQS85m71LTNgAA9UDqJvM9BQL3qat8rOOJ0eGBqO_iHIb6mL9Ms_UI8pzH_plathCemk8seCFB24n54rlakfbBmv_psN2dlOyNCaIfG9BLRhTwsgSzCQGq7pgA8Pmsq_/s2662/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.20.09.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1198&quot; data-original-width=&quot;2662&quot; height=&quot;288&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicCNc8Ylvj7O_mVNM0-wrgnbD1opvrLGZLl5JAfx8jZZKT7tdPBkhokPTolNpucQS85m71LTNgAA9UDqJvM9BQL3qat8rOOJ0eGBqO_iHIb6mL9Ms_UI8pzH_plathCemk8seCFB24n54rlakfbBmv_psN2dlOyNCaIfG9BLRhTwsgSzCQGq7pgA8Pmsq_/w640-h288/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.20.09.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결과 화면&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;SonarQube 분석 결과을 보면 이 프로젝트는 다음과 같은 조치가 필요한 것으로 나타난다.&lt;br /&gt;&lt;/span&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Bugs, Vulnerabilities, Coverage, Duplications 항목에서 개선 필요&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특히 Bugs (170개), Coverage (0%), 취약점 (13개)가 심각한 문제&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보안 문제를 해결하고, 테스트 커버리지를 높이는 것이 가장 시급함&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이제 SonarQube 에서 &quot;&lt;u&gt;Issues&lt;/u&gt;&quot; 탭을 확인하고, 하나씩 문제를 해결해 나가면 된다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCvHaZ84YenCTn7xvCl69QgS6EjSkCmrcrj4brHGp35S3668KXLvA1H95sqzG4fvR6ppw9f9yj6vylSq1ymnodQyTsEc-Wo_p6u-s_RD3DRG4PYLztExCyAZezVHS0A1rKluUy90ccyC04oXZYg9qmTEDcAmBnDScVHYLn46fM1ymAMlb7eeeMkkIPjBi-/s2710/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_49_14.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1452&quot; data-original-width=&quot;2710&quot; height=&quot;342&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCvHaZ84YenCTn7xvCl69QgS6EjSkCmrcrj4brHGp35S3668KXLvA1H95sqzG4fvR6ppw9f9yj6vylSq1ymnodQyTsEc-Wo_p6u-s_RD3DRG4PYLztExCyAZezVHS0A1rKluUy90ccyC04oXZYg9qmTEDcAmBnDScVHYLn46fM1ymAMlb7eeeMkkIPjBi-/w640-h342/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_49_14.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이슈 목록 화면&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;각 이슈를 클릭하면 해당 건에 대한 상세 화면으로 이동하게 된다.&amp;nbsp; 이슈 내용을 확인하고 코드를 수정한다. 이슈 상세 페이지를 보면 이슈 상태를 변경할 수 있는 기능이 있는데&amp;nbsp; 코드 수정 후 다시 로컬에서 SonarScanner 을 실행하기 때문에 문자가 해결되면 자동으로&amp;nbsp;&amp;nbsp;&lt;u&gt;Resolved(Fixed)&lt;/u&gt; 로 상태가 변경 된다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGHKWELhFsiyQPkjaiSwmeWmh-IKfirFSU0RCBTDmT_ptKnq5uZB6wpyFmxO-I2REVyfddtBHF0-GtdNCKRiekGeFpuUNJSK7U55oSiQxYcIsS-6KPhdojYmX_k9RHu6uyh8RybT6JhXBWgyRf-0ibm8F1JC6VlA620B1kExoZKThBIVtc1zpRR9Adnkb2/s1454/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_02_11.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;580&quot; data-original-width=&quot;1454&quot; height=&quot;256&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGHKWELhFsiyQPkjaiSwmeWmh-IKfirFSU0RCBTDmT_ptKnq5uZB6wpyFmxO-I2REVyfddtBHF0-GtdNCKRiekGeFpuUNJSK7U55oSiQxYcIsS-6KPhdojYmX_k9RHu6uyh8RybT6JhXBWgyRf-0ibm8F1JC6VlA620B1kExoZKThBIVtc1zpRR9Adnkb2/w640-h256/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_02_11.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이슈 상세화면에서 &quot;See all issues in this file&quot; 클릭하여 해당 파일에 대한 목록만 보여지는데&amp;nbsp; 이를 활용하면 파일 별로 작업을 진행 할 수도 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGUGq57Z_iUgSYlmbyvKGxg5am2w7jQMosZ5KEYn6R1FMd4c0cL0JMTBdNm9bg7nld9ZDYZpeMOk54wXo8zAZQaEXYAh-jYiqmlwhKZxhNy1oWtuOoR1U_hyjQStCMj3loNsp4nRqd5JuHAnyBYOa-uegzljoq9hYwMMOY1p6nHvH0ioWiPCX6lJcFUx17/w640-h314/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_20_23.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이슈 상세 화면&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGUGq57Z_iUgSYlmbyvKGxg5am2w7jQMosZ5KEYn6R1FMd4c0cL0JMTBdNm9bg7nld9ZDYZpeMOk54wXo8zAZQaEXYAh-jYiqmlwhKZxhNy1oWtuOoR1U_hyjQStCMj3loNsp4nRqd5JuHAnyBYOa-uegzljoq9hYwMMOY1p6nHvH0ioWiPCX6lJcFUx17/s2086/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_20_23.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7mXVLUfHMkRmi1COlNZxitBH29V87Jsxi0aUfZ3G1tc0Dx_aZsbiKO7sj1QTCDXtOO_D3YaUphB-Enewy0esfymWaj5dBS2ke48ArzJRKVN5RZlxaVx9QnavQdlgWqoFW7PUuG_WYlxVsgA6Qutj2lgD4uYH6YVRsaHkyjtpNT2L53U1aBreoMUVZyD7d/w640-h266/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_24_46.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;파일 단위로 필터 된 이슈 목록&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7mXVLUfHMkRmi1COlNZxitBH29V87Jsxi0aUfZ3G1tc0Dx_aZsbiKO7sj1QTCDXtOO_D3YaUphB-Enewy0esfymWaj5dBS2ke48ArzJRKVN5RZlxaVx9QnavQdlgWqoFW7PUuG_WYlxVsgA6Qutj2lgD4uYH6YVRsaHkyjtpNT2L53U1aBreoMUVZyD7d/s2646/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-17_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_24_46.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코드를 수정하고 SonarScanner 을 동일하게 실행하면 결과가 반영되어 다시 분석결과가 업데이트 된다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;3. 느낀점&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;자바 언어를 사용하는 프로젝트에 1주 정도 적용을 해보았는데 아래와 같은 점에서 아주 만족스러웠다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;좋은 코딩 습관을 위한 아주 좋은 도구이다. 코드에 대한&amp;nbsp; 결함을 해결하면서 좋은 코드를 작성하는 방법을 자연스럽게 학습할 수 있었다.&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Bug (버그): 코드에서 오류가 발생할 가능성이 있는 부분&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Code Smell (코드 냄새): 유지보수성이 낮거나 개선이 필요한 코드&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vulnerability (보안 취약점): SQL Injection, XSS 같은 보안 문제&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Coverage (테스트 커버리지): 단위 테스트가 얼마나 잘 작성되었는지&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Duplications (코드 중복): 중복된 코드 블록 확인&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;자바 언어의 버전에 따른 좋은 코드를 지적해주기 때문에 코딩 스킬 향상에 도움이 되었다.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/1298042142591813184/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2025/03/sonarqube.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1298042142591813184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1298042142591813184'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2025/03/sonarqube.html' title='사용기 - 맥에서 도커 기반 SonarQube 활용하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2CvX9hYeUQ9HiwVbT8Qwzv90tem63W4gZIIC_f38MpxeScM5L_AdGH0ii_mPg5zRJ_htrc7TrAaSdYirbm-zN9p7puXwGifusjmIEQR8F-Y3OinORbhKzVm6qg91SBd13s_B1sjTpUJh9-iLSrm2fsqCRqx9dZ-i_Nb8P4mwCzbWkGCYyBNZYltICxVD6/s72-w640-h428-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-03-12_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_35_00.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-3185848518981799016</id><published>2025-03-01T21:49:00.001+09:00</published><updated>2025-03-03T10:41:23.890+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="Gemini Code Assist"/><category scheme="http://www.blogger.com/atom/ns#" term="코딩 자동화"/><title type='text'>사용기 - VSCode 에서 Gemini Code Assist</title><content type='html'>&lt;h3 style=&quot;text-align: left;&quot;&gt;Gemini Code Assist 설치하기&lt;/h3&gt;&lt;a href=&quot;https://codeassist.google/&quot; target=&quot;_blank&quot;&gt;Gemini Code Assist&lt;/a&gt; 사이트를&amp;nbsp;&amp;nbsp;방문하여 &lt;u&gt;Use in Visual Studio Code&lt;/u&gt; 버튼을 클릭한댜.&lt;div&gt;&lt;br /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgot8VQ_AYqsw8yBfsFhpDDG8kEiaLlqcqUbrrt3r8c_GnZtKxVOPd9NWAVYp22tH6wCQlMAwhDKYVRbmSJFflZRjpAofcVSiId7MXBTK6CEzNS1abJ6juAlXnBvNbP3AgqNxK3uLt1Venz_a2y1MwMEj8kidR1Jgzshw46zwGCzU5UwongfgUjiFyU7TCC/s2288/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-02-27%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.08.28.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1592&quot; data-original-width=&quot;2288&quot; height=&quot;446&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgot8VQ_AYqsw8yBfsFhpDDG8kEiaLlqcqUbrrt3r8c_GnZtKxVOPd9NWAVYp22tH6wCQlMAwhDKYVRbmSJFflZRjpAofcVSiId7MXBTK6CEzNS1abJ6juAlXnBvNbP3AgqNxK3uLt1Venz_a2y1MwMEj8kidR1Jgzshw46zwGCzU5UwongfgUjiFyU7TCC/w640-h446/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-02-27%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.08.28.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;br /&gt;https://codeassist.google/#available-in-your-favorite-ides-and-platforms&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;u&gt;Use in Visual Studio Code&lt;/u&gt;&amp;nbsp;버튼을 클릭하면 마이크로소프트 Visual Studio Maketplace 의 Gemini Code Assist 설치 사이트로 이동하게 된다.&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_cbiDy2NeCRjz4QSXRedS8AVAH60oXxuJL-ng7ul5gc2qBEXx9cfF3ZuFhYkycNMeJYMOQynrD2ICyT29UEddBiqy4Rq5mPMC8obmxBKCwlTYGstuDppuRCzGmMjyWNkr1liNCah2z1ARWjVM1qSM_GCH-EeeGfB9uoofgpu4lFBSGMztem758DCBjOWt/s1920/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-02-27%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.11.28.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1586&quot; data-original-width=&quot;1920&quot; height=&quot;528&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_cbiDy2NeCRjz4QSXRedS8AVAH60oXxuJL-ng7ul5gc2qBEXx9cfF3ZuFhYkycNMeJYMOQynrD2ICyT29UEddBiqy4Rq5mPMC8obmxBKCwlTYGstuDppuRCzGmMjyWNkr1liNCah2z1ARWjVM1qSM_GCH-EeeGfB9uoofgpu4lFBSGMztem758DCBjOWt/w640-h528/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-02-27%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.11.28.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;직접 Visual Studio Code 마켓플레이스 확장을 통하여 설치할 수도 있는데 &lt;u&gt;gemini&lt;/u&gt; 로 검색하여 설치하면 된다.&amp;nbsp;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuaUtq0Clb-WQH0QPKwb5NJp9Z1KW9krJ3UHWn7KldZlDJ_xYl_VnQcC4LQeu-LdGN1-7BNkmhSd7bSxkyNUMH7yYl8jz4WmyWPhxJRkivrqxYDHo43C4Y7Sfq2kNl0hC8dNVP1MruXf2cNTZ5FnDihYhbpDAMwvq-pnLLQMEutCpjzRwz28dtBBLICk2k/s1176/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-02-27_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_16_13.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1176&quot; data-original-width=&quot;1166&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuaUtq0Clb-WQH0QPKwb5NJp9Z1KW9krJ3UHWn7KldZlDJ_xYl_VnQcC4LQeu-LdGN1-7BNkmhSd7bSxkyNUMH7yYl8jz4WmyWPhxJRkivrqxYDHo43C4Y7Sfq2kNl0hC8dNVP1MruXf2cNTZ5FnDihYhbpDAMwvq-pnLLQMEutCpjzRwz28dtBBLICk2k/w634-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-02-27_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_16_13.jpg&quot; width=&quot;634&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;설치가 완료되면 먼저 가지고 있는 구글 계정으로 로그인을 하고 챗봇 형태로 사용할 수 있다.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgMZJfpBiqlAeZ3c8mws22kOmV1JkBSJYS165RCyuPA-Y6wh0kAy8CgFDo6nZg19SeOGjKHapI50dCmqlzE1RiVuhW_v3xHvjovMlXSdIi7GO-JLCJLsE7lQHjdTHxubWmmDAYiaJsUBsHF6Xm8MX0kARHyhxDKp2BLvqQ1XXiD3jZRC2O_viOYK38DUd/s1404/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-02-27_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9_36_15.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1404&quot; data-original-width=&quot;1060&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAgMZJfpBiqlAeZ3c8mws22kOmV1JkBSJYS165RCyuPA-Y6wh0kAy8CgFDo6nZg19SeOGjKHapI50dCmqlzE1RiVuhW_v3xHvjovMlXSdIi7GO-JLCJLsE7lQHjdTHxubWmmDAYiaJsUBsHF6Xm8MX0kARHyhxDKp2BLvqQ1XXiD3jZRC2O_viOYK38DUd/w484-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-02-27_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_9_36_15.jpg&quot; width=&quot;484&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;코드 파일에서 Gemini Code Assist 프롬프트&lt;/h4&gt;&lt;/div&gt;&lt;div&gt;Control+I(Windows 및 Linux) 또는 Command+I(macOS)를 눌러 Gemini Code Assist&amp;nbsp;를 실행할 수 있다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxDHYpXpo7GlWH9mgXZq-cm9IDEkkk4e7FphSbwBUbaoWj4MmzbclXdNKWWlvCI9E6s7lHp99ErjVOlXXmVZgimfn8qk2Lla9W1r263ip4zEosL0j72M8MOCWo38zm2QLBf4_ZRmLvRDOZHGk2As8ITHqUSo1m2PyzJUF-RGAoBaNfNQIcQX-Yuf6-p3iR/s685/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.12.55.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;632&quot; data-original-width=&quot;685&quot; height=&quot;590&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxDHYpXpo7GlWH9mgXZq-cm9IDEkkk4e7FphSbwBUbaoWj4MmzbclXdNKWWlvCI9E6s7lHp99ErjVOlXXmVZgimfn8qk2Lla9W1r263ip4zEosL0j72M8MOCWo38zm2QLBf4_ZRmLvRDOZHGk2As8ITHqUSo1m2PyzJUF-RGAoBaNfNQIcQX-Yuf6-p3iR/w640-h590/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.12.55.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;채팅을 사용하여 선택한 코드로 Gemini Code Assist에 프롬프트 입력&lt;/h4&gt;&lt;/div&gt;&lt;div&gt;코드 블록을 선택하고 Gemini Code Assist 창에서 코드에 대한 프롬프트를 입력한다.&lt;/div&gt;&lt;div&gt;&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9lOsf_I9GulYrNh51yHOtXVd3024z0C0H0xDWAPW7x92wLRu08sASbC8uSHazzF00lU-Tluy-4i8IlJ1YkDEgt-vt-aZK6LqlKODKc76mXSolJgQonEOBrwggvMu13-0hBg3VtRdEs5M7plUu6M7m24fxbHl9ac1Xj5e_7bYQHeB42oL_b6vhIj4HTmqn/s1081/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.16.29.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;482&quot; data-original-width=&quot;1081&quot; height=&quot;286&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9lOsf_I9GulYrNh51yHOtXVd3024z0C0H0xDWAPW7x92wLRu08sASbC8uSHazzF00lU-Tluy-4i8IlJ1YkDEgt-vt-aZK6LqlKODKc76mXSolJgQonEOBrwggvMu13-0hBg3VtRdEs5M7plUu6M7m24fxbHl9ac1Xj5e_7bYQHeB42oL_b6vhIj4HTmqn/w640-h286/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-03-01%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%209.16.29.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;참고&lt;/h3&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;a href=&quot;https://cloud.google.com/workstations/docs/write-code-gemini?hl=ko&quot; target=&quot;_blank&quot;&gt;Gemini Code Assist를 사용한 코드&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/3185848518981799016/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2025/03/vscode-gemini-code-assist.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3185848518981799016'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3185848518981799016'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2025/03/vscode-gemini-code-assist.html' title='사용기 - VSCode 에서 Gemini Code Assist'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgot8VQ_AYqsw8yBfsFhpDDG8kEiaLlqcqUbrrt3r8c_GnZtKxVOPd9NWAVYp22tH6wCQlMAwhDKYVRbmSJFflZRjpAofcVSiId7MXBTK6CEzNS1abJ6juAlXnBvNbP3AgqNxK3uLt1Venz_a2y1MwMEj8kidR1Jgzshw46zwGCzU5UwongfgUjiFyU7TCC/s72-w640-h446-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-02-27%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.08.28.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-2940405919895953160</id><published>2024-12-19T20:14:00.002+09:00</published><updated>2024-12-27T13:05:07.769+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="chatgpt"/><category scheme="http://www.blogger.com/atom/ns#" term="swift"/><category scheme="http://www.blogger.com/atom/ns#" term="코딩 자동화"/><title type='text'>코딩 - ChatGPT 을 이용한 맥 프로그램 만들기(네임나이저)</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;ChatGPT 의 코딩 실력을 확인하는 목적과 Shift 코딩 연습을 목적으로 맥용 프로그램을 만들어 보았다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;◼︎ 개발 환경&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;HW : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 15.0.1 (24A348)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : XCode 16.1&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Shift&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;◼︎ 프로그램 요구사항&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;맥은 UTF-8 NFD (Normalization Form Decomposed)로 저장하는 반면, 윈도우는 UTF-8 NFC (Normalization Form Composed)를 사용 하는 차이로 인하여 맥에서 생성된 파일이 윈도우로 이동하면 자모가 분리되어 보여지는 현상이다. 이를 해결하기 위하여 아래와 같은 목표를 정의했다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Drag&amp;amp;Drop 기능을 활용&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;자소가 분리된(NFD) 유니코드 파일명을 자소가 조합된(NFC) 파일명으로 변환&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;참고로 ChatGPT 는 유료버전의 4o을 사용했고 개발 과정에서 모양과 기능은 &lt;a href=&quot;https://github.com/namhokim/cocoa_app&quot; target=&quot;_blank&quot;&gt;Contact&lt;/a&gt;&amp;nbsp;과 &lt;a href=&quot;https://kr.bandisoft.com/bandinamer/&quot; target=&quot;_blank&quot;&gt;반디네이머&lt;span style=&quot;color: black;&quot;&gt;를&lt;/span&gt;&lt;/a&gt; 참고했다.&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3&gt;어떻게 프로그램을 만들 것인가&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;맥에서 생성하거나 수정한 파일의 이름이 윈도우에서 깨지는 이슈가 있는데 자동으로 변환을 해주는 맥용 앱을 만들고 싶어.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvcykUDS_k1PMUfLl2kX-Oxkbs-Ur1SRDsDOnKqPxKW7-ZY3ghayxhvRCFlhs5lF-KQqnGnUuZv9jR6zV8oazw3ZqLC3HNxBqIO6TsrILhWXy9OOblvbDqT8fnIpPBQBIzQqEW2U4Q-p50EcrzGonB5tlEdjy3CVnpeICl4rMQcdhlD02UjD39s0h-Jomb/s1608/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.23.11.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1196&quot; data-original-width=&quot;1608&quot; height=&quot;475&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvcykUDS_k1PMUfLl2kX-Oxkbs-Ur1SRDsDOnKqPxKW7-ZY3ghayxhvRCFlhs5lF-KQqnGnUuZv9jR6zV8oazw3ZqLC3HNxBqIO6TsrILhWXy9OOblvbDqT8fnIpPBQBIzQqEW2U4Q-p50EcrzGonB5tlEdjy3CVnpeICl4rMQcdhlD02UjD39s0h-Jomb/w640-h475/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.23.11.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;전체적으로 어떻게 만들 것인가를 자세하게 설명해주고 있다. 추가로 좀더 구체적인 질문을 하며 상세하게 원하는 것을 설명해준다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;앱을 실행하면 파일 탐색기 처럼 좌측에는 폴더 우측에서 세부 파일 구조와 NFC, NFD 을 보여주고 선택된 파일 또는 폴더에 대하여 일괄적으로 NFD 형식의 유니코드 파일명을 NFC 변경하거나 반대로 변경하는 기능으로 구현하면&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🅰&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpN93fkVHji2XC506I2EaTI6HUoKtKgPvGOXt28Veq-6HHX6wquN_k4u3e_IkfIDeDjsQmpKrU5A5ADfrrtWFp_ILNP_r41MQlzecgTkE49nMtBEfqeR00kEErpSZvpdJApUMMCV3NdfRXrPLvwOK2geajANNRsWyRwDhYAYShMeO8L4abdryEe7ZpfHq4/s1584/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.26.07.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1164&quot; data-original-width=&quot;1584&quot; height=&quot;470&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpN93fkVHji2XC506I2EaTI6HUoKtKgPvGOXt28Veq-6HHX6wquN_k4u3e_IkfIDeDjsQmpKrU5A5ADfrrtWFp_ILNP_r41MQlzecgTkE49nMtBEfqeR00kEErpSZvpdJApUMMCV3NdfRXrPLvwOK2geajANNRsWyRwDhYAYShMeO8L4abdryEe7ZpfHq4/w640-h470/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.26.07.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;프로젝트 생성&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제시된 코드를 기반으로 &quot;Namenizer&quot; 라는 이름으로 XCode 프로젝트를 생성하였다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음으로는 컴파일을 통하여 코드를 실행하면서 지속적으로 코드 수정을 요청하고 이를 반복하였다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;&quot;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Namenizer&lt;/span&gt;&quot; 프로그램 코딩&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;코딩 과정의 최초의 문제는 모든 파일들을 보여주지 못한다는 점이었다.&amp;nbsp; download 등 주요한 폴더들은 표시되지 않았다.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;downloads 와 같은 폴더는 접근할 수 없는데&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTQOBn74bYBa9Z_HBOvUH5ebl-3QsBueHnVdOG08op6ZLCGykuZzNNmQdnFTwZREt4jzleVCl7atfSSf5j-WF1fkFEOze0EnxY8fSN6A5T9s7zCC0kUBkWCnoZxOE78b9EmYJ4-ODEgH2FlY7idtCWzN_RIqENytYt8upZM_4SuYE3Whd5u4WBmTuexIBZ/s1596/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.34.11.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1058&quot; data-original-width=&quot;1596&quot; height=&quot;424&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjTQOBn74bYBa9Z_HBOvUH5ebl-3QsBueHnVdOG08op6ZLCGykuZzNNmQdnFTwZREt4jzleVCl7atfSSf5j-WF1fkFEOze0EnxY8fSN6A5T9s7zCC0kUBkWCnoZxOE78b9EmYJ4-ODEgH2FlY7idtCWzN_RIqENytYt8upZM_4SuYE3Whd5u4WBmTuexIBZ/w640-h424/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.34.11.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;해결방법은 크게 ❶ Sandbox 설정을 통하여 보안을 무력화 하거나 ❷ NSOpenPanel을 사용하여 사용자에게 권한 요청하는 방식을 알려주었는데 두번쨰 방법을 사용하는 것을 선택하고&amp;nbsp; 제시되는 코드를 사용하여 코드를 수정했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;두번째 문제는 반디네이머와 같이 NFD 유니코드로 인하여 윈도우에서 한글 자모가 분리되는 것을 미리 보여주는 기능을 구현하는 것이었다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🆀&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;NFD 여부를 알려면&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🅰&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3WnuvVlJb-lHOItLKZKEPTe8j3wqQZFizBLkO6Qf-dZ1pv3TnW-Kg3Eo9fsaPRSGV1lQw13HKnTNgYZ235lk1pwr2_m-3faz3zjRRvrZqb7NEoWm9OjLApt_xR7zqoHtfvHAiSJC5drPOYce4UelAa-UBIOCjHAprkDi1H8tzxTktcujck3as-tKh2E1N/s1624/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.47.25.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1156&quot; data-original-width=&quot;1624&quot; height=&quot;456&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3WnuvVlJb-lHOItLKZKEPTe8j3wqQZFizBLkO6Qf-dZ1pv3TnW-Kg3Eo9fsaPRSGV1lQw13HKnTNgYZ235lk1pwr2_m-3faz3zjRRvrZqb7NEoWm9OjLApt_xR7zqoHtfvHAiSJC5drPOYce4UelAa-UBIOCjHAprkDi1H8tzxTktcujck3as-tKh2E1N/w640-h456/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.47.25.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;제안된 방법으로 코딩을 해보았지만 자모가 분리되어 보이지 않았다. 지루한 주고받는 방식의 질의를 통하여 알게된 유니코드 디버딩 과정에서 보여지는 텍스트와 유니코드 값의 차이를 확하게 되었다. (동일하게 보이는 텍스트가 유니코드 값이 다르게 보여짐. 보통 NFD 의 경우 유니코드 값이 더 많았다.) &quot;그럼 유니코드 값의 동일 유무를 검사하면 되겠네&quot; 가정을 수립하고 확인을 위한 질문을 계속한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🆀&amp;nbsp;&lt;/span&gt;항상 NFC 로만 보여지는 이유는&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🅰&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH-CEj3jq6pT1RaDM4sHdbsOxbYFJRoWX0mXci976e-hs0VcqRxDotICuO67cBW1f9QXOrqMNPGXIcfOFLJoi72E9Ip2nnURbuU8fpta6jN2970OUJiGanGNvNy1B54rbQI4AM3I35xxKZlXWbhSIjGRtOh3SNuyqBDXup0_MhFyCKHlWIFwQEv0ZaGgRn/s1592/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.51.15.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1118&quot; data-original-width=&quot;1592&quot; height=&quot;450&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH-CEj3jq6pT1RaDM4sHdbsOxbYFJRoWX0mXci976e-hs0VcqRxDotICuO67cBW1f9QXOrqMNPGXIcfOFLJoi72E9Ip2nnURbuU8fpta6jN2970OUJiGanGNvNy1B54rbQI4AM3I35xxKZlXWbhSIjGRtOh3SNuyqBDXup0_MhFyCKHlWIFwQEv0ZaGgRn/w640-h450/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.51.15.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;NFC 여부를 판단하는 방법으로 제시된 다음 코드를 기반으로 추가 질의를 하여 이 문제를 좀더 깊이 확인 해보았다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s2&quot; style=&quot;color: #0f68a0;&quot;&gt;isNFC&lt;/span&gt;(&lt;span class=&quot;s2&quot; style=&quot;color: #0f68a0;&quot;&gt;_&lt;/span&gt; string: &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;) -&amp;gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Bool&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s4&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; string == string.&lt;/span&gt;precomposedStringWithCanonicalMapping&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🆀&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;func isNFC(_ string: String) -&amp;gt; Bool { 
        return string == string.precomposedStringWithCanonicalMapping
    } &lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코드가 항상 true 을 리턴하는 것 은&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0a48-NfluEO5YnTGLxuVPxhKOMK6cUH_kNomAdnuU1fOxkhc6xbpQsg5p5-J1k56jwM_Yr8EjzUavdmxRl2LEUfEeG2DzArAVtSH74UU5E31WqOmXCN7r3vh22TFXxgSf2TymxjCe4R2PUWdZ-__qlynQXMvueHgtD8k4Y8td_UCRBPuU3-FskJspqnK1/s1608/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.56.20.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1232&quot; data-original-width=&quot;1608&quot; height=&quot;490&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0a48-NfluEO5YnTGLxuVPxhKOMK6cUH_kNomAdnuU1fOxkhc6xbpQsg5p5-J1k56jwM_Yr8EjzUavdmxRl2LEUfEeG2DzArAVtSH74UU5E31WqOmXCN7r3vh22TFXxgSf2TymxjCe4R2PUWdZ-__qlynQXMvueHgtD8k4Y8td_UCRBPuU3-FskJspqnK1/w640-h490/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.56.20.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이러한 내용을 바탕으로 유니코드 값을 활용하여 NFD 정규화 상태인지 확인하는 함수는 앞서 제시된 유니코드 디버깅을 활용하여 직접 문제를 아래와 같이 해결했다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;background-color: white; color: #5d6c79; font-family: &amp;quot;Helvetica Neue&amp;quot;; font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #5d6c79; font-family: &amp;quot;Helvetica Neue&amp;quot;; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot; style=&quot;font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(93, 108, 121, 0.35)&quot; style=&quot;font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal;&quot;&gt;///&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot; style=&quot;font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal;&quot;&gt; &lt;/span&gt;문자열이 NFD로 정규화된 상태인지 확인하는 함수&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;isNFDUsingUnicodeScalars&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; string: &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;// NFD로 변환된 문자열&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; nfdString = string.&lt;/span&gt;decomposedStringWithCanonicalMapping&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;// 원본 문자열과 NFD로 변환된 문자열의 유니코드 스칼라를 비교&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; string.&lt;/span&gt;unicodeScalars&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;elementsEqual&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(nfdString.&lt;/span&gt;unicodeScalars&lt;span class=&quot;s3&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;background-color: white; color: #5d6c79; font-family: &amp;quot;Helvetica Neue&amp;quot;; font-size: 12px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 과정에서 알게된 건 &quot;&lt;strong&gt;macOS 파일 시스템&lt;/strong&gt;에서 파일 이름을 읽어올 때는 NFD로 변환된 상태로 제공할 수 있다&quot;라는 가능성이 있다는 것이었다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🆀&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;자모가 분리되는 것을 보여주는 것은 다음 질문에 대한 답으로 해결할 수 있었다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;originalString.decomposedStringWithCanonicalMapping 해도 자모가 분리되어 보이지 않는다면&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; font-family: &amp;quot;Nanum Gothic&amp;quot;; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbKsdM1zmr34Je7HK7VV8gfdqne5f-LzeRBqjXaRHNeS-DIfv-8KiBUALVFelSf9zXCsjySGlpfkmtoV_rJ_Gd6aFnTy2eK5SS_Xd96FMx5EFXY72Y-9CmM6_nosq8SDKNCy84hjEBSn78SSgr1o6GQvC5TQfmjRtkVUU10t6vMUDbcAs4j0L4I3FIevyp/s1480/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.03.29.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1300&quot; data-original-width=&quot;1480&quot; height=&quot;562&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbKsdM1zmr34Je7HK7VV8gfdqne5f-LzeRBqjXaRHNeS-DIfv-8KiBUALVFelSf9zXCsjySGlpfkmtoV_rJ_Gd6aFnTy2eK5SS_Xd96FMx5EFXY72Y-9CmM6_nosq8SDKNCy84hjEBSn78SSgr1o6GQvC5TQfmjRtkVUU10t6vMUDbcAs4j0L4I3FIevyp/w640-h562/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.03.29.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;마지막 가장 큰 문제는&amp;nbsp;NFC 로 파일 이름을 변경하는 것이었다. 제시된 코드는 정상동작 하지 않아 관련하여 질문을 해보았다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;NFC 유니코드를 출력하면 다른 값으로 보이는데&amp;nbsp; 파일이름을 NFC 로 저장하고 다시 읽으면 변경되어 있지 않는데&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy8FjSVT9ixaFA0oGUfcD75gErL1DFb9qTC5UhJYzlUWfQVKce51bbl_xqqaFaFFxTXs_ooEdqsXw0SA6klhyCIrvTQ9tE2cfG510sgZfHP-K3JNrF1jGiSMGdw6JtPEeYF7qasa99iV_Su_7nTH3TO0XZjSpvy7U5fgLW1VwkAqULyJCxo-Tt7HA00n2Q/s1616/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.08.20.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1134&quot; data-original-width=&quot;1616&quot; height=&quot;450&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy8FjSVT9ixaFA0oGUfcD75gErL1DFb9qTC5UhJYzlUWfQVKce51bbl_xqqaFaFFxTXs_ooEdqsXw0SA6klhyCIrvTQ9tE2cfG510sgZfHP-K3JNrF1jGiSMGdw6JtPEeYF7qasa99iV_Su_7nTH3TO0XZjSpvy7U5fgLW1VwkAqULyJCxo-Tt7HA00n2Q/w640-h450/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.08.20.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;결론은 macOS 파일 시스템(APFS, HFS+)은 파일 이름을 항상 NFD로 저장하기 때문에 정상적인 방법으로는 불가하다고 판단하였다.&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;커멘드를 실행하여 처리하면&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;별도의 설치없이 사용하는 커멘드는 없는가&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;Swift 코드에서 커멘드를 실행하도록&amp;nbsp;만들면&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Perl 명령을 사용한 파일 이름 변경은 실패하였다. 아래는 GPT 가 제시한 방법이다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;convertFileNameToNFCUsingPerl&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; url: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; originalPath = url.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;path&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; directory = url.&lt;/span&gt;deletingLastPathComponent&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;().&lt;/span&gt;path&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; fileName = url.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;lastPathComponent&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; perlCommand = &lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;/usr/bin/perl -CIO -MUnicode::Normalize -e &#39;rename shift, shift&#39; &quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(originalPath)&lt;/span&gt;&quot; &quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(directory)&lt;/span&gt;/$(/usr/bin/perl -CIO -MUnicode::Normalize -e &#39;print NFC(shift)&#39; &quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(fileName)&lt;/span&gt;&quot;)&quot;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&quot;&quot;&quot;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; process = &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Process&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;process.&lt;/span&gt;executableURL&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;fileURLWithPath&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;/bin/zsh&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #5d6c79;&quot;&gt;// 또는 &quot;/bin/bash&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;process.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;arguments&lt;/span&gt; = [&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;-c&quot;&lt;/span&gt;, perlCommand]&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; pipe = &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Pipe&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;process.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;standardOutput&lt;/span&gt; = pipe&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;process.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;standardError&lt;/span&gt; = pipe&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt; process.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;run&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;process.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;waitUntilExit&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; data = pipe.&lt;/span&gt;fileHandleForReading&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;readDataToEndOfFile&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; output = &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;data&lt;/span&gt;: data, &lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;encoding&lt;/span&gt;: .&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;utf8&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;(output)&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; process.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;terminationStatus&lt;/span&gt; == &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;0&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;파일 이름이 NFC로 변환되었습니다.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;perl 명령어 실행 실패&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;catch&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;print&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;파일 이름 변환 실패: &lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(error.&lt;/span&gt;localizedDescription&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-emoji: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;}&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;결국 Contact 코드를 분석하여 문제를 해결해보기로 했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;https://github.com/namhokim/cocoa_app 에서는 위 문제를 어떻게 해결하고 있지&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;https://github.com/namhokim/cocoa_app 를 참고하여 convertFileNameToNFC 함수를 만들면&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;문제 해결이 되지 않았고&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Contact&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;프로젝트 소스를 확인해보니 perl 정규식이 아닌 단순 mv 명령으로 이름을 변경하는 것으로 확인하여 다시 질문을 했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;https://github.com/namhokim/cocoa_app 는 mv 을 사용하여 처리하지 않았나&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🅰&amp;nbsp;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifzMvUz6uXrNlEKkzQCL1xCHTldJ26yNmQwHW09hJrc7NQhAne28ACW-rT5PkKAvFRzufSwxSKKxNp0xl0wwqcIuJMjEtvrDXok3BLEls7wP1SYt699tkrjVwx74vPkOlnSx8pZmDDDT-WWAQLTTMfK_kApqqTO7UO7V3ru51lJc29V-IiMRKkvckBJeJO/s1654/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.23.02.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1272&quot; data-original-width=&quot;1654&quot; height=&quot;492&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifzMvUz6uXrNlEKkzQCL1xCHTldJ26yNmQwHW09hJrc7NQhAne28ACW-rT5PkKAvFRzufSwxSKKxNp0xl0wwqcIuJMjEtvrDXok3BLEls7wP1SYt699tkrjVwx74vPkOlnSx8pZmDDDT-WWAQLTTMfK_kApqqTO7UO7V3ru51lJc29V-IiMRKkvckBJeJO/w640-h492/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.23.02.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Perl 을 정규식을 사용하는 점을 제외하면 동일한 방식으로 코드를 제안했지만 문제가 해결되지 않았다. 결국 Contact 의 변환소스에 해당하는 &lt;a href=&quot;https://github.com/namhokim/cocoa_app/blob/master/Contact/Contact/ScriptGenerator/ScriptGenerator.swift&quot; target=&quot;_blank&quot;&gt;소스&lt;/a&gt;를 분석하게 하고 동일하게 코드를 만들라고 하여 문제를 해결 할수 있었다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;🅰&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6FVSiXXSlK8pHwPz5EitIL8h2tmdbqpoAsDDYjNEwf1ibeHI11U0mTeAVcYMTvizJiaIIYyDTN_wX4zcry6ajrwbC5xsoG-2bf4OX8mC-GrJtgzVlcbkQ5nNbqYsAjDTEZ-hfXy48dGkUjnaCkqBcJnRC2hFUohWu7xoVd_MhEJm0euOL1tB15d2chrcX/s1596/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.28.05.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1270&quot; data-original-width=&quot;1596&quot; height=&quot;510&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6FVSiXXSlK8pHwPz5EitIL8h2tmdbqpoAsDDYjNEwf1ibeHI11U0mTeAVcYMTvizJiaIIYyDTN_wX4zcry6ajrwbC5xsoG-2bf4OX8mC-GrJtgzVlcbkQ5nNbqYsAjDTEZ-hfXy48dGkUjnaCkqBcJnRC2hFUohWu7xoVd_MhEJm0euOL1tB15d2chrcX/w640-h510/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.28.05.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;mv 스크립트를 생성하여 실행하는 방식은 정상 동작하고 perl 스크립트 방식에서는 잘못된 문자들로 저장되는 원인을 물어보았으나 이부분에 대한 명확한 답변을 듣지 못했다. 다만 아래와 같은&amp;nbsp; mv 가 좀더 신뢰성 있게 동작한다는 답변을 얻었다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFKzWslMpMdBzDAsDLlvsodhp8r7btqR-sSsp4x2Q0LaRbdFKCoftTZe08D8QADW5lZnu6yIx7SKbWBtwImsWLwmOuDyHRYqzphN9gBxPOOUlKwhnOEKk9Hhk2HGvF-qx7iFZI1V-GFqgcQ6Yl0mQmxYu6v_IXVCpkrsBKMaB650tCfEkw_e7eRjouu2Ow/s1512/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-12-20_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_19_54.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1072&quot; data-original-width=&quot;1512&quot; height=&quot;454&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFKzWslMpMdBzDAsDLlvsodhp8r7btqR-sSsp4x2Q0LaRbdFKCoftTZe08D8QADW5lZnu6yIx7SKbWBtwImsWLwmOuDyHRYqzphN9gBxPOOUlKwhnOEKk9Hhk2HGvF-qx7iFZI1V-GFqgcQ6Yl0mQmxYu6v_IXVCpkrsBKMaB650tCfEkw_e7eRjouu2Ow/w640-h454/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-12-20_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_9_19_54.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;아래는 마직막으로 작성된 코드를 실행하는 화면이다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Z_fPq_dTssc6TQFnOP17aGvrAg-S5FRvpiljrRpJ7UevHssl09XQbokKn_Y0vCASMIxVkN8onvZfGHLzdwNInL12BLBGSlYcNd7QwDITXOn_H-ZGsA65vXjCE7-AtSX6GUNpf0KI7ZpftXhGU5oVJzKgG403fuAHajouSRw6lsRBB6JeRVA7CpzU6WmY/s2338/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-12-19_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_37_02.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1302&quot; data-original-width=&quot;2338&quot; height=&quot;356&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_Z_fPq_dTssc6TQFnOP17aGvrAg-S5FRvpiljrRpJ7UevHssl09XQbokKn_Y0vCASMIxVkN8onvZfGHLzdwNInL12BLBGSlYcNd7QwDITXOn_H-ZGsA65vXjCE7-AtSX6GUNpf0KI7ZpftXhGU5oVJzKgG403fuAHajouSRw6lsRBB6JeRVA7CpzU6WmY/w640-h356/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-12-19_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_5_37_02.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;전체 소스 :&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://github.com/andang72/andang72.unsplash &quot; target=&quot;_blank&quot;&gt;https://github.com/andang72/andang72.namenizer&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;article class=&quot;w-full scroll-mb-[var(--thread-trailing-height,150px)] text-token-text-primary focus-visible:outline-2 focus-visible:outline-offset-[-4px]&quot; data-scroll-anchor=&quot;false&quot; data-testid=&quot;conversation-turn-194&quot; dir=&quot;auto&quot;&gt;&lt;div class=&quot;m-auto text-base py-[18px] px-3 md:px-4 w-full md:px-5 lg:px-4 xl:px-5&quot;&gt;&lt;div class=&quot;mx-auto flex flex-1 gap-4 text-base md:gap-5 lg:gap-6 md:max-w-3xl&quot;&gt;&lt;div class=&quot;group/conversation-turn relative flex w-full min-w-0 flex-col&quot;&gt;&lt;div class=&quot;flex-col gap-1 md:gap-3&quot;&gt;&lt;div class=&quot;flex max-w-full flex-col flex-grow&quot;&gt;&lt;div class=&quot;min-h-8 text-message flex w-full flex-col items-end gap-2 whitespace-normal break-words text-start [.text-message+&amp;amp;]:mt-5&quot; data-message-author-role=&quot;user&quot; data-message-id=&quot;aaa2345a-d068-4442-928b-e462d9efda90&quot; dir=&quot;auto&quot;&gt;&lt;div class=&quot;flex w-full flex-col gap-1 empty:hidden items-end rtl:items-start&quot;&gt;&lt;div class=&quot;relative max-w-[var(--user-chat-width,70%)] rounded-3xl bg-token-message-surface px-5 py-2.5&quot;&gt;&lt;div class=&quot;whitespace-pre-wrap&quot;&gt;&lt;/div&gt;&lt;div class=&quot;absolute bottom-0 right-full top-0 -mr-3.5 hidden pr-5 pt-1 [.group\/conversation-turn:hover_&amp;amp;]:block&quot;&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;button aria-label=&quot;메시지 편집&quot; class=&quot;flex h-9 w-9 items-center justify-center rounded-full text-token-text-secondary transition hover:bg-token-main-surface-tertiary&quot;&gt;&lt;svg class=&quot;icon-md&quot; fill=&quot;none&quot; height=&quot;24&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;24&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;&lt;path clip-rule=&quot;evenodd&quot; d=&quot;M13.2929 4.29291C15.0641 2.52167 17.9359 2.52167 19.7071 4.2929C21.4784 6.06414 21.4784 8.93588 19.7071 10.7071L18.7073 11.7069L11.6135 18.8007C10.8766 19.5376 9.92793 20.0258 8.89999 20.1971L4.16441 20.9864C3.84585 21.0395 3.52127 20.9355 3.29291 20.7071C3.06454 20.4788 2.96053 20.1542 3.01362 19.8356L3.80288 15.1C3.9742 14.0721 4.46243 13.1234 5.19932 12.3865L13.2929 4.29291ZM13 7.41422L6.61353 13.8007C6.1714 14.2428 5.87846 14.8121 5.77567 15.4288L5.21656 18.7835L8.57119 18.2244C9.18795 18.1216 9.75719 17.8286 10.1993 17.3865L16.5858 11L13 7.41422ZM18 9.5858L14.4142 6.00001L14.7071 5.70712C15.6973 4.71693 17.3027 4.71693 18.2929 5.70712C19.2831 6.69731 19.2831 8.30272 18.2929 9.29291L18 9.5858Z&quot; fill-rule=&quot;evenodd&quot; fill=&quot;currentColor&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/article&gt;&lt;article class=&quot;w-full scroll-mb-[var(--thread-trailing-height,150px)] text-token-text-primary focus-visible:outline-2 focus-visible:outline-offset-[-4px]&quot; data-scroll-anchor=&quot;false&quot; data-testid=&quot;conversation-turn-195&quot; dir=&quot;auto&quot;&gt;&lt;h6 class=&quot;sr-only&quot;&gt;&lt;/h6&gt;&lt;/article&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/2940405919895953160/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/12/chatgpt.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/2940405919895953160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/2940405919895953160'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/12/chatgpt.html' title='코딩 - ChatGPT 을 이용한 맥 프로그램 만들기(네임나이저)'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvcykUDS_k1PMUfLl2kX-Oxkbs-Ur1SRDsDOnKqPxKW7-ZY3ghayxhvRCFlhs5lF-KQqnGnUuZv9jR6zV8oazw3ZqLC3HNxBqIO6TsrILhWXy9OOblvbDqT8fnIpPBQBIzQqEW2U4Q-p50EcrzGonB5tlEdjy3CVnpeICl4rMQcdhlD02UjD39s0h-Jomb/s72-w640-h475-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.23.11.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-4744271626799655702</id><published>2024-11-08T16:13:00.004+09:00</published><updated>2024-11-18T10:39:52.797+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI 코딩"/><category scheme="http://www.blogger.com/atom/ns#" term="chatgpt"/><category scheme="http://www.blogger.com/atom/ns#" term="맥 프로그램"/><category scheme="http://www.blogger.com/atom/ns#" term="코딩 자동화"/><title type='text'>코딩 - ChatGPT 을 이용한 맥 프로그램 만들기(오늘의 명언)</title><content type='html'>&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ChatGPT 의 코딩 실력을 확인하는 목적으로 간단한 맥용 프로그램을 만들어 보았다. 참고로 맥 프로그래밍은 과거에 관련 서적을 보고 Object C 기반의 웹뷰 예제를 만들어 본것이 전부이다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;◼︎ 개발 환경&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;HW : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 15.0.1 (24A348)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS :  XCode 16.1 &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Shift&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt; ◼︎ 프로그램 요구사항&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;배경 이미지와 명언이 프로그램을 클릭하면 변경되는 간단한 오늘의 명언 프로그램.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;간단한 날씨정보도 같이 보여줌.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참고로 ChatGPT 는 유료버전의 4o을 사용했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;어떻게 프로그램을 만들 것인가 알아보기&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 맥에서 동작하는 Unsplash 에서 랜덤 이미지를 배경으로 명언 보여주는  프로그램을 스위프트를 사용하여 만들고 싶다. 화면을 클릭하면 매번 배경이미지와 명언을 새로 보여주고 싶다.&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 이 프로그램은 Xcode에서 Swift와 Cocoa 프레임워크를 사용해 개발할 수 있으며, 네트워크 요청을 통해 Unsplash API에서 이미지를 가져오고 화면에 표시하는 방식입니다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;요약 후 아래와 같은 절차를 가이드 한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Unsplash API 키 준비&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;XCode 을 설치&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;새로운 App 프로젝트를 생성&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예제 코드&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;명언 역시 외부에서 가져오고 싶어 아래와 같은 질문을 했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 명언도 API 을 사용하여 랜덤하게 가져오려면&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;명언을 API에서 랜덤하게 가져오려면 다양한 명언 API를 사용할 수 있습니다. 예를 들어, Quotes REST API나 ZenQuotes API를 사용하면 간편하게 랜덤 명언을 가져올 수 있습니다. 여기서는 ZenQuotes API를 사용하여 Swift 코드에 적용하는 방법을 설명드리겠습니다.&lt;br /&gt;&lt;br /&gt;요약 후 앞의 코드에 명언을 &lt;a href=&quot;https://docs.zenquotes.io/zenquotes-documentation/&quot; target=&quot;_blank&quot;&gt;ZenQuotes API &lt;/a&gt;사용하여 가져오는 수정된 코드를 제시한다. (참고로 ZenQuotes API 는&amp;nbsp;API Key 없이 사용할 수 있다.)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;프로젝트 생성&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ChatGPT 가이드에 따라 XCode 을 사용하여 새로운 &quot;오늘의 명언&quot; 프로젝트를 아래 절차로 생성하였다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieN_uhZ8qyPPWVHYsMQuY-TkdQkKCB5DcpG-4QtjZOBg2c1J4XeOJlXwf3nZHaLxHGl2HZeXXvLvugLVasijsL3YYbgo7fROad2rVRtg-jg8jgaF5AJCc9-ND21JCTGTSi21_lgQvtNNqK6oTEZY-K175U9zYVKe5EBCX_InXOiJf7Or9ajrKOenPexUAF/s1510/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_16_23.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img alt=&quot;그림1. 새로운 프로젝트 생성&quot; border=&quot;0&quot; data-original-height=&quot;950&quot; data-original-width=&quot;1510&quot; height=&quot;402&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieN_uhZ8qyPPWVHYsMQuY-TkdQkKCB5DcpG-4QtjZOBg2c1J4XeOJlXwf3nZHaLxHGl2HZeXXvLvugLVasijsL3YYbgo7fROad2rVRtg-jg8jgaF5AJCc9-ND21JCTGTSi21_lgQvtNNqK6oTEZY-K175U9zYVKe5EBCX_InXOiJf7Or9ajrKOenPexUAF/w640-h402/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_16_23.jpg&quot; title=&quot;그림1. 새로운 프로젝트 생성&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그림1. 새로운 프로젝트 생성&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirA2hMooKXfgibDolSeR2emvZX9ymOJA0HzyX7s6x8r_N79F8qGzppJYfdX_914YpuHbe_VfB-qcc2Bw_p8v7ks2LEmfdjQA3RsirZ3XgTisZ_6meeYu2TQq7PQi4CpGUoddk9ov8vxYENKNMdKKj24Q7gpREg-g6Zd9Sj3RjmACIpuGH4WHmEuq-Fy_yI/s1818/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_21_10.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1358&quot; data-original-width=&quot;1818&quot; height=&quot;478&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirA2hMooKXfgibDolSeR2emvZX9ymOJA0HzyX7s6x8r_N79F8qGzppJYfdX_914YpuHbe_VfB-qcc2Bw_p8v7ks2LEmfdjQA3RsirZ3XgTisZ_6meeYu2TQq7PQi4CpGUoddk9ov8vxYENKNMdKKj24Q7gpREg-g6Zd9Sj3RjmACIpuGH4WHmEuq-Fy_yI/w640-h478/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_21_10.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그림2. 템플릿 목록에서 App 선택&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihdKLCXja4_a59YYUAdjd25l0MKbUZ7upyplvYVBbvqR-nPNUQ9JbPYUwvRkJtrmyaQsx4h-UGxxJ4YX4CRHg8N-VuMvNne2d2ZdoBmPyu_ENMVkKEgPnSpGHwbDAtnBovgRsglgmYI-F3Gk4aNIrK4Sxo4jrUnEXpYjDvfjJ1PLz0HrJfavNedHwndIvY/s1622/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_23_56.jpg&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1200&quot; data-original-width=&quot;1622&quot; height=&quot;474&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihdKLCXja4_a59YYUAdjd25l0MKbUZ7upyplvYVBbvqR-nPNUQ9JbPYUwvRkJtrmyaQsx4h-UGxxJ4YX4CRHg8N-VuMvNne2d2ZdoBmPyu_ENMVkKEgPnSpGHwbDAtnBovgRsglgmYI-F3Gk4aNIrK4Sxo4jrUnEXpYjDvfjJ1PLz0HrJfavNedHwndIvY/w640-h474/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_23_56.jpg&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그림3. 프로젝트 정보 입력 및 생성&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;(생성시 Testing System 을 None 로 변경하여 테스트를 위한 프로그램들이 생성되지 않도록 했다.)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;XCode 에 의하여 생성된 프로젝트는 아래과 같은 파일로 구성된다. (프로젝트 이름을 Quotes 로 한 경우)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlTfx_chp9zgSn4UkP7Ckpai8z3BM-63uyDOnBJB1DFUmJzQkCjFTsIF6fQiH5nt-OwU3fBNcCpnWM0yLImSKjusuJujFO9lkXIqwMTVsxSxPL1LTp8_jITh7uklhcN2YYQkYimRPkaWrAgu-d9l8txkg_qBJAZBP_LXj_T3MoLeYmxPW6BdtaxQNJfDpe/s746/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.30.31.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;746&quot; data-original-width=&quot;586&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlTfx_chp9zgSn4UkP7Ckpai8z3BM-63uyDOnBJB1DFUmJzQkCjFTsIF6fQiH5nt-OwU3fBNcCpnWM0yLImSKjusuJujFO9lkXIqwMTVsxSxPL1LTp8_jITh7uklhcN2YYQkYimRPkaWrAgu-d9l8txkg_qBJAZBP_LXj_T3MoLeYmxPW6BdtaxQNJfDpe/w314-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.30.31.png&quot; width=&quot;314&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그림4. 생성된 프로젝트 파일 구조&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;Unsplash API 사용을 위해서는 API Key 가 필요하다. API Key 는&amp;nbsp;&lt;a href=&quot;https://unsplash.com/ko&quot; target=&quot;_blank&quot;&gt; Unsplash 홈페이지&lt;/a&gt;&amp;nbsp;에서 회원 가입 후&amp;nbsp;&lt;a href=&quot;https://unsplash.com/developers&quot; target=&quot;_blank&quot;&gt;Unsplash Developer&lt;/a&gt;&amp;nbsp;페이지로 이동해서 &lt;u&gt;Your Apps&lt;/u&gt; 섹션에서 &lt;u&gt;New Application&lt;/u&gt;&amp;nbsp;버튼을 클릭하여 새로운 앱을 만드는 것으로 키를 생성할 수 있다.&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;h3&gt;&quot;오늘의 명언&quot; 프로그램 코딩&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ContentView 소스는 ChatGPT 가 제시한 코드를 적용하였다.&lt;br /&gt;빌드하고 실행하면 통신 오류 처럼 보여지는 에러를 확인 할 수 있는데 이 부분을 해결하는 것에 큰 어려움이 있었다. &lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;Error fetching quote: Error Domain=NSURLErrorDomain Code=-1003 &quot;A server with the specified hostname could not be found.&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ChatGPT 는 위 오류에 대하여 (앱과 서버 간의 통신을 HTTPS를 통한 암호화된 연결로 제한하는) &lt;u&gt;⑴ATS&lt;/u&gt; 설정을 추가하거나 &lt;u&gt;⑵서버 API 상태&lt;/u&gt;,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;u&gt;⑶&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;u&gt;방화벽&lt;/u&gt; 점검을 해결방법을 제안하였다. 외부 서비스가 https 을 사용하는 이유로 ATS 문제는 아니고 방화벽 과 같은 네트워크 문제도 아닌것으로 확신하여 프로젝트 설정에 보안 관련 사항이 있는 것은 아닌가를 의심하고 아래와 같은 추가 질문을 했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;❉&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;&amp;nbsp;ATS(App Transport Security) &lt;/b&gt;는&amp;nbsp; Apple이 iOS 9 및 macOS 10.11(El Capitan)부터 앱의 네트워크 보안을 강화하기 위해 도입한 기술이다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;ATS는 앱이 네트워크를 통해 데이터를 전송할 때 보안이 강화된 HTTPS 연결을 사용하도록 요구하며 이를 통해 중간자 공격, 데이터 탈취 등의 위험을 줄이고 네트워크 보안 표준을 준수하도록 한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 맥용 앱 프로젝트는 보안 관련 고려하여야 할 제약이 있는가&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkulRoZMvK20ckjL8dSheZNbM6x2E2yCBH_3Sr3T_NaiNTvVRGv7ZBgF2ftrnRnRuxFQHqSmJMNYi1DHlsVpZPYeYBZD7342hYy5qSWO472lb2wHYdIfOpmMF7PS1UufKRZghWvgFnvp7RPJWleJcm4YJko9ire7-VBAXi4hbBFrKJMa-TbcMhyFvKcFu_/s1702/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_26_43.jpg&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1188&quot; data-original-width=&quot;1702&quot; height=&quot;446&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkulRoZMvK20ckjL8dSheZNbM6x2E2yCBH_3Sr3T_NaiNTvVRGv7ZBgF2ftrnRnRuxFQHqSmJMNYi1DHlsVpZPYeYBZD7342hYy5qSWO472lb2wHYdIfOpmMF7PS1UufKRZghWvgFnvp7RPJWleJcm4YJko9ire7-VBAXi4hbBFrKJMa-TbcMhyFvKcFu_/w640-h446/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_26_43.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;답변 &lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;내용중에서 App Sandbox 관련 이슈라는 확신을 갖고 아래와 같은 질문을 했다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;🆀 App Sandbox 에서 Connections 등의 세부 권한을 추가 하려면&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;답변에 따라 프로젝트의 Xcode에서 프로젝트 파일을 클릭하고, Targets에서 앱의 타겟을 선택한 후 Signing &amp;amp; Capabilities 탭으로 이동 &lt;u&gt;Outgoing&amp;nbsp;Connections&lt;/u&gt; 항목을 체크 하여 문제를 해결하였다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu5V9SiiOoenLjjwXY3WauPUQvvLgRyBDVwyQamD1M3cL0BoCl4CQBTrEvqz3eESqTn6_yddA6vFWxVHqenfblGAIlb5J4OYnShtYZy0gywcOKoIl7bcKAiAJeq2Ffm2QWxA7kMDJOCiwp3YcS5W0y6gJzgjaWk4n7GVwE-yjxxr7MM11-dau-FFhgdan4/s2308/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_43_57.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1292&quot; data-original-width=&quot;2308&quot; height=&quot;358&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu5V9SiiOoenLjjwXY3WauPUQvvLgRyBDVwyQamD1M3cL0BoCl4CQBTrEvqz3eESqTn6_yddA6vFWxVHqenfblGAIlb5J4OYnShtYZy0gywcOKoIl7bcKAiAJeq2Ffm2QWxA7kMDJOCiwp3YcS5W0y6gJzgjaWk4n7GVwE-yjxxr7MM11-dau-FFhgdan4/w640-h358/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2_43_57.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이제 프로그램을 실행하면 아래와 같다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtne0Non3Z8Z87wy1_tWw3LtU98wlhCJUrTpWJimhjtgJC0S78vI-BRkRQXciV51DZoPDQ-gQRVVxl61Zce4R-VfxGfcqxWLqBHkfMgrHEQ6xkk3bF7C1j5w-_P-gZyJZWi3xnH094AjMZ83RSEqicdXB9z5opQH7urdADKEj4US-9QjMLg-kOm69X-U9R/s2006/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.52.17.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1210&quot; data-original-width=&quot;2006&quot; height=&quot;386&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtne0Non3Z8Z87wy1_tWw3LtU98wlhCJUrTpWJimhjtgJC0S78vI-BRkRQXciV51DZoPDQ-gQRVVxl61Zce4R-VfxGfcqxWLqBHkfMgrHEQ6xkk3bF7C1j5w-_P-gZyJZWi3xnH094AjMZ83RSEqicdXB9z5opQH7urdADKEj4US-9QjMLg-kOm69X-U9R/w640-h386/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-06%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.52.17.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;❉&lt;/span&gt;&lt;b style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;A&lt;/b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;pp Sandbox&lt;/b&gt;&lt;/span&gt;&lt;b style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;는&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Apple은 보안을 강화하고 앱이 사용자 데이터를 오용하거나 시스템 자원에 무단으로 접근하는 것을 방지하기 위해 macOS Lion (10.7) 버전부터 App Sandbox를 도입했다. 특히, Mac App Store를 통해 배포되는 앱은 사용자 신뢰와 보안을 보장해야 했기 때문에 강제화되었다. 주요한 특징으로 격리실행(앱은 자신의 데이터와 권한 내에서만 작동하며, 다른 앱이나 시스템에 접근할 수 없음), 권한 기반 접근(파일, 네트워크, 하드웨어 리소스 등 필요한 권한만 명시적으로 요청), 보안강화(악성 코드 실행 및 데이터 탈취 방지) 을 가지고 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;h3&gt;&quot;오늘의 명언&quot; 프로그램 개선하기&lt;/h3&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;프로그램을 개선을 위하여 아래의 기능들을 추가로 정의하였다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;무료 버전의 Unsplash API&amp;nbsp; 호출은&amp;nbsp;&lt;span style=&quot;text-align: center;&quot;&gt;시간당 50개의 요청과 하루에 5,000개의 요청으로&amp;nbsp;&lt;/span&gt;제약이 있다. 이런 이유에서 이미지를 가져오지 못하는 경우 미리 가지고 있는 이미지를 랜덤으로 보여주는 기능이 구현.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음으로 단순하게 텍스트를 보여주는 것이 아니라 타이핑과 같은 효과 구현&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;외부에서 이미지를 가져오는 Unsplash API 을 호출하려면 키가 필요한데 소스에 코딩하여 사용하던 것을 입력할 수 있도록 프로그램 환경설정에 메뉴를 추가&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;우측 상단에 위치정보를 기반으로 테스트로 위치와 날씨 노출 구현&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Unsplash 의 경우 좌측 하단에 인스타그램과 같이 제작자 정보 노출 구현&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기능 구현을 위하여 아래와 같은 질문들을 했다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp;&lt;span style=&quot;text-align: center;&quot;&gt;Unsplash API 을 통하여 이미지를 가져오지 못할 때는 디폴트 이미지들을 랜덤으로 보여주게 하려면&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 Unsplash API를 통해 이미지를 가져오지 못할 때, 로컬에 저장된 기본 이미지를 랜덤으로 표시하는 기능을 추가할 수 있습니다. 이 기능을 구현하려면 이미지 로드 실패 시 로컬 이미지 배열에서 무작위로 선택하여 표시하는 로직을 작성하면 됩니다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp;&lt;/span&gt;fetchRandomLocalImage&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;() {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&amp;nbsp;imageNames = (&lt;span class=&quot;s3&quot; style=&quot;color: #1c00cf;&quot;&gt;1&lt;/span&gt;...&lt;span class=&quot;s3&quot; style=&quot;color: #1c00cf;&quot;&gt;8&lt;/span&gt;).&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;map&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;\($0)&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;&amp;nbsp;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&amp;nbsp;randomImageName = imageNames.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;randomElement&lt;/span&gt;(),&amp;nbsp;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&amp;nbsp;nsImage =&amp;nbsp;&lt;span class=&quot;s6&quot; style=&quot;color: #3900a0;&quot;&gt;NSImage&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;named&lt;/span&gt;: randomImageName)&amp;nbsp;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;&amp;nbsp;{&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Could not load local image.&quot;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #326d74;&quot;&gt;image&lt;/span&gt;&amp;nbsp;=&amp;nbsp;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;nil&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s7&quot; style=&quot;color: #326d74;&quot;&gt;isUnsplashImage&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp;=&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;false&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp;&lt;/span&gt;// Unsplash 이미지가 아님을 설정&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #326d74;&quot;&gt;image&lt;/span&gt;&amp;nbsp;= nsImage&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;s2&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;fetchRandomQuote&lt;span class=&quot;s1&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;}&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot; /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;제공되는 예제를 적용하여&amp;nbsp;&lt;/span&gt;Unsplash 에서 이미지를 가져오는 과정에서 오류가 발생하면 가지고 있는 이미지들 중에서 랜덤하게 하나의 이미지를 가져와 배경으로 보여주도록 기능을 추가하였다. 이미지는 AI 이미지 관련 웹 사이트에서 몇개를 다운로드하여 사용하였다. 로컬 이미지 추가는&amp;nbsp; Assets 에 새로운 폴더 &quot;Images&quot; 를 생성하고 이미지를 Drag&amp;amp;Drop 하여 이미지를 추가 하고 코딩시 이미지 목록을 자동화 하여 가져올 수 있도록 이름을 1, 2, 3, 4 형태로 변경하여 사용하였다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR_P8aNndSYdFafGQWfJPIzBr-fRTmI-EWNVIc85zlLMhxvcGEr8UUr9y8WasjFPNZUtuat0A_nIVg7R_IISVMQLVDHp10UzbPR5bS7kVHDOMzi3c1KIHE6iE-w7Jdnv5mQcf5sN7hxpKw0mLpOuFJsdaA5Id_RUcsd5WZ7lnLoHrWydUWntDHeXenb98U/s1494/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-08_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11_04_52.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;910&quot; data-original-width=&quot;1494&quot; height=&quot;390&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR_P8aNndSYdFafGQWfJPIzBr-fRTmI-EWNVIc85zlLMhxvcGEr8UUr9y8WasjFPNZUtuat0A_nIVg7R_IISVMQLVDHp10UzbPR5bS7kVHDOMzi3c1KIHE6iE-w7Jdnv5mQcf5sN7hxpKw0mLpOuFJsdaA5Id_RUcsd5WZ7lnLoHrWydUWntDHeXenb98U/w640-h390/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-08_%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB_11_04_52.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 명언 텍스트를 보여줄때 타이핑 효과를 주려면&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;SwiftUI에서 텍스트에 타이핑 효과를 주려면 애니메이션과 타이머를 조합하여 텍스트가 한 글자씩 나타나도록 구현할 수 있습니다. DispatchQueue와 타이머를 사용해 문자열의 각 문자를 일정 간격으로 추가하여 타이핑 애니메이션을 만들 수 있습니다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;제공되는 예제를 적용하여 문자를 티이핑하는 효과를 구현하는 기능의&amp;nbsp;&lt;/span&gt;TypewriterText&lt;span style=&quot;text-align: center;&quot;&gt;&amp;nbsp;구조체를&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;추가하였다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0b4f79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;TypewriterText&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;text&lt;/span&gt;: &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;onComplete&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: (() -&amp;gt; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)? = &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;nil&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;// 타입 효과 완료 시 호출되는 클로저&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@State&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;displayedText&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@State&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;currentIndex&lt;/span&gt;: &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Int&lt;/span&gt; = &lt;span class=&quot;s6&quot; style=&quot;color: #1c00cf;&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@State&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;typingTimer&lt;/span&gt;: &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Timer&lt;/span&gt;? = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;nil&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;typingSpeed&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #1c00cf;&quot;&gt;0.07&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;body&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;some&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;displayedText&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;onAppear&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;startTyping&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;onChange&lt;/span&gt;(&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;of&lt;/span&gt;: &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;text&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;resetTyping&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;startTyping&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #9b2393; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;private&lt;/b&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;b&gt;func&lt;/b&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;startTyping&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;() {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingTimer&lt;/span&gt;?.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;invalidate&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingTimer&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;nil&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;displayedText&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;currentIndex&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #1c00cf;&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p8&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingTimer&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Timer&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;scheduledTimer&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;withTimeInterval&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingSpeed&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;repeats&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;true&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) { timer &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;in&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;currentIndex&lt;/span&gt; &amp;lt; &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;text&lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;count&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; index = &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;text&lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;index&lt;/span&gt;(&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;text&lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;startIndex&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;offsetBy&lt;/span&gt;: &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;currentIndex&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;displayedText&lt;/span&gt;.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;append&lt;/span&gt;(&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;text&lt;/span&gt;[index])&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;currentIndex&lt;/span&gt; += &lt;span class=&quot;s6&quot; style=&quot;color: #1c00cf;&quot;&gt;1&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;timer.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;invalidate&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingTimer&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;nil&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;onComplete&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;?() &lt;/span&gt;// 타이핑이 완료되면 onComplete 클로저 호출&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #9b2393; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;private&lt;/b&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;b&gt;func&lt;/b&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;resetTyping&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;() {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingTimer&lt;/span&gt;?.&lt;span class=&quot;s7&quot; style=&quot;color: #6c36a9;&quot;&gt;invalidate&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;typingTimer&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;nil&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;displayedText&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;currentIndex&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #1c00cf;&quot;&gt;0&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;}&lt;/p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 프로그램 환경설정에 Unsplash API&amp;nbsp; 키를 설정할 수 있게 하려면&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;프로그램의 환경설정 창에서 API 키를 설정할 수 있도록 하려면 SwiftUI 앱에서는 Settings를 사용하여 시스템 메뉴의 기본 설정 창에 해당 UI를 추가할 수 있습니다. 이를 통해 Unsplash API Key를 설정할 수 있도록 합니다. &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;제공되는 예제를 적용하여 키를 설정하는 기능의&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;SettingsView 구조체를&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;추가하였다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; SwiftUI&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #0b4f79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;SettingsView&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@AppStorage&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;UnsplashAPIKey&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;unsplashApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&quot;&quot;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@AppStorage&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;OpenWeatherMapAPIKey&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;weatherApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&quot;&quot;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #3900a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;@AppStorage&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;OpenAIAPIKey&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;openAIAPIKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;String&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@State&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;showSaveConfirmation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;false&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;body&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;some&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;VStack&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;spacing&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;// API Key Table&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;VStack&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;spacing&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;15&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HStack&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Unsplash API Key&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;150&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;TextField&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Enter Unsplash API Key&quot;&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;text&lt;/span&gt;: &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;$unsplashApiKey&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;textFieldStyle&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedBorderTextFieldStyle&lt;/span&gt;())&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;300&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HStack&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;OpenWeatherMap API Key&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;150&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Enter OpenWeatherMap API Key&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;$weatherApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;textFieldStyle&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedBorderTextFieldStyle&lt;/span&gt;())&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;300&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HStack&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;OpenAI API Key&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;150&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;TextField&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Enter OpenAI API Key&quot;&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;text&lt;/span&gt;: &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;$openAIAPIKey&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;textFieldStyle&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedBorderTextFieldStyle&lt;/span&gt;())&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;300&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;horizontal&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;top&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;40&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Spacer&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px; text-align: start;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;// Save Button with Clear Background&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Button&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;action&lt;/span&gt;: {&lt;/p&gt;&lt;p class=&quot;p8&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;showSaveConfirmation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;true&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}) {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Save Changes&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;font&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;headline&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;foregroundColor&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;// Text color only, no background color&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;maxWidth&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;infinity&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;overlay&lt;/span&gt;(&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedRectangle&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;cornerRadius&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;8&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;stroke&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Color&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;blue&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;lineWidth&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;2&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;buttonStyle&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;PlainButtonStyle&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()) &lt;/span&gt;// Ensures the button has no additional background styling&lt;/p&gt;&lt;p class=&quot;p9&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;padding&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;([.&lt;/span&gt;leading&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, .&lt;/span&gt;trailing&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, .&lt;/span&gt;bottom&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;], &lt;/span&gt;&lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p8&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;isPresented&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;$showSaveConfirmation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Settings Saved&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Your API keys have been saved.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;dismissButton&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: .&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;OK&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)))&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;500&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;height&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;250&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; text-align: start;&quot;&gt;}&lt;/p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 사용자 위치정보를 기반으로 오늘의 날씨 정보와 위치 정보를 우측 상단 고정된 영역에 보려주려면&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 사용자의 위치 정보를 기반으로 날씨와 위치를 우측 상단에 고정하여 보여주는 방법을 구현할 수 있습니다. 아래 예제에서는 &lt;code&gt;LocationManager&lt;/code&gt;를 통해 사용자의 위치를 가져오고, OpenWeatherMap API를 사용하여 날씨 정보를 표시합니다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: start;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제공되는 예제를 적용하여 WeatherView 구조체를 추가하였다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0b4f79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;WeatherView&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@Binding&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;locationString&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;?&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;weatherInfo&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;body&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;some&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;VStack&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;alignment&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: .&lt;/span&gt;trailing&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;weatherInfo&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;font&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;subheadline&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;foregroundColor&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;white&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;background&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Color&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;black&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;opacity&lt;/span&gt;(&lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;0.4&lt;/span&gt;))&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;cornerRadius&lt;/span&gt;(&lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;8&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;trailing&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;top&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;40&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #3900a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #0b4f79;&quot;&gt;LocationManager&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;NSObject&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;ObservableObject&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;CLLocationManagerDelegate&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #3900a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;CLLocationManager&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #3900a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;@Published&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;userLocation&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;CLLocationCoordinate2D&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;?&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #3900a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;@Published&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;locationString&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;String&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;?&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #9b2393; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;b&gt;override&lt;/b&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;b&gt;init&lt;/b&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;() {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;super&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;init&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;manager&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;delegate&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;desiredAccuracy&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;kCLLocationAccuracyBest&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;requestLocation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;() {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;requestWhenInUseAuthorization&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;requestLocation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;locationManager&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;_&lt;/span&gt; manager: &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;CLLocationManager&lt;/span&gt;, &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;didUpdateLocations&lt;/span&gt; locations: [&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;CLLocation&lt;/span&gt;]) {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; location = locations.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;first&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;userLocation&lt;/span&gt; = location.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;coordinate&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #326d74;&quot;&gt;locationString&lt;/span&gt; = &lt;span class=&quot;s9&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Lat: &lt;/span&gt;\(location.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;coordinate&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;latitude&lt;/span&gt;)&lt;span class=&quot;s9&quot; style=&quot;color: #c41a16;&quot;&gt;, Lon: &lt;/span&gt;\(location.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;coordinate&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;longitude&lt;/span&gt;)&lt;span class=&quot;s9&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;locationManager&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; manager: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;CLLocationManager&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;didFailWithError&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; error: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;print&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s9&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Location error: &lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(error.&lt;/span&gt;localizedDescription&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s9&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;}&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 Unsplash API 에서 가져온 이미지를 보여줄 때는 인스타그램과 같이 이미지 이름과 작성자 그리고 프로필 이미지를 하단 좌측에 노출하게 하면&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 Unsplash API에서 이미지를 가져올 때, 이미지 정보와 작성자 이름, 작성자 프로필 사진 URL 등을 함께 받아와 화면에 표시할 수 있도록 코드를 수정할 수 있습니다. 아래는 해당 기능을 구현한 코드입니다. 이 코드는 이미지 하단 좌측에 Unsplash에서 가져온 이미지 이름과 작성자 정보를 표시합니다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제공되는 예제를 적용하여 코드를 수정하였다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;fetchImageFromUnsplash&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;() {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; !&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;unsplashApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; url = &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&quot;https://api.unsplash.com/photos/random?client_id=&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;unsplashApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Unsplash API Key is missing or invalid URL.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;fetchRandomLocalImage&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URLSession&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;shared&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;dataTask&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;with&lt;/span&gt;: url) { data, response, error &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;in&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;defer&lt;/b&gt;&lt;/span&gt; { &lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;isLoading&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;false&lt;/b&gt;&lt;/span&gt; }&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; error = error {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Error fetching image: &lt;/span&gt;\(error.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;localizedDescription&lt;/span&gt;)&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;fetchRandomLocalImage&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; data = data &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: No data received.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;fetchRandomLocalImage&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; json = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;JSONSerialization&lt;/span&gt;.jsonObject(with: data) &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;Any&lt;/b&gt;&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; urls = json[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;urls&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; imageUrlString = urls[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;regular&quot;&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; imageUrl = &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;string&lt;/span&gt;: imageUrlString),&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; user = json[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;user&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;Any&lt;/b&gt;&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; authorName = user[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;name&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;,&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; profileImageUrls = user[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;profile_image&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; profileImageUrlString = profileImageUrls[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;small&quot;&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; profileImageUrl = &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;string&lt;/span&gt;: profileImageUrlString),&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; description = json[&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;description&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;imageTitle&lt;/span&gt; = description&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;authorName&lt;/span&gt; = authorName&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;isUnsplashImage&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;true&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s7&quot; style=&quot;color: #5d6c79;&quot;&gt;// Unsplash 이미지임을 설정&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;downloadImage&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;from&lt;/span&gt;: imageUrl)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;downloadAuthorProfileImage&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;from&lt;/span&gt;: profileImageUrl)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Could not parse JSON.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;fetchRandomLocalImage&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;catch&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Error parsing JSON: &lt;/span&gt;\(error.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;localizedDescription&lt;/span&gt;)&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;fetchRandomLocalImage&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;resume&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s8&quot; style=&quot;color: #0f68a0;&quot;&gt;downloadImage&lt;/span&gt;(&lt;span class=&quot;s8&quot; style=&quot;color: #0f68a0;&quot;&gt;from&lt;/span&gt; url: &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URLSession&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;shared&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;dataTask&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;with&lt;/span&gt;: url) { data, response, error &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;in&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; data = data, &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; nsImage = &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;NSImage&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;data&lt;/span&gt;: data) &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; error = error {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Error downloading image: &lt;/span&gt;\(error.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;localizedDescription&lt;/span&gt;)&lt;span class=&quot;s6&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Unable to create image from data.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;fetchRandomLocalImage&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;image&lt;/span&gt; = nsImage&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;fetchRandomQuote&lt;/span&gt;() &lt;span class=&quot;s7&quot; style=&quot;color: #5d6c79;&quot;&gt;// 이미지가 로드된 후에 명언을 가져옴&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;resume&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;downloadAuthorProfileImage&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;from&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; url: &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;URLSession&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;shared&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;dataTask&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;with&lt;/span&gt;: url) { data, response, error &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;in&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; data = data, &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; nsImage = &lt;span class=&quot;s5&quot; style=&quot;color: #3900a0;&quot;&gt;NSImage&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;data&lt;/span&gt;: data) &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error downloading author profile image: &lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(error?.&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;localizedDescription&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; ?? &lt;/span&gt;&quot;Unknown error&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s3&quot; style=&quot;color: #326d74;&quot;&gt;authorProfileImage&lt;/span&gt; = nsImage&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;resume&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 로컬 이미지의 경우에는 작성자 정보를 보이지 않고 싶은데&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 로컬 이미지를 사용할 때는 작성자 정보가 표시되지 않도록 설정할 수 있습니다. 이를 위해, Unsplash에서 이미지를 가져온 경우에만 작성자 정보가 표시되도록 조건을 추가하면 됩니다. ContentView에서 Unsplash 이미지를 사용할 때만 작성자 정보를 보여주는 플래그를 추가하겠습니다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제공되는 예제를 적용하여 코드를 수정하였다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 명언이 영어로 제공되는데 chatgpt API 을 사용하여 한국어로 같이 표시하려면&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰&amp;nbsp;ChatGPT API를 사용하여 영어로 제공된 명언을 한국어로 번역하는 방법을 구현할 수 있습니다. 아래는 OpenAI의 ChatGPT API를 통해 영어 명언을 번역하여 한국어와 영어로 함께 표시하는 예제 코드입니다. 이 코드는 Swift에서 URLSession을 사용하여 ChatGPT API를 호출하고 번역 결과를 받아와 표시합니다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;제공되는 예제를 적용하여 코드를 수정하였다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;func&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;translateQuoteToKorean&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; quote: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; url = &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&quot;https://api.openai.com/v1/chat/completions&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Invalid URL for OpenAI API&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; request = &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;URLRequest&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;url&lt;/span&gt;: url)&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;request.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;httpMethod&lt;/span&gt; = &lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;POST&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;request.&lt;/span&gt;addValue&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Bearer &lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #326d74;&quot;&gt;openAIAPIKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;forHTTPHeaderField&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Authorization&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;request.&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;addValue&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;application/json&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;forHTTPHeaderField&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&quot;Content-Type&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; prompt = &lt;/span&gt;&quot;Translate this quote to Korean: &lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(quote)&lt;/span&gt;&quot;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; parameters: [&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;Any&lt;/b&gt;&lt;/span&gt;] = [&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&quot;model&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&quot;gpt-4o-mini&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;,&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;messages&quot;&lt;/span&gt;: [&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;[&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;role&quot;&lt;/span&gt;: &lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;user&quot;&lt;/span&gt;, &lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;content&quot;&lt;/span&gt;: prompt ]&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;max_tokens&quot;&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;60&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;]&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;request.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;httpBody&lt;/span&gt; = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;JSONSerialization&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;data&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;withJSONObject&lt;/span&gt;: parameters)&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;catch&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Failed to serialize JSON for request body - &lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(error)&lt;/span&gt;&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Sending request to ChatGPT API with prompt: &lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(prompt)&lt;/span&gt;&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;URLSession&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;shared&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;dataTask&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;with&lt;/span&gt;: request) { data, response, error &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;in&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; error = error {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Network request failed - &lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(error.&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;localizedDescription&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; httpResponse = response &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HTTPURLResponse&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Received HTTP response: &lt;/span&gt;\(httpResponse.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;statusCode&lt;/span&gt;)&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; httpResponse = response &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HTTPURLResponse&lt;/span&gt;, httpResponse.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;statusCode&lt;/span&gt; == &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;429&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Quota exceeded. Please check your API plan and usage.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;// 사용자에게 할당량 초과 메시지를 표시하는 로직 추가&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #5d6c79;&quot;&gt;//return&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;guard&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; data = data &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: No data received from ChatGPT API&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;return&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;do&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; json = &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;JSONSerialization&lt;/span&gt;.jsonObject(with: data) &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;Any&lt;/b&gt;&lt;/span&gt;] {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Received JSON response: &lt;/span&gt;\(json)&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; choices = json[&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;choices&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [[&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;Any&lt;/b&gt;&lt;/span&gt;]],&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; message = choices.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;first&lt;/span&gt;?[&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;message&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? [&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;String&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;Any&lt;/b&gt;&lt;/span&gt;],&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt; translatedText = message[&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;content&quot;&lt;/span&gt;] &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;as&lt;/b&gt;&lt;/span&gt;? &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;DispatchQueue.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;main&lt;/span&gt;.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;async&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;self&lt;/b&gt;&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #326d74;&quot;&gt;translatedQuote&lt;/span&gt; = translatedText.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;trimmingCharacters&lt;/span&gt;(&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;in&lt;/span&gt;: .&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;whitespacesAndNewlines&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Unexpected JSON structure or missing &#39;choices&#39; key&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;} &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;catch&lt;/b&gt;&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Error: Failed to parse JSON response - &lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;\(error)&lt;/span&gt;&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}.&lt;span class=&quot;s4&quot; style=&quot;color: #6c36a9;&quot;&gt;resume&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;추가로 앞선 SettingsView 구조체에 ChatGPT API 키 설정 코드를 추가하고 이 키값을 사용하도록 ContentView 를 수정하였다.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; SwiftUI&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p3&quot; style=&quot;background-color: white; color: #0b4f79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;SettingsView&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@AppStorage&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;UnsplashAPIKey&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;unsplashApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&quot;&quot;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@AppStorage&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;OpenWeatherMapAPIKey&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;weatherApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&quot;&quot;&lt;/p&gt;&lt;p class=&quot;p5&quot; style=&quot;background-color: white; color: #3900a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;@AppStorage&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;OpenAIAPIKey&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;openAIAPIKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;String&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p6&quot; style=&quot;background-color: white; color: #0f68a0; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;@State&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; &lt;/span&gt;showSaveConfirmation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;false&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;var&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s4&quot; style=&quot;color: #0f68a0;&quot;&gt;body&lt;/span&gt;: &lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;some&lt;/b&gt;&lt;/span&gt; &lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;View&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;VStack&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;spacing&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;// API Key Table&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;VStack&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;spacing&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;15&lt;/span&gt;) {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HStack&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Unsplash API Key&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;150&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;TextField&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Enter Unsplash API Key&quot;&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;text&lt;/span&gt;: &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;$unsplashApiKey&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;textFieldStyle&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedBorderTextFieldStyle&lt;/span&gt;())&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;300&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HStack&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;OpenWeatherMap API Key&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;150&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Enter OpenWeatherMap API Key&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;$weatherApiKey&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;textFieldStyle&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedBorderTextFieldStyle&lt;/span&gt;())&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;300&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;HStack&lt;/span&gt; {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;OpenAI API Key&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;150&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alignment&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;leading&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;TextField&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Enter OpenAI API Key&quot;&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;text&lt;/span&gt;: &lt;span class=&quot;s8&quot; style=&quot;color: #326d74;&quot;&gt;$openAIAPIKey&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;textFieldStyle&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedBorderTextFieldStyle&lt;/span&gt;())&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;300&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;horizontal&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;top&lt;/span&gt;, &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;40&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Spacer&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p2&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px; min-height: 14px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;// Save Button with Clear Background&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Button&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;action&lt;/span&gt;: {&lt;/p&gt;&lt;p class=&quot;p8&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;showSaveConfirmation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;s1&quot; style=&quot;color: #9b2393;&quot;&gt;&lt;b&gt;true&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}) {&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;(&lt;span class=&quot;s5&quot; style=&quot;color: #c41a16;&quot;&gt;&quot;Save Changes&quot;&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;font&lt;/span&gt;(.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;headline&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;foregroundColor&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) &lt;/span&gt;// Text color only, no background color&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;padding&lt;/span&gt;()&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;maxWidth&lt;/span&gt;: .&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;infinity&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;overlay&lt;/span&gt;(&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;RoundedRectangle&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;cornerRadius&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;8&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;stroke&lt;/span&gt;(&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Color&lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;blue&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;lineWidth&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;2&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p7&quot; style=&quot;background-color: white; color: #5d6c79; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;buttonStyle&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;PlainButtonStyle&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;()) &lt;/span&gt;// Ensures the button has no additional background styling&lt;/p&gt;&lt;p class=&quot;p9&quot; style=&quot;background-color: white; color: #6c36a9; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;padding&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;([.&lt;/span&gt;leading&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, .&lt;/span&gt;trailing&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;, .&lt;/span&gt;bottom&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;], &lt;/span&gt;&lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p8&quot; style=&quot;background-color: white; color: #326d74; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;isPresented&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;$showSaveConfirmation&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;) {&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p4&quot; style=&quot;background-color: white; color: #c41a16; font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Alert&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Settings Saved&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;Your API keys have been saved.&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;dismissButton&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;: .&lt;/span&gt;&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s3&quot; style=&quot;color: #3900a0;&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;(&lt;/span&gt;&quot;OK&quot;&lt;span class=&quot;s2&quot; color=&quot;rgba(0, 0, 0, 0.85)&quot;&gt;)))&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;.&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;frame&lt;/span&gt;(&lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;width&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;500&lt;/span&gt;, &lt;span class=&quot;s6&quot; style=&quot;color: #6c36a9;&quot;&gt;height&lt;/span&gt;: &lt;span class=&quot;s7&quot; style=&quot;color: #1c00cf;&quot;&gt;250&lt;/span&gt;)&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;}&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;background-color: white; color: rgba(0, 0, 0, 0.85); font-family: Menlo; font-feature-settings: normal; font-kerning: auto; font-optical-sizing: auto; font-size-adjust: none; font-size: 12px; font-stretch: normal; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; font-variation-settings: normal; line-height: normal; margin: 0px;&quot;&gt;}&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ChatGPT API 사용을 위해서는 Access Key 가 필요하다. Access Key 는 &lt;a href=&quot;https://platform.openai.com/&quot;&gt;OpenAI 홈페이지&lt;/a&gt;에서 계정을 생성하거나 기존 계정으로 로그인 후 &lt;a href=&quot;https://platform.openai.com/settings/organization/api-keys&quot;&gt;API 키 생성 페이지&lt;/a&gt; 로 이동 &lt;u&gt;&quot;Create new secret key&quot; &lt;/u&gt;버튼을 클릭하여 키를 생성할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijS-T32I7pMiN1d6XicyCObeHbwQF0aKIRj1c_sijzkq0U4-b1iZ0mp3FRal9vhEcR5yjySZHmFd6bYjvP6FP_yTbf1No9OL3Dbsz6-7kxWUxYpSg2dIfMUf8cE1C6sFzVcYdSg9ejkXCNJamhUIbzdr40ivhnaPuO7v0DpDvbxx8c5H3KtUMuIigxuIcC/s662/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-08_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_00_32.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;662&quot; data-original-width=&quot;568&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijS-T32I7pMiN1d6XicyCObeHbwQF0aKIRj1c_sijzkq0U4-b1iZ0mp3FRal9vhEcR5yjySZHmFd6bYjvP6FP_yTbf1No9OL3Dbsz6-7kxWUxYpSg2dIfMUf8cE1C6sFzVcYdSg9ejkXCNJamhUIbzdr40ivhnaPuO7v0DpDvbxx8c5H3KtUMuIigxuIcC/w344-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-08_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_00_32.jpg&quot; width=&quot;344&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;color: #0000ee;&quot;&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqxvYvj58h3frPP7NMldThjZdJ-J6M2o30ePF4BWflUyqhlQ6w-nVgBxY1-NfcpETjhwbf16pGEbcezXv3376JAcP3Ewixn_xaG0FfLv-FjOOgk0pXDAztp5E3PlfHavN53utKOuFWMCrxdbAI-uzpMFYbKP5df6MA7bxKReWTIli1ji9lj9fWc8K3dmf3/s1188/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.00.56.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;746&quot; data-original-width=&quot;1188&quot; height=&quot;251&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqxvYvj58h3frPP7NMldThjZdJ-J6M2o30ePF4BWflUyqhlQ6w-nVgBxY1-NfcpETjhwbf16pGEbcezXv3376JAcP3Ewixn_xaG0FfLv-FjOOgk0pXDAztp5E3PlfHavN53utKOuFWMCrxdbAI-uzpMFYbKP5df6MA7bxKReWTIli1ji9lj9fWc8K3dmf3/w400-h251/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-08%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.00.56.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4-Iaw3HtLUKu6PzzDwmrMbitFizgEla4Kw073xn4tnRpRmu2sgTQpGIKGBkgE0D5ZmizV-mWRaACnYcJzYJ4tukMmBqtSnfDPsSueUPw9e6GOPWGACO5-XyA-14-Wdg73xuYt5nCsdufOjpbBfJOJRDntdyw8OvTpaxRAEEcgOI9mkXevExdgEJ-3i_19/s1430/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-07%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.33.58.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1045&quot; data-original-width=&quot;1430&quot; height=&quot;468&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4-Iaw3HtLUKu6PzzDwmrMbitFizgEla4Kw073xn4tnRpRmu2sgTQpGIKGBkgE0D5ZmizV-mWRaACnYcJzYJ4tukMmBqtSnfDPsSueUPw9e6GOPWGACO5-XyA-14-Wdg73xuYt5nCsdufOjpbBfJOJRDntdyw8OvTpaxRAEEcgOI9mkXevExdgEJ-3i_19/w640-h468/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-11-07%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.33.58.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;전체 소스 :&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://github.com/andang72/andang72.unsplash &quot; target=&quot;_blank&quot;&gt;https://github.com/andang72/andang72.unsplash&amp;nbsp;&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;text-align: center;&quot;&gt;총평&lt;/span&gt;&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;기대 이상의 정확한 설명과 예제 코드는 인상적이다. 중간 중간 오류가 발생하기도 했지만 관련하여 문의하면 또 적절한 답변을 해주었다.&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;ChatGPT 와 대화 가운데 잘모르는 것은 바로 질문하여 확인할 수 있기 때문에 자연스럽게 학습이 되었다.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;충분한 맥 코딩 경험과 언어를 잘알고 있다면 전문가수준의 코드 작성도 충분하게 가능할것 같다는 느낌이다.&lt;/div&gt;&lt;div style=&quot;text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3&gt;&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/4744271626799655702/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/11/chatgpt.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/4744271626799655702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/4744271626799655702'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/11/chatgpt.html' title='코딩 - ChatGPT 을 이용한 맥 프로그램 만들기(오늘의 명언)'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieN_uhZ8qyPPWVHYsMQuY-TkdQkKCB5DcpG-4QtjZOBg2c1J4XeOJlXwf3nZHaLxHGl2HZeXXvLvugLVasijsL3YYbgo7fROad2rVRtg-jg8jgaF5AJCc9-ND21JCTGTSi21_lgQvtNNqK6oTEZY-K175U9zYVKe5EBCX_InXOiJf7Or9ajrKOenPexUAF/s72-w640-h402-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-11-06_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_16_23.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-1546613185417885915</id><published>2024-10-29T17:47:00.006+09:00</published><updated>2024-10-29T17:47:59.382+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ag-grid"/><category scheme="http://www.blogger.com/atom/ns#" term="Vue3"/><category scheme="http://www.blogger.com/atom/ns#" term="vuetify3"/><title type='text'>코딩 - Vue3 : AG-Grid 커뮤니티 버전 기반의 페이징 그리드 컴포넌트 만들기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;AG&amp;nbsp;Grid&amp;nbsp;&lt;span color=&quot;var(--color-fg-primary)&quot; face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, &amp;quot;Noto Sans&amp;quot;, &amp;quot;Liberation Sans&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;&quot; style=&quot;background-color: white; font-size: var(--text-fs-xl); font-weight: var(--text-bold);&quot;&gt;Community&amp;nbsp;&lt;/span&gt;버전은 매우 인기 있는 오픈소스 그리드 컴포넌트로, 다양한 기능을 제공하지만 상업적인 용도로 사용할 때는 프로 버전으로의 업그레이드가 필요할 수도 있다. 커뮤니티 버전의 이점과 한계를 살펴보면 다음과 같다.&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-weight: normal;&quot;&gt;AG&amp;nbsp;Grid&amp;nbsp;&lt;span color=&quot;var(--color-fg-primary)&quot; face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, &amp;quot;Noto Sans&amp;quot;, &amp;quot;Liberation Sans&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;&quot; style=&quot;background-color: white; font-size: var(--text-fs-xl);&quot;&gt;Community&amp;nbsp;&lt;/span&gt;&amp;nbsp;버전의 이점&lt;/span&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;무료 사용: 커뮤니티 버전은 오픈소스로 제공되므로 무료로 사용할 수 있다. 중소규모의 프로젝트나 상업적 용도가 아닌 경우에 적합.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;강력한 성능:&amp;nbsp; AG&amp;nbsp;Grid 는 많은 양의 데이터를 효율적으로 처리할 수 있는 그리드 컴포넌트로 기본적인 CRUD 작업을 포함하여 빠른 렌더링 성능을 지원.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;광범위한 기능:&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기본적인 정렬, 필터링, 페이징, 그룹핑, 편집 등 그리드에서 필요한 대부분의 기능을 포함&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다양한 컬럼 레이아웃과 사용자 정의 셀 렌더러 등 유연한 데이터 표현이 지원&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;활발한 커뮤니티: AG&amp;nbsp;Grid는 대규모 사용자 커뮤니티를 보유하고 있어 문제 발생 시 도움을 얻기 용의.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다양한 프레임워크 지원: React, Angular, Vue, 순수 자바스크립트 등 여러 프레임워크에서 사용할 수 있는 유연함&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;AG&amp;nbsp;Grid&amp;nbsp;&lt;/span&gt;&lt;span color=&quot;var(--color-fg-primary)&quot; face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, &amp;quot;Noto Sans&amp;quot;, &amp;quot;Liberation Sans&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;&quot; style=&quot;background-color: white; font-size: var(--text-fs-xl); font-weight: normal;&quot;&gt;Community&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;&amp;nbsp;버전의 한계&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;고급 기능 제한: 커뮤니티 버전에는 고급 기능이 포함되어 있지 않음. 특히 아래 기능들이 프로 버전에만 포함.&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;u&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버 사이드 모델(Server-Side Model): 대규모 데이터 집합에서 서버와 연동하여 그리드 데이터를 관리하는 기능.&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;익스포트 기능: CSV, Excel 등의 형식으로 데이터를 내보내는 기능이 제한.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Tree Data 구조: 트리 구조의 데이터를 처리할 수 있는 고급 데이터 표현 방식 미지원.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;엔터프라이즈 레벨 필터링: 고급 필터링 기능은 프로 버전에만 포함.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기술 지원 부족: 커뮤니티 버전에서는 공식적인 기술 지원을 받을 수 없음. 문제 해결 시 커뮤니티에 의존해야 함.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;사용 제한: 상업적 프로젝트에서 고급 기능이 필요하거나 성능 최적화 및 유지보수가 중요한 경우, 커뮤니티 버전만으로는 한계가 있을 수 있음.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;AG&amp;nbsp;Grid&amp;nbsp;&lt;/span&gt;&lt;span color=&quot;var(--color-fg-primary)&quot; face=&quot;-apple-system, &amp;quot;system-ui&amp;quot;, &amp;quot;Segoe UI&amp;quot;, Roboto, &amp;quot;Helvetica Neue&amp;quot;, Arial, &amp;quot;Noto Sans&amp;quot;, &amp;quot;Liberation Sans&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;&quot; style=&quot;background-color: white; font-size: var(--text-fs-xl); font-weight: normal;&quot;&gt;Community&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-weight: normal;&quot;&gt;버전은 무료로 사용할 수 있고, 기본적인 그리드 기능을 모두 제공하기 때문에 많은 프로젝트에서 유용하다. 그러나 고급 기능이나 대규모 데이터 처리가 필요한 경우 프로 버전으로 업그레이드하는 것이 필요하다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic; font-weight: normal;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;유료 버전에서는 rowModelType을 &quot;serverSide&quot; 로 설정하고 그리드가 준비되면 getRows 함수 내에서 서버 요청을 수행하고 결과를 그리드에 전달하는 데이터소스를 api.setServerSideDatasource() 함수를 사용하여 설정하는 방식으로 쉽게 구현할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AG Grid 커뮤니티 버전에서 서버 페이징은 (무한 스크롤을 구현하는 방법) rowModelType 값으로&amp;nbsp;&amp;nbsp;&quot;infinite&quot; 을 사용하여 비슷한 방법으로 구현할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;rowModelType을 &quot;infinite&quot;로 설정하여 그리드가 데이터를 한 번에 모두 로드하지 않고, 필요한 만큼 서버에서 요청하도록 한다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;getRows 함수는 그리드가 추가 데이터를 요청할 때마다 서버에 데이터를 가져오는 역할을 한다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;dataSource는그리드가 준비될 때 설정하고, 그리드가 데이터를 필요로 할 때마다 자동으로 서버에 데이터를 요청한다. ( 그리드 준비 여부는 onGridReady 이벤트를 사용)&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;개발 단계를 구체적으로 설명하면 아래와 같다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
  
&lt;style&gt;
  table.mt { /* .mt 클래스가 있는 table에만 적용 */
    width: 100%;
    border-collapse: collapse;
  }
  table.mt, table.mt th, table.mt td { /* .mt 클래스가 있는 table의 th, td에만 적용 */
    border: 1px solid black;
  }
  table.mt th {
    background-color: #4CAF50; /* 헤더 배경 색상 */
    color: white; /* 헤더 글자 색상 */
    padding: 4px;
    text-align: left;
  }
  table.mt td {
    padding: 4px;
    text-align: left;
  }
&lt;/style&gt; 
  &lt;table class=&quot;mt&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th width=&quot;30&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;단&lt;span&gt;계&lt;/span&gt;&lt;/span&gt;&lt;/th&gt;
      &lt;th&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명&lt;/span&gt;&lt;/th&gt;
      &lt;th&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;코드 예시&lt;/span&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;프로젝트에 AG Grid 설치&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;npm install --save ag-grid-community ag-grid-vue&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;컬럼 정의 및 그리드 옵션 설정&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;columnDefs&lt;/code&gt;와 &lt;code&gt;gridOptions&lt;/code&gt;를 &lt;code&gt;&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;&lt;/code&gt;에서 정의하고 &lt;code&gt;ref&lt;/code&gt;로 선언&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;3&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Infinite Row Model 활성화&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;gridOptions&lt;/code&gt;에서 &lt;code&gt;rowModelType&lt;/code&gt;을 &lt;code&gt;&#39;infinite&#39;&lt;/code&gt;로 설정하고, &lt;code&gt;paginationPageSize&lt;/code&gt; 및 &lt;code&gt;cacheBlockSize&lt;/code&gt;를 정의&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;4&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;onGridReady 함수에서 서버 데이터 소스 설정&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;onGridReady&lt;/code&gt;에서 &lt;code&gt;getRows&lt;/code&gt; 함수가 포함된 &lt;code&gt;dataSource&lt;/code&gt;를 설정&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;5&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;getRows 함수에서 서버 데이터 요청&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;params.startRow&lt;/code&gt;, &lt;code&gt;params.endRow&lt;/code&gt;를 기반으로 페이지와 페이지 크기를 서버에 요청&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;6&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버 응답 처리&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버의 데이터 응답을 받아 &lt;code&gt;params.successCallback(data.rows, data.totalCount)&lt;/code&gt;을 호출하여 그리드에 전달&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;7&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vue 컴포넌트 마운트 시 그리드 참조 설정&lt;/span&gt;&lt;/td&gt;
      &lt;td&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;onMounted&lt;/code&gt;에서 &lt;code&gt;gridRef&lt;/code&gt;를 통해 그리드 API에 접근하여 초기 설정 완료&lt;/span&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

  
  &lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://andang72.blogspot.com/2024/07/vue3-spring-ag-grid.html&quot; target=&quot;_blank&quot;&gt;코딩 - Vue3 &amp;amp; Spring : AG-Grid 페이징, 필터 구현하기&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;매번 서버 페이징이 필요한 경우 위와 같이 코딩하는 것은 여간 불편한 것이 아니다. 이런 이유에서 추상 형태의 DataSource 을 정의하고 공통으로 적용할 설정을 미리 정의하고 필요한 값만 전달하여 페이징 그리드를 구현하는 컴포넌트를 만들어 보았다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/donghyuck/9b0bacc700f708d1412de288d89e948e.js&quot;&gt;&lt;/script&gt;

&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;아래는 PageableGridContent.vue 에서 사용하는 서버에서 데이터를 가져오는 PageableDataSource 에 대한 추상 AbstractPageDataSource 이다. 이를 통하여 좀더 쉽게 서버에서 데이터를 가져오는 데이터소스 구현을 가능하게 한다. ( 구현체에서는 규칙을 벗어 나지 않는 경우라면 서버 엔트포인트 값을 리턴하는 getPatchUrl () 만 구현하면 된다. 서버 프로그램은 스프링의 Pageable&amp;nbsp; 형식으로 데이터를 리턴하는 것을 가정 하여 데이터소스 추상을 구현 했다.&lt;/span&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/donghyuck/2ba16f3e01593651611630dde7e89fc6.js&quot;&gt;&lt;/script&gt;&lt;span style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;/span&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
위의 컴포넌트를 사용하여 1) 컴포넌트 임포트 2)&amp;nbsp; 그리드 컬럼 정의 3) 태그를 사용하여 컴포넌트를 정의하는 것으로 그리드를 간단하게 구현 할 수 있다. 또한 컴포넌트에 직접 제어가능한 함수를 사용하여 새로고침, 선택된 데이터 접근, 필터 초기화 등을 제어할 수 있다. 그리드 컬럼에서 단수 데이터 출력이 아닌 버튼과 또는 이미지 출력 등의 작업이 필요한 경우는 사용자 정의  더러를 정의하고 버튼 클릭등의 이벤트는 이벤트 리스트너를 통하여 구현하였다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;script src=&quot;https://gist.github.com/donghyuck/d5f8ef313e1ff636f4092a2fbdcf6b34.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음은 위의 AbstractPageDataSource&amp;nbsp;활용하여 구현한 예이다. 아래는 목록을 조회하는 기능과 추가로 여러 함수를 포함하고 있다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;구현 클래스는 추가 기능이 필요하면 PageableDataSource 을 포함하여 새로운 타입을 정의하고 이를 구현하는 클래스를 Abstract&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;PageableDataSource 상속하여&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;만든다. 구현 클래스는 getFetchUrl 함수를 구현하는 것으로 완성되며 this 이슈를 해결하기 위하여 반인딩을 사용하여 스토어를 생성하게 한다.&lt;/span&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;필요한 새로운 PageableDataSource 을 포함하는 type 생성&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;getFetchUrl 을 포함 새로운 type 을 구현하는 클래스 생성&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;구현 클래스를 사용하여 스토어 생성&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;RoleModel&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;@/types/studio/RoleModel&quot;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;API_HEADERS&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;authHeader&lt;/span&gt;&lt;/div&gt;&lt;div&gt;} &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;@/util/helpers&quot;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;axios&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;axios&quot;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;defineStore&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;pinia&quot;&lt;/span&gt;;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;type&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;PageableDataSource&lt;/span&gt;&lt;/div&gt;&lt;div&gt;} &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;@/types/studio/index&quot;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;AbstractPageDataSource&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;../AbstractPageDataSource&quot;&lt;/span&gt;;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;// getById,getByName,loadById,saveOrUpdate 추가을 추가하여 IPageableRoleDataSource를 정의&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;type&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;IPageableRoleDataSource&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;PageableDataSource&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;amp;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getById&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getByName&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;string&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;loadById&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Promise&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;&amp;gt;;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveOrUpdate&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Promise&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;void&lt;/span&gt;&amp;gt;;&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;baseUrl&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/roles:find`&lt;/span&gt;;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;PageableRoleDataSource&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;extends&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;AbstractPageDataSource&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;implements&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;IPageableRoleDataSource&lt;/span&gt;&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getById&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;find&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;      (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;===&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    );&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;br /&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getByName&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;string&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;find&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;===&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;br /&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;loadById&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;API_HEADERS&lt;/span&gt;, &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;() };&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;axios&lt;/span&gt;&lt;/div&gt;&lt;div&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;get&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/roles/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;        { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; }&lt;/div&gt;&lt;div&gt;      )&lt;/div&gt;&lt;div&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;      })&lt;/div&gt;&lt;div&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;alertStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;      });&lt;/div&gt;&lt;br /&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;category&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;br /&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveOrUpdate&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RoleModel&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;API_HEADERS&lt;/span&gt;, &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;() };&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;axios&lt;/span&gt;&lt;/div&gt;&lt;div&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;post&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/roles/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;roleId&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;JSON&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;stringify&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;        { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; }&lt;/div&gt;&lt;div&gt;      )&lt;/div&gt;&lt;div&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;      })&lt;/div&gt;&lt;div&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;this&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;alertStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;      });&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;br /&gt;&lt;div&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// API 엔드포인트 URL을 제공. 이 클래스만 구현하면 그리드는 정상 동작한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getFetchUrl&lt;/span&gt;()&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;string&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;baseUrl&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/div&gt;// 필수로 표기된 부분은 반드시 동일하게 리턴해야 한다.  &lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;usePageableRolesStore&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;defineStore&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;mgmt-pageable-roles-store&quot;&lt;/span&gt;, () &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;PageableRoleDataSource&lt;/span&gt;();&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; {      &lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;isLoaded&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;isLoaded&lt;/span&gt;, // 필수&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;dataItems&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;dataItems&lt;/span&gt;, // 필수&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;total&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;total&lt;/span&gt;, // 필수   &lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;pageSize&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;pageSize&lt;/span&gt;,// 필수&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getById&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getById&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getByName&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getByName&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;loadById&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;loadById&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveOrUpdate&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveOrUpdate&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setPage&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setPage&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),// 필수&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setSort&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setSort&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),// 필수&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setFilter&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setFilter&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;),// 필수&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;fetch&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;fetch&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bind&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;), // 필수&lt;/div&gt;&lt;div&gt;  };&lt;/div&gt;&lt;div&gt;});&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;예제 프로그램 실행 화면은 아래와 같다.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvtJahmepgJWu-JKwfmlhT4qFzkp5JgeI3FQbbJwZ77JoU_s3yPPgH1U8y86YP20Wa6Gpn3kzyYs2hlE6ZnaJDZVEmMIuGfG6qwJQxCGa9JrBz_kcsyl8uRvOLdMxiNV3rwLgB4Acd2VOZXjEmtVf5EP64OdELYstGjFHqNb1BQfwEn9zkozJFoFpx028a/s2400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-29_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_13_04.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1506&quot; data-original-width=&quot;2400&quot; height=&quot;402&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvtJahmepgJWu-JKwfmlhT4qFzkp5JgeI3FQbbJwZ77JoU_s3yPPgH1U8y86YP20Wa6Gpn3kzyYs2hlE6ZnaJDZVEmMIuGfG6qwJQxCGa9JrBz_kcsyl8uRvOLdMxiNV3rwLgB4Acd2VOZXjEmtVf5EP64OdELYstGjFHqNb1BQfwEn9zkozJFoFpx028a/w640-h402/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-29_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_13_04.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/1546613185417885915/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/10/vue3-ag-grid.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1546613185417885915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1546613185417885915'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/10/vue3-ag-grid.html' title='코딩 - Vue3 : AG-Grid 커뮤니티 버전 기반의 페이징 그리드 컴포넌트 만들기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvtJahmepgJWu-JKwfmlhT4qFzkp5JgeI3FQbbJwZ77JoU_s3yPPgH1U8y86YP20Wa6Gpn3kzyYs2hlE6ZnaJDZVEmMIuGfG6qwJQxCGa9JrBz_kcsyl8uRvOLdMxiNV3rwLgB4Acd2VOZXjEmtVf5EP64OdELYstGjFHqNb1BQfwEn9zkozJFoFpx028a/s72-w640-h402-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-29_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_4_13_04.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-218478197710390734</id><published>2024-10-26T20:04:00.008+09:00</published><updated>2024-10-31T13:20:08.508+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AES"/><category scheme="http://www.blogger.com/atom/ns#" term="CryptoJS"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Javascript"/><category scheme="http://www.blogger.com/atom/ns#" term="RSA"/><category scheme="http://www.blogger.com/atom/ns#" term="암호화"/><category scheme="http://www.blogger.com/atom/ns#" term="하이브리드 암호화"/><title type='text'>코딩 - 자바스크립트 CryptoJS 와 JAVA 간의 하이브리드 암호화 (RSA+AES)</title><content type='html'>&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클라이언트와 서버간의 안전한 통신을 위하여 간단하게 암호화를 만들어보았다. 작업 환경은 아래와 같다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;background-color: white; color: #333333; font-size: 14.85px;&quot;&gt;◼︎&amp;nbsp;&lt;/span&gt;환경&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;HW : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 15.0.1 (24A348)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : Visual Studio Code, Java 11&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Java, HTML, JavaScript&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;개인적으로 데이터 암호화는 AES (Advanced Encryption Standard) 알고리즘을 사용한다. AES는 대칭키 알고리즘 중 하나로, 데이터 암호화와 복호화에 동일한 키를 사용한다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AES 키: 대칭키 암호화에서 데이터를 암호화하고 복호화하는데 사용되는 비밀 키. AES 키는 128, 192, 또는 256비트로 설정될 수 있다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV (Initialization Vector): AES-CBC 모드에서 사용되는 추가 보안 요소. IV는 암호화할 때마다 무작위로 생성되고, 암호화된 데이터와 함께 전송됩다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Base64 인코딩: AES 키와 IV는 바이너리 데이터이므로, 이를 텍스트 형식으로 저장하고 전송하기 위해 Base64로 인코딩한다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버/클라이언트 환경을 고려하면 대칭키 방식의 암호화/복호화는 서버와 클라이언트 모두가 AES 키 와 IV 값을 미리 알고 있어야 한다.&amp;nbsp; 키 관리의 위험성을 고려하면&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;암호화 키를 서버와 클라이언트가 공유 하는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;대칭키 방식 보다는 비대칭키를 사용하는 것이 더 키 관리에 안전하다고 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;대칭키와 비대칭키 암호화의 장점과 단점은 아래와 같다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;대칭키 암호화 (Symmetric Encryption)&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;① 특징:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;암호화와 복호화에 같은 키를 사용.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AES(Advanced Encryption Standard)와 같은 알고리즘이 대칭키 암호화에 해당.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;② 장점:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;빠른 속도: 대칭키 암호화는 비대칭키보다 훨씬 빠름. 특히 대량의 데이터를 암호화할 때 성능이 우수함.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;간단한 구현: 동일한 키로 암호화와 복호화를 수행하기 때문에 상대적으로 간단하게 구현할 수 있음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;③ 단점:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 관리 문제: 대칭키를 안전하게 공유하는 것이 문제. 만약 네트워크를 통해 키를 전송해야 한다면, 키가 중간에서 가로채기당할 위험이 있음.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보안성 문제: 키가 노출되면 데이터를 보호할 방법이 없음. 키 교환이 안전하지 않다면, 대칭키 암호화는 취약할 수 있음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;비대칭키 암호화 (Asymmetric Encryption)&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;① 특징:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;암호화에는 공개키를, 복호화에는 개인키를 사용.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;RSA(Rivest-Shamir-Adleman)와 같은 알고리즘이 비대칭키 암호화에 해당.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;②&amp;nbsp;장점:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보안성: 비대칭키 암호화는 공개키를 사용해 암호화하므로 키 교환이 안전. 공개키는 누구나 사용할 수 있지만, 개인키는 소유자만이 알고 있기 때문에 보안성이 뛰어남.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 관리 용이: 공개키는 네트워크를 통해 쉽게 공유할 수 있고, 개인키는 비밀로 유지되므로 키 교환이 안전하게 구현됨.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;③&amp;nbsp;단점:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;속도 문제: 비대칭키 암호화는 대칭키 암호화에 비해 훨씬 느림. 특히 대량의 데이터를 암호화하는 데 비효율적임.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;데이터 크기 제한: RSA와 같은 비대칭키 알고리즘은 암호화할 수 있는 데이터의 크기가 키 길이에 의해 제한됨.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;   이들 암호화 방식의 특성을 고려하면 서버/클라이언트 환경에서는&amp;nbsp;&amp;nbsp;TLS/SSL 프로토콜(HTTPS) 등에서 널리 사용되는&amp;nbsp;&lt;u&gt;비대칭키와 대칭키를 결합한 하이브리드 암호화 방식&lt;/u&gt;이 가장 안전하고 효율적이라고 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참고로 아래는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;TLS/SSL 프로토콜(HTTPS)&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;을 쉽게 설명하는 이미지 이다. (출처&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;a href=&quot;https://has3ong.github.io/computer%20science/ssl-tls/&quot;&gt;https://has3ong.github.io/computer%20science/ssl-tls/&lt;/a&gt;&amp;nbsp;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://user-images.githubusercontent.com/44635266/68072865-ccf14e00-fdcd-11e9-919e-4d4f4ad4ddbf.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1604&quot; data-original-width=&quot;1176&quot; height=&quot;640&quot; src=&quot;https://user-images.githubusercontent.com/44635266/68072865-ccf14e00-fdcd-11e9-919e-4d4f4ad4ddbf.png&quot; width=&quot;469&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;클라이언트/서버간의 안전한 데이터 암호화를 위한 하이브리드 방식은 아래와 같은 절차를 따른다.&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버는 클라이언트(웹) 에게 RSA 공개키를 배포&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클라이언트는 랜덤 생성된 AES 키를 사용하여 데이터를 암호화&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;RSA 공개키로 AES 키를 암호화 하고 암호화된 데이터와 IV 값을 함께 서버에 전달&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버는 RSA 개인키로 암호화된 AES 키를 복호화하고 함께 전달된 IV 값을 사용하여 데이터를 복호화&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj82GBupBGPfT8FmVR_rmeimeK2WFtaF-pDNzbEN5M6ab_efGetnJykcTmBnUKj9PhjQo2fKOR4FflNKUZi9EKgiClUkp3MV1DzsgtA0BS6RPlz85djvsp6r4xZI9pHGN5aSMrxjb15JMhlVcl3jiAxmtF7JMoxCEHTPWJBI_Lx1Z4xuLq9-b-31T3gf-BM/s1024/948bca1f-0d08-4874-9e7c-54ea44770cf9.webp&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1024&quot; data-original-width=&quot;1024&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj82GBupBGPfT8FmVR_rmeimeK2WFtaF-pDNzbEN5M6ab_efGetnJykcTmBnUKj9PhjQo2fKOR4FflNKUZi9EKgiClUkp3MV1DzsgtA0BS6RPlz85djvsp6r4xZI9pHGN5aSMrxjb15JMhlVcl3jiAxmtF7JMoxCEHTPWJBI_Lx1Z4xuLq9-b-31T3gf-BM/w640-h640/948bca1f-0d08-4874-9e7c-54ea44770cf9.webp&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;하이브리드 방식의 암호화 방식을 적용하면 적은 노력으로 손쉽게 클라이언트와 서버간의 암호화 통신을 구현할 수 있다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;하이브리드 방식 암호화&amp;nbsp;구현에 있어 클라이언트에서 ❶ AES 암호화는 &lt;a href=&quot;JavaScript library of crypto standards&quot;&gt;CryptoJS&lt;/a&gt; (JavaScript library of crypto standards) 을 사용하였고 ❷ RSA 암호화는 웹 암호화 API 의 일부로 제공되는 crypto.subtle 을 사용하였다. 주의 할 점은 crypto.subtle API는모든 브라우저에서 지원하지 않으며, 특히 일부 구형 브라우저나 특정 모바일 브라우저에서는 지원되지 않을 수 있다. 서버의 경우 기본 자바의 암호화 기능을 사용하였다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://caniuse.com/cryptography&quot; target=&quot;_blank&quot;&gt;Can I Use - Web Cryptography API&lt;/a&gt;&amp;nbsp;사이트를 통하여 호환성을 확인해 볼 수 있다. 이 사이트에 따르면 대부분의 웹 브라우저에서 지원된다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;하이브리드 방식 암호화 구현하기&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버는 AES 암호화를 위한 대칭키를 암호화기 위하여 먼저 RSA 비대칭키&amp;nbsp; 생성한다&lt;/span&gt;.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;


&lt;script src=&quot;https://gist.github.com/donghyuck/534bad3e5ffae492e8ed514617e45ac5.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;비밀키는 안전하게 보관하고 공개키는 클라이언트에 전달한다. 클라이언트는 AES 키를 생성하여 데이터를 암호화하고 AES 키는 서버가 공개한 RAS 공개키로 암호화를 한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/donghyuck/e21a072dc92276f0416c8ec573b76287.js&quot;&gt;&lt;/script&gt;

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ1QXCup7TBk9nh0gUsKU0PC22vjzDg1_CLBb6byGI_CEWVvxgIUPdWsKAquaTpp9Hn07Uu2hPi4g5bVAlSp_-9ouRrlLl8yWML-RFYAiWpRQxV3Bc0T6FteZwWxVjgDj9g2xhg_E0CinP7LtBjSt6Q1obAT7K8whTcXsBZG9syX2baDmu6G1TE5hIMeuD/s718/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-10-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.39.12.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;705&quot; data-original-width=&quot;718&quot; height=&quot;393&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ1QXCup7TBk9nh0gUsKU0PC22vjzDg1_CLBb6byGI_CEWVvxgIUPdWsKAquaTpp9Hn07Uu2hPi4g5bVAlSp_-9ouRrlLl8yWML-RFYAiWpRQxV3Bc0T6FteZwWxVjgDj9g2xhg_E0CinP7LtBjSt6Q1obAT7K8whTcXsBZG9syX2baDmu6G1TE5hIMeuD/w400-h393/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-10-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.39.12.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;E&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ncrypt Data 버튼을 클릭하여 데이터를 암호화 한다.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWQ6OXCN5zf-wtu72grurYbSYkHchgnN7gX7z4XDMFaLqj7NEFl7BOIFJZT1rIPqoukwqduG8_pFy2hdmbZfFF_54ZVA8aiUTtsV_5uU9VlSxg0kfaEZQge5_Le1_fZm7XMcHPmEW7tdprR8UJlpPnejYbVZr6XmM5gxGvu_z97hAdYAEDHFGstg9c5wck/s701/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-26_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_7_39_26.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;701&quot; data-original-width=&quot;601&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWQ6OXCN5zf-wtu72grurYbSYkHchgnN7gX7z4XDMFaLqj7NEFl7BOIFJZT1rIPqoukwqduG8_pFy2hdmbZfFF_54ZVA8aiUTtsV_5uU9VlSxg0kfaEZQge5_Le1_fZm7XMcHPmEW7tdprR8UJlpPnejYbVZr6XmM5gxGvu_z97hAdYAEDHFGstg9c5wck/w548-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-26_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_7_39_26.jpg&quot; width=&quot;548&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이제 공개키로 암호화된 AES 키 값, AES 로 암호화된 데이터와 IV 값을 서버에 전달한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;공개키로 암호화된 AES 키 : BASE64로 인코딩&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV : BASE64로 인코딩&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AES 로 암호화된 데이터 : BASE64로 인코딩&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버는 비밀키로 암호화된 대칭키 값을 복호화하고 키를 사용하여 암호화된 데이터를 복호화 한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
  
 &lt;script src=&quot;https://gist.github.com/donghyuck/243c4e067d56369669263c83e9c41983.js&quot;&gt;&lt;/script&gt;
  
  
  &lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참고자료&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ChatGPT 4o : 코드는 ChatGPT 4o 을 사용하여 작성.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/218478197710390734/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/10/cryptojs-java-rsaaes.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/218478197710390734'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/218478197710390734'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/10/cryptojs-java-rsaaes.html' title='코딩 - 자바스크립트 CryptoJS 와 JAVA 간의 하이브리드 암호화 (RSA+AES)'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj82GBupBGPfT8FmVR_rmeimeK2WFtaF-pDNzbEN5M6ab_efGetnJykcTmBnUKj9PhjQo2fKOR4FflNKUZi9EKgiClUkp3MV1DzsgtA0BS6RPlz85djvsp6r4xZI9pHGN5aSMrxjb15JMhlVcl3jiAxmtF7JMoxCEHTPWJBI_Lx1Z4xuLq9-b-31T3gf-BM/s72-w640-h640-c/948bca1f-0d08-4874-9e7c-54ea44770cf9.webp" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-9043504548464169935</id><published>2024-10-02T13:54:00.001+09:00</published><updated>2024-10-04T22:39:39.566+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bouncy castle"/><category scheme="http://www.blogger.com/atom/ns#" term="jasypt"/><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="spring boot"/><category scheme="http://www.blogger.com/atom/ns#" term="암호화"/><title type='text'>코딩 - Spring Boot 환경에서 설정 정보 암호화</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;&quot;Config Server 을 구성할 필요가 없는 경우 주요한 설정을 어떻게 암호화를 할 것인가&quot;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Spring Boot 에서 Config Server를 사용하지 않고도 암호화를 적용하는 방법은 여러 가지가 있다. 특히, 민감한 데이터를 보호하기 위해 Jasypt&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;와 같은 라이브러리를 사용하여 암호화를 적용, 애플리케이션의 설정 파일이나 환경 변수에 저장된 비밀번호, API 키 등의 민감한 정보를 안전하게 암호화할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;background-color: white; color: #333333; font-size: 14.85px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;◼︎ 환경&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;background-color: white; color: #333333; font-size: 14.85px; line-height: 1.4; list-style-image: initial; list-style-position: initial; margin: 0.5em 0px; padding: 0px 2.5em;&quot;&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 13.2.4 (22F66)&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : Visual Studio Code, Java 11, Gradle, Docker&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version Control : GitHub&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Java&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Back-End Framework : Spring Boot 2.7.12, Spring Security 5.7.7&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DBMS : MySql 8.0.33&lt;/span&gt;&lt;/li&gt;&lt;li style=&quot;border: none; margin: 0px 0px 0.25em; padding: 0px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Cloud : OCI (free tier account&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;color: #333333; font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-size: 14.85px;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Jasypt ?&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;http://www.jasypt.org/&quot; target=&quot;_blank&quot;&gt;Jasypt&lt;/a&gt; (Java Simplified Encryption) 는 자바 애플리케이션 속성 파일, 데이터베이스 비밀번호, 또는 기타 중요한 데이터를 쉽게 암호화하고 복호화할 수 있도록 도와주는 것이다. Jasypt는 복잡한 암호화 알고리즘을 이해하거나 구현할 필요 없이 간단한 API를 통해 보안을 향상시킬 수 있도록 설계되었다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg50imjEHKtIJOPcVsSUGd5iFieOPEJ-55WGo4WRmBkZ705h-NPDgHT2P75H_DZFE22D7yI1qJpo_8VspyXeFJ6_Zipf_k_2dh04FNrAklcCQRlG-WVOpPYUJSevIp31yCJAgIueeDcbMJQE-MzcL4xv_lMdznpg9N39cSIpJMGp7Ui8WSid2kce9GpYgPl/s338/jasypt-small.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;100&quot; data-original-width=&quot;338&quot; height=&quot;95&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg50imjEHKtIJOPcVsSUGd5iFieOPEJ-55WGo4WRmBkZ705h-NPDgHT2P75H_DZFE22D7yI1qJpo_8VspyXeFJ6_Zipf_k_2dh04FNrAklcCQRlG-WVOpPYUJSevIp31yCJAgIueeDcbMJQE-MzcL4xv_lMdznpg9N39cSIpJMGp7Ui8WSid2kce9GpYgPl/s320/jasypt-small.png&quot; width=&quot;320&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;주요 특징&lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;암호화 및 복호화 기능&lt;/strong&gt;: 비밀번호, 속성 값 등의 중요한 데이터를 쉽게 암호화하고, 필요한 시점에 복호화&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;구성 파일 보호&lt;/strong&gt;: 애플리케이션의 &lt;code&gt;application.properties&lt;/code&gt; 또는 &lt;code&gt;application.yml&lt;/code&gt;과 같은 설정 파일에서 중요한 정보(예: 데이터베이스 연결 정보)를 암호화&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;알고리즘 지원&lt;/strong&gt;: AES, DES, PBE 등 다양한 암호화 알고리즘을 지원&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;설정이 용이&lt;/strong&gt;: 환경 변수나 명령줄 인자를 통해 암호화 키를 전달하고, 자동으로 암호화된 데이터를 복호화할 수 있는 기능을 제공&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;스프링 통합&lt;/strong&gt;: 스프링 프레임워크와 통합되어 스프링 부트&amp;nbsp;(&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Spring Boot)&amp;nbsp;&lt;/span&gt;애플리케이션에서 손쉽게 사용&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Jasypt는 특히 애플리케이션 보안 향상을 위해 중요한 정보를 암호화하는 데 유용하며, 자바 기반 프로젝트에서 많이 사용된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Jasypt를 사용한 암호화 적용 방법&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;재십트(jasypt) 는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;스프링 부트&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Spring Boot) 와의 통합을 돕기 위해 &lt;u&gt;jasypt-spring-boot-starter&lt;/u&gt; 라이브러리를 제공한다. 이를 사용하면 Spring Boot 의 환경 설정 파일(application.properties, application.yml)에서 암호화된 값을 쉽게 처리할 수 있다.&amp;nbsp; 아래는 gradle 기반 스프링 부트 (&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Spring Boot&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;) 프로젝트에&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;암호화를&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;적용하는 것을 설명한다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❶ 의존성 추가: build.gradle 에&amp;nbsp;&lt;/span&gt;&lt;u style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;jasypt-spring-boot-starter&lt;/u&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;라이브러리&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;의존성을 추가한다.&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt; implementation &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4&quot; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❷&amp;nbsp;&lt;strong&gt;암호화된 값 사용&lt;/strong&gt;:
애플리케이션의 &lt;code&gt;application.properties&lt;/code&gt; 또는 &lt;code&gt;application.yml&lt;/code&gt; 파일에 민감한 데이터를 암호화된 상태로 저장할 수 있다. 암호화된 값은 &lt;code&gt;ENC(...)&lt;/code&gt; 형식으로 표기한다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic Coding&amp;quot;;&quot;&gt;application.yml&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;datasource&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;driver-class-name&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;net.sf.log4jdbc.sql.jdbcapi.DriverSpy&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;url&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;jdbc:log4jdbc:postgresql://localhost:5432/studio_db&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;username&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;ENC(amX5KdNShNl7jMYsHfpWccYeGhDWHD9bXsxXQSZGuUI=)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;password&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;ENC(4EyexAjWphLdRG6NaDaPb2S2c6gU8PZr/QgLM7e4nY4=)&lt;/span&gt;  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❸&amp;nbsp;&lt;strong&gt;Jasypt Encryptor 설정&lt;/strong&gt;: 재십트(jasypt)&amp;nbsp;가 암호화된 값을 복호화할 수 있도록 &lt;code&gt;JasyptStringEncryptor&amp;nbsp;&lt;/code&gt;를 설정해야 한다.&amp;nbsp;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;스프링 부트&amp;nbsp;(&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Spring Boot)&lt;/span&gt;&amp;nbsp;애플리케이션에서는 암호화를 위한 비밀번호를 설정하는 것으로 간단하게 구현할 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;비밀번호를 전달하는 방법은 여러가지 방법이 있다.  &lt;br /&gt;&lt;br /&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;환경변수로 전달&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CI/CD 도구에서 지원하는 시크릿 관리 기능을 사용하여 전달&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AWS Secrets Manager, HashiCorp Vault, Azure Key Vault 등의 비밀 관리 서비스 사용하여 전달&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;사용자 정의 JasyptStringEncryptor 을 구현하여 원하는 곳에서 비밀번호를 로드하여 직접 사용&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;아래는 환경변수를 사용하여 비밀번호를 전달하는 방법이다.&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;application.yml&lt;/span&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;  jasypt&lt;/span&gt;:&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; white-space: pre;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;encryptor&lt;/span&gt;:&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; white-space: pre;&quot;&gt;      &lt;span style=&quot;color: #569cd6;&quot;&gt;password&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;${JASYPT_ENCRYPTOR_PASSWORD}&lt;/span&gt; &lt;span style=&quot;color: #6a9955;&quot;&gt;# 환경 변수로 암호화 비밀번호 설정&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;JASYPT_ENCRYPTOR_PASSWORD 환경변수에 비밀번호를 세팅.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;&lt;strong&gt;Linux/macOS&lt;/strong&gt;:&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;export JASYPT_ENCRYPTOR_PASSWORD=your-encryption-password&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;./gradlew bootRun&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;&lt;strong&gt;Windows&lt;/strong&gt;:&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;set JASYPT_ENCRYPTOR_PASSWORD=your-encryption-password&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;gradlew bootRun&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❹&amp;nbsp;&lt;strong&gt;암호화&amp;nbsp;&lt;/strong&gt;:
Jasypt CLI(Command Line Interface)를 사용하여 값을 암호화하거나 복호화할 수 있다. 예를 들어, 다음과 같이 명령어를 사용하여 값을 암호화할 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;encrypt input=&lt;span class=&quot;hljs-string&quot;&gt;&quot;yourSecretValue&quot;&lt;/span&gt; password=&lt;span class=&quot;hljs-string&quot;&gt;&quot;your-encryption-password&quot;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class=&quot;hljs-string&quot;&gt;&lt;a href=&quot;https://github.com/jasypt/jasypt/releases/download/jasypt-1.9.3/jasypt-1.9.3-dist.zip&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;jasypt 1.9.3 (binaries and javadocs)&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;암호화된 값을 ❷ 암호화된 값 사용 과 같이 application.yml 설정에 기술하면 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt) 암호화&lt;/span&gt;&lt;/h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;재십트(jasypt) 에서 디폴트로 적용되는 암호화 알고리즘과 관련된 주요 값들은 다음과 같다. 이 값들은&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;를 기본 설정으로 사용할 때 적용되는 값 들이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;br /&gt;① 디폴트 암호화 알고리즘&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;background-color: #fcff01;&quot;&gt;PBEWithMD5AndDES&lt;/span&gt;: 기본적으로 Jasypt는 PBE (Password-Based Encryption) 알고리즘 중 하나인 PBEWithMD5AndDES를 사용한다. PBEWithMD5AndDES는 MD5 해시 알고리즘과 DES(Data Encryption Standard)를 사용한 암호화 알고리즘이다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;이 알고리즘은 기본적인 보안성을 제공하지만, 현대적 암호화 표준에 비해 상대적으로 약한 것으로 간주되기 때문에 더 강력한 알고리즘을 사용할 수 있도록 설정을 변경하는 것이 좋다.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;② 디폴트 해시 알고리즘&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;background-color: #fcff01;&quot;&gt;MD5&lt;/span&gt;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;는 기본적으로 MD5 해시 알고리즘을 사용하여 암호화 키를 처리한다. MD5는 널리 사용되지만, 충돌 공격에 취약하다는 보안 문제로 인해 요즘은 SHA-256 또는 SHA-512와 같은 더 강력한 해시 알고리즘이 선호된다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;③ 키 생성 반복 횟수&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;1000번 &lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;반복: Jasypt는 기본적으로 암호화 키를 생성할 때 1000번의 반복을 수행한다. 이 값은 비밀번호 기반 암&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;호화의 보안성을 높이기 위한 중요한 요소로 이 값을 더 높여 보안을 강화할 수 있다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;④ 디폴트 Salt Generation (솔트 생성)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;랜덤 솔트:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;는 암호화 시 자동으로 랜덤 솔트(Salt) 값을 생성한다. 솔트는 암호화된 값의 보안성을 높이기 위해 추가되는 값으로, 암호화된 텍스트의 패턴화를 방지하는 역할을 한다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;⑤ 디폴트 출력 포맷&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Base64:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;는 암호화된 텍스트를 기본적으로 Base64 로 인코딩하여 출력한다. Base64는 바이너리 데이터를 텍스트로 인코딩하는 방식으로, 암호화된 값을 쉽게 문자열로 표현할 수 있게 한다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;⑥ IV(Initialization Vector, 초기화 벡터)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;기본적으로 Jasypt는 PBEWithMD5AndDES 알고리즘을 사용할 때 초기화 벡터(IV)를 생성하지 않는데 알고리즘 자체가 IV를 사용하지 않기 때문이다. 그러나 다른 알고리즘, 예를 들어 AES와 같은 알고리즘을 사용할 때는 IV가 자동으로 처리된다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;⑦ 디폴트 암호화기(PBE String Encryptor)&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;는 기본적으로 **&lt;i&gt;&lt;b&gt;StandardPBEStringEncryptor&lt;/b&gt;&lt;/i&gt;**를 사용하여 문자열을 암호화 및 복호화한다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;이와 같은 기본 설정들은 애플리케이션의 보안 요구에 맞게 조정할 수 있으며, 기본값을 사용하더라도 어느 정도의 보안을 제공하지만, 더 강력한 알고리즘 변경  권장된다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;아래는 보안 수준에 따른 알고리즘 및 설정 값을 정리한 것이다. 운영 환경이라면 최소 중간 수준이상의 알고리즘 적용이 필요하다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;낮은 보안 수준&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;알고리즘 :&amp;nbsp;&lt;span style=&quot;color: red;&quot;&gt;PBEWithMD5AndDES&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 획득 반복 횟수&amp;nbsp;:&amp;nbsp;1000&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 길이&amp;nbsp;:&amp;nbsp;56&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;솔트 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV 사용&amp;nbsp;: ✗&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명 :&amp;nbsp;기본 Jasypt 설정. MD5와 DES를 사용하는 알고리즘으로 비교적 낮은 보안 수준. 과거에 널리 사용되었으나 &lt;span style=&quot;color: red;&quot;&gt;현대의 공격에 취약&lt;/span&gt;.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;권장 사용 환경 :&amp;nbsp;테스트 환경 또는 민감하지 않은 데이터를 암호화할 때.&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;보통 보안 수준&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;알고리즘&amp;nbsp;:&amp;nbsp;&lt;span style=&quot;color: red;&quot;&gt;PBEWithSHA1AndDESede&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 획득 반복 횟수&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;:&amp;nbsp;1000&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 길이&amp;nbsp;:&amp;nbsp;168&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;솔트 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV 사용&amp;nbsp;:&amp;nbsp;✗&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명 :&amp;nbsp;SHA-1 해시 알고리즘과 3DES 암호화 알고리즘 사용. &lt;span style=&quot;color: red;&quot;&gt;DES보다 더 안전하지만, SHA-1이 약해져 더 강력한 알고리즘이 권장&lt;/span&gt;됨.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;u&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;권장 사용 환경 :&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;테스트 환경 또는 민감하지 않은 데이터를 암호화할 때.&lt;/span&gt;&lt;/u&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;중간&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;보안 수준&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;알고리즘&amp;nbsp;:&amp;nbsp;PBEWithSHA256And128BitAES-CBC-BC&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 획득 반복 횟수&amp;nbsp;:&amp;nbsp;1000&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 길이&amp;nbsp;:&amp;nbsp;168&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;솔트 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명 :&amp;nbsp;SHA-256 해시 알고리즘과 AES-128 비트 암호화를 사용. AES는 고성능과 높은 보안성을 제공. IV를 사용하여 보안성을 강화.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;권장 사용 환경 :&amp;nbsp;내부 시스템의 암호화 작업이나 중요하지만 최고 수준의 보안을 요구하지 않는 환경.&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;높은&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;보안 수준&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;알고리즘&amp;nbsp;:&amp;nbsp;PBEWithHMACSHA512AndAES_256&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 획득 반복 횟수&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;:&amp;nbsp;1000&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 길이&amp;nbsp;:&amp;nbsp;256&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;솔트 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명 :&amp;nbsp;HMAC-SHA512 해시 알고리즘과 AES-256 비트 암호화를 사용. AES-256은 강력한 보안을 제공하며, HMAC을 사용해 무결성 보장.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;권장 사용 환경 :&amp;nbsp;금융 서비스, 헬스케어 시스템 등 민감한 데이터를 보호해야 하는 환경.&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;매우높은&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;보안 수준&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;알고리즘&amp;nbsp;:&amp;nbsp;PBEWithHMACSHA512AndAES_256&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 획득 반복 횟수&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;:&amp;nbsp;5000~10000&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 길이&amp;nbsp;:&amp;nbsp;256&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;솔트 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV 사용&amp;nbsp;: ✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명 :&amp;nbsp;암호화와 해시에서 최고 수준의 보안. 반복 횟수를 늘리고 AES-256을 사용하여 비밀번호 기반 암호화의 보안을 최대한 강화.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;권장 사용 환경 :&amp;nbsp;금융 서비스, 헬스케어 시스템 등 민감한 데이터를 보호해야 하는 환경.&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;최고&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;보안 수준&lt;/span&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;알고리즘&amp;nbsp;:&amp;nbsp;PBKDF2WithHmacSHA512 + AES_256&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 획득 반복 횟수&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;:&amp;nbsp;10000~50000&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;키 길이&amp;nbsp;:&amp;nbsp;256&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;솔트 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;IV 사용&amp;nbsp;:&amp;nbsp;✓&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설명 :&amp;nbsp;PBKDF2는 비밀번호 기반 키 도출 기능으로 반복 횟수와 HMAC-SHA512를 사용해 높은 보안성을 제공. AES-256과 함께 사용하면 최상의 보안을 제공.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;권장 사용 환경 :&amp;nbsp;정부, 군사 시스템, 민감한 데이터를 보호하는 최고 수준의 보안이 요구되는 환경&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;중간 보안 요구 이상에서는 &lt;b&gt;&lt;u&gt;AES-256&lt;/u&gt;과 함께 &lt;u&gt;PBEWithHMACSHA512AndAES_256&lt;/u&gt;&lt;/b&gt; 또는 &lt;b&gt;&lt;u&gt;PBKDF2WithHmacSHA512&lt;/u&gt;&lt;/b&gt;를 사용하는 것이 권장. AES-256은 현재 가장 안전한 암호화 표준 중 하나이며, HMAC-SHA512는 암호화 데이터의 무결성을 보장. 반복 횟수(Iterations)를 5000번 이상으로 설정하여 암호화 키 도출 과정의 보안을 더욱 강화하는 것을 권장.&lt;br /&gt;&lt;br /&gt;특히 개인정보와 같은 민감한 데이터 보호가 필요한 환경에서는 &lt;u&gt;AES-256&lt;/u&gt;과 &lt;u&gt;HMAC-SHA512&lt;/u&gt;를 사용한 설정을 적극 추천.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;중간 수준이상의 암호화 적용&lt;/span&gt;&lt;/h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;테스트 환경에서는 디폴트 암호화 알고리즘 이외의 암호화를 사용하려는 경우 오류가 발생하여 진행이 불가 하였다. 이런 이유로 환경 이슈에 독립적으로 동작하도록&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&lt;/span&gt;보니캐슬(Bouncy Castle)&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;암호화 프로바이터를 사용하였다. (맥 환경이 문제는 아닌가 추정만 하였다.)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❶ 의존성 추가: build.gradle 에&amp;nbsp;&lt;/span&gt;보니캐슬(Bouncy Castle)&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;라이브러리&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;의존성을 추가한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;❷&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt)&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;에&amp;nbsp;&lt;/span&gt;보니캐슬(Bouncy Castle)&amp;nbsp;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설정&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Jasypt 설정 예시 (AES 256 사용):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic Coding&amp;quot;;&quot;&gt;application.yml&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;encryptor&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;password&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;${JASYPT_ENCRYPTOR_PASSWORD}&lt;/span&gt; &lt;span style=&quot;color: #6a9955;&quot;&gt;# 환경 변수로 암호화 비밀번호 설정&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;algorithm&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;PBEWithSHA256And256BitAES-CBC-BC&quot;&lt;/span&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;# Bouncy Castle 알고리즘 사용&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;providerName&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;BC&quot;&lt;/span&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;# Bouncy Castle 프로바이더 지정&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;key-obtention-iterations&lt;/span&gt;: &lt;span style=&quot;color: #b5cea8;&quot;&gt;1000&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;pool-size&lt;/span&gt;: &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;salt-generator-classname&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;org.jasypt.salt.RandomSaltGenerator&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;string-output-type&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;base64&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;PBEWithSHA256And256BitAES-CBC-BC:&amp;nbsp;&lt;/span&gt;보니캐슬(Bouncy Castle)&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 제공하는 AES-256 알고리즘이다.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;❸&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;Bouncy Castle 프로바이더 등록&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Java 환경에서 보니캐슬(Bouncy Castle)을 암호화 프로바이더로 등록해야 하며, 이 작업은 JVM이 시작될 때 수행할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;스프링 부트&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Spring Boot)&amp;nbsp;에서는 Application.java 에 추가하여 프로바이터를 등록할 수 있다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;java&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Security&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;bouncycastle&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;jce&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;provider&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;BouncyCastleProvider&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;boot&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;SpringApplication&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;org&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;springframework&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;boot&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;autoconfigure&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;SpringBootApplication&lt;/span&gt;;&lt;/div&gt;&lt;br /&gt;&lt;div&gt; @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;SpringBootApplication&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt; public&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;MyApplication&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;void&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;main&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;String&lt;/span&gt;[] &lt;span style=&quot;color: #9cdcfe;&quot;&gt;args&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Security&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getProvider&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;BouncyCastleProvider&lt;/span&gt;.&lt;span style=&quot;color: #4fc1ff;&quot;&gt;PROVIDER_NAME&lt;/span&gt;) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;            &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Security&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;addProvider&lt;/span&gt;(&lt;span style=&quot;color: #c586c0;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;BouncyCastleProvider&lt;/span&gt;());&lt;/div&gt;&lt;div&gt;        }&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #4ec9b0;&quot;&gt;SpringApplication&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;run&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;MyApplication&lt;/span&gt;.&lt;span style=&quot;color: #c586c0;&quot;&gt;class&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;args&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt; }&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;좀더 자동화된 방법을 고민하다&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;재십트(jasypt) 라이브러리가 추가되어 있고&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;보니캐슬(Bouncy Castle) 암호화 라이브러리가 있는경우&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;보니캐슬(Bouncy Castle) 프로파이더를 추가 하고&amp;nbsp; 디폴트&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;암호화(&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;i style=&quot;font-weight: bold;&quot;&gt;StandardPBEStringEncryptor) &lt;/i&gt;모듈을 생성하도록 자동화된 설정을 구현하여 사용하였다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;다만 이경우&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Jasypt CLI(Command Line Interface)를 사용하여 값을 암호화하거나 복호화 하는 것이 어려워저 추가로 암호화를 위한 RESTful API 을 추가하여 사용할 수 있도록 하였다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특정 값을 암호화하려면 아래와 같이 curl 을 사용하여 암호화하고 yml 파일에 ENC() 함수를 사용하여 암호화된 값으로 설정을 추가하면 된다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;curl localhost:8080/data/encrypt -s -d 암호화할 데이터&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
  
&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf6O9l4nCUvGvZdSjMNvkwN5rBdtdfpHkvsehpxqd7KTPydc5vwDN_Ufa5AJHCse4xBjndoTtpqCCEhKW29InRRIuOJNwBWBzHKaU1u1h5Wzw4hGRZzGCpYNxAEXFXZ1ULAk3oMGMIwWWgmWrCPGAIXRD_8tG6DQrDhvbYQfDsb1EgzqaXHG9DjN7j4v7O/s1462/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-02_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_43_40.jpg&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;224&quot; data-original-width=&quot;1462&quot; height=&quot;98&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf6O9l4nCUvGvZdSjMNvkwN5rBdtdfpHkvsehpxqd7KTPydc5vwDN_Ufa5AJHCse4xBjndoTtpqCCEhKW29InRRIuOJNwBWBzHKaU1u1h5Wzw4hGRZzGCpYNxAEXFXZ1ULAk3oMGMIwWWgmWrCPGAIXRD_8tG6DQrDhvbYQfDsb1EgzqaXHG9DjN7j4v7O/w640-h98/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-10-02_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_43_40.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;
  
  &lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
  
  &lt;script src=&quot;https://gist.github.com/donghyuck/53c4dbf4cdefbac36287c8b284d14343.js&quot;&gt;&lt;/script&gt;
  
  &lt;h3&gt;참고자료&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;a href=&quot;https://andang72.blogspot.com/2024/02/cloud-ready-appliction-spring-config.html&quot; target=&quot;_blank&quot;&gt;코딩 - Cloud Ready : Spring Config Server&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/9043504548464169935/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/10/spring-boot.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/9043504548464169935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/9043504548464169935'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/10/spring-boot.html' title='코딩 - Spring Boot 환경에서 설정 정보 암호화'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg50imjEHKtIJOPcVsSUGd5iFieOPEJ-55WGo4WRmBkZ705h-NPDgHT2P75H_DZFE22D7yI1qJpo_8VspyXeFJ6_Zipf_k_2dh04FNrAklcCQRlG-WVOpPYUJSevIp31yCJAgIueeDcbMJQE-MzcL4xv_lMdznpg9N39cSIpJMGp7Ui8WSid2kce9GpYgPl/s72-c/jasypt-small.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-8621108764348948723</id><published>2024-08-09T22:33:00.002+09:00</published><updated>2024-08-09T22:34:38.772+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="spring boot"/><category scheme="http://www.blogger.com/atom/ns#" term="tus"/><category scheme="http://www.blogger.com/atom/ns#" term="uppy"/><category scheme="http://www.blogger.com/atom/ns#" term="Vue3"/><title type='text'>코딩 - Vue3 : Uppy 을 이용한 파일 업로드</title><content type='html'>&lt;p&gt;&amp;nbsp;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;◼︎ 환경&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 13.2.4 (22F66)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : Visual Studio Code, Java 11, Gradle, Docker&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version Control : GitHub&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Java, Vue3&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;Front-End Framework : Vue 3.4.30, Vuetify 3.6.10, ag-grid-vue3 31.3.2&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Back-End Framework : Spring Boot 2.7.12, Spring Security 5.7.7&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DBMS : MySql 8.0.33&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Cloud : OCI (free tier account&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;h3 style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;&lt;h3 style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. 업로드 라이브러리 &amp;amp; 모듈 조사&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vue 3 환경에서 파일업로드 구현을 위한 인기있는 라이브러리 또는 모듈들에는&amp;nbsp; 여러 가지가 있다. 추가로 사용성 확인을 위하여 npmjs.com 사이트를 활용하였다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➀ Dropzone&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Weekly Downloads: 363,089&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version: 6.0.0-beta.2&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Last Publish: 3년 전&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특징: 가장 많이 사용되는 파일 업로드 라이브러리 중 하나이며, Vue.js 에서도 널리 사용되고 있음. 하지만, Vue 3 공식 지원이 부족할 수 있음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➁ Vue3 Dropzone&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Weekly Downloads: 10,754&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version: 2.2.1&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Last Publish: 8개월 전&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특징: Dropzone.js의 Vue 3 통합 버전으로, Vue 3 프로젝트에서 드래그 앤 드롭 파일 업로드를 쉽게 구현할 수 있음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➂ Vue Advanced Cropper&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Weekly Downloads: 82,508&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version: 2.8.9&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Last Publish: 2달 전&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특징: 이미지 크롭 기능을 제공하는 파일 업로드 라이브러리로, Vue 3와의 호환성이 높고, 비교적 최근에 업데이트되었음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➃ Uppy&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Weekly Downloads: 23,383&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version: 4.1.0&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Last Publish: 10일 전&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특징: 강력한 모듈화 파일 업로드 라이브러리로, 여러 소스에서 파일을 업로드할 수 있으며, Vue 3와의 호환성도 좋음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➄ Vue FilePond&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Weekly Downloads: 21,154&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version: 7.0.4&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Last Publish: 1년 전&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특징: 사용자 친화적인 인터페이스를 제공하며, 다양한 파일 포맷을 지원. 다만, 최근에 업데이트가 없음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➅ Vue Uploader&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Weekly Downloads: 115&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version: 3.37.1&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Last Publish: 1년 전&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;특징: 다운로드 수가 비교적 적으며, 최근 업데이트가 없는 편임. 작은 프로젝트나 간단한 용도로 적합할 수 있음.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;간단하게 요약해보면 아래와 같다.&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;가장 많이 사용되는 라이브러리: Dropzone은 여전히 가장 많은 다운로드 수를 기록하고 있으며, 널리 사용되고 있다. 하지만 Vue 3에 대한 직접적인 지원이 부족할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vue 3 에 적합한 라이브러리: Vue Advanced Cropper, Uppy, Vue FilePond, Vue3 Dropzone 등은 Vue 3에서 사용할 수 있는 좋은 선택이다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;개인적으로는&amp;nbsp;Vue3 Dropzone, Vue FilePond 은 사용해 보았고 이번에는 대용량 파일 업로드가 강점이라고 하는 Uppy 을 사용해 보았다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. Uppy&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://uppy.io/&quot; target=&quot;_blank&quot;&gt;Uppy&lt;/a&gt;는 강력하고 모듈화된 파일 업로드 라이브러리로, 다양한 파일 소스에서 업로드를 지원하며 파일 업로드 경험을 쉽게 관리할 수 있도록 설계되었다. Uppy는 최신 웹 기술을 활용하며, 파일 업로드를 직관적으로 구현할 수 있도록 다양한 플러그인을 제공한다. Vue.js와의 통합도 지원하여, Vue 프로젝트에서 Uppy의 기능을 쉽게 사용할 수 있다.&lt;/div&gt;&lt;div&gt;&lt;strong&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;모듈식 구조&lt;/strong&gt;: 필요한 기능만 선택적으로 사용할 수 있도록 다양한 플러그인으로 구성되어 있다. 예를 들어, 파일 드래그 앤 드롭, 웹캠, Google Drive, Dropbox 등 다양한 소스를 지원한다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;다양한 파일 소스&lt;/strong&gt;: 로컬 파일뿐만 아니라 원격 소스(예: Google Drive, Dropbox, Instagram)에서도 파일을 업로드할 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;Vue.js 통합&lt;/strong&gt;: &lt;code&gt;@uppy/vue&lt;/code&gt; 패키지를 통해 Vue.js 프로젝트에 쉽게 통합할 수 있다.&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;strong&gt;커스터마이징 가능&lt;/strong&gt;: 업로드 UI와 동작을 프로젝트의 요구에 맞게 커스터마이징할 수 있다. 또한, 업로드 진행률 표시, 취소, 재시도 등의 기능도 제공.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;⇨&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;UI 커스터마이징이 비교적 용의했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;3. Uppy 설치&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Uppy와 Vue 통합 패키지를 설치한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: white;&quot;&gt;&lt;span style=&quot;font-family: Menlo, Monaco, Courier New, monospace;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;npm install @uppy/core &lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;@uppy/dashboard @uppy/drag-drop @uppy/file-input @uppy/progress-bar&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: white; font-family: Nanum Gothic Coding;&quot;&gt;    @uppy/vue @uppy/xhr-upload --save&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;4. Uppy 을 이용한 파일 업로드&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;업로드 구현은 아래와 같은 순서로 코딩하면 된다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❶ Uppy 컴포넌트 임포트&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;script&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;setup&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;lang&lt;/span&gt;=&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ts&quot;&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt; // import upload component(uppy)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;Uppy&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;@uppy/core&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt; import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;Dashboard&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;@uppy/vue&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;XHRUpload&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;@uppy/xhr-upload&#39;&lt;/span&gt;; &lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;@uppy/core/dist/style.css&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt; import&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;@uppy/dashboard/dist/style.css&#39;&lt;/span&gt;;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❷ Vue 컴포넌트에서&amp;nbsp;&lt;code&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Dashboard&lt;/span&gt;&lt;/code&gt;&amp;nbsp;사용&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;dashboard-container&quot;&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Dashboard&lt;/span&gt; :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;uppy&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;uppy&lt;/span&gt;&quot;  &lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;               &lt;span style=&quot;color: #9cdcfe;&quot;&gt;inline&lt;/span&gt;=&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;true&quot;&lt;/span&gt;  &lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;               :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt;=&quot;&lt;span style=&quot;color: #b5cea8;&quot;&gt;200&lt;/span&gt;&quot;  &lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;               :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;note&lt;/span&gt;=&quot;&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;Images only, up to 10MB&#39;&lt;/span&gt;&quot;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;               :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metaFields&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metaFields&lt;/span&gt;&quot;&lt;span style=&quot;color: grey;&quot;&gt; /&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;@uppy/vue에서 가져온 Dashboard 컴포넌트를 사용하여 Vue 템플릿에서 Uppy 대시보드를 직접 렌더링.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;inline 속성을 사용 대시보드를 &amp;lt;div&amp;gt; 요소에 직접 렌더링 되도록 설정.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;metaFields 을 사용하여 업로드할 파일과 관련된 추가적인 메타데이터를 수집하고, 사용자로부터 입력받을 수 있게 한다. 이를 통해 파일에 대한 추가 정보를 서버로 전송하거나, 파일 처리 로직에서 메타데이터를 활용할 수 있다.&amp;nbsp; &amp;nbsp;&lt;span style=&quot;color: red;&quot;&gt;→ 이부분은 확인 할 수 없었다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❸ Uppy 인스턴스를 생성하고 파일업로드 플러그인을 설정&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;fileUploadUrl&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;computed&lt;/span&gt;(() &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/resources/images/${props.imageId}/upload&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;/div&gt;&lt;div&gt; })&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt; const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;uppy&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Uppy&lt;/span&gt;({&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;autoProceed&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;// 수동으로 업로드 시작&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;restrictions&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;maxFileSize&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;10000000&lt;/span&gt;,  &lt;span style=&quot;color: #6a9955;&quot;&gt;// 1최대 파일 크기: 10MB&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;maxNumberOfFiles&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;5&lt;/span&gt;,    // 업로드 가능한 최대 파일 수&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;minNumberOfFiles&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;,    // 업로드 가능한 최소 파일 수&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;allowedFileTypes&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; [&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;image/*&#39;&lt;/span&gt;]&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    }&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt; })&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;XHRUpload&lt;/span&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;, {&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;endpoint&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;fileUploadUrl&lt;/span&gt;.&lt;span style=&quot;color: #4fc1ff;&quot;&gt;value&lt;/span&gt;, // 업로드할 서버 엔드포인트&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fieldName&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;file&#39;&lt;/span&gt;,             // 서버에 전송되는 파일의 필드 이름&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;formData&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;,                // FormData를 사용하여 파일을 업로드 (멀티파트 사용)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;            &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;(),&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        },&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;retryDelays&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; [&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;1000&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;3000&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;5000&lt;/span&gt;]&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;});&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참로로 authHeader 는 JWT 토큰 관련 값을 정의하는 내용이다. 이런 방식으로 헤더에 값을 추가할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Uppy 는 여러가지 다수의 업로드 방식을 지원하고 있고 여기에서는 가장 일반적인 XHRUpload 을 적용했다.&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;XHRUpload&lt;/u&gt;: 가장 일반적인 파일 업로드 방식으로, 대부분의 서버에서 지원.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Tus: 대규모 파일 업로드 및 네트워크 문제로 인한 업로드 중단 시 재개를 지원하는 프로토콜&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Multipart: multipart/form-data 형식으로 서버에 파일을 전송.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;S3 Multipart: AWS S3에 대규모 파일을 멀티파트 방식으로 업로드.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://transloadit.com/&quot;&gt;Transloadit&lt;/a&gt;: 클라우드 기반 업로드 서비스와 통합&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;❹ 파일 업로드시 추가 정보 전송&lt;br /&gt;파일을 업로드 할때 추가 정보를 전송하려면 uppy 의 &lt;u&gt;upload&lt;/u&gt; 이벤트를 사용하여 추가하면된다. 이경우 멀티파트 파마메터 형식으로 추가된 값들이 전달된다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;uppy&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;on&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;upload&#39;&lt;/span&gt;, (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;uppy&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setMeta&lt;/span&gt;({ &lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;objectId&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataRef&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;objectId&lt;/span&gt; ,&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;objectType&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataRef&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;objectType&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;link&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;createSharedLink&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataRef&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;description&lt;/span&gt;&lt;/div&gt;&lt;div&gt;     });&lt;/div&gt;&lt;div&gt;});&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;❺&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;onBeforeUnmount 을 사용 컴포넌트가 파괴되기 전에 Uppy 인스턴스를 정리&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt; onBeforeUnmount&lt;/span&gt;(() &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;   &lt;span style=&quot;color: #4fc1ff;&quot;&gt;uppy&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;destroy&lt;/span&gt;();&lt;/div&gt;&lt;div&gt; });&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;❻ 업로드 영역 크기 조정하기&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Dashboard 의 height 을 사용해도 높이가 조정 되지 않기 떄문에&lt;/span&gt;&amp;nbsp;CSS 을 아래와 같은 방식으로 수정해 적용해야 한다.&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;style&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;scoped&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt; ::&lt;span style=&quot;color: #569cd6;&quot;&gt;v-deep&lt;/span&gt; &lt;span style=&quot;color: #d7ba7d;&quot;&gt;.uppy-Dashboard&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt;: &lt;span style=&quot;color: #b5cea8;&quot;&gt;250px&lt;/span&gt;; &lt;span style=&quot;color: #6a9955;&quot;&gt;/* 원하는 높이로 설정 */&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;max-height&lt;/span&gt;: &lt;span style=&quot;color: #b5cea8;&quot;&gt;100%&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;display&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;flex&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;flex-direction&lt;/span&gt;: &lt;span style=&quot;color: #ce9178;&quot;&gt;column&lt;/span&gt;;&lt;/div&gt;&lt;div&gt; }&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br class=&quot;Apple-interchange-newline&quot; /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwolAfW5IVQJQwNRzoW_y_Jj-NHTCH_CDG-EIZs3XFUn5X5NGbuF1NSKNJQmo79VNn3qqjKNquBhm0JTsNRC_9Rd6KKar2SIv0NoAZw7Q-P20F87ClT_loK4DQasq-n71bpiOCjuxQS8i8oT6OoMAZ16OFjL9yKxWl44AFqR52CcJNfz_N4tbHN7p08nVH/s1342/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.34.19.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1342&quot; data-original-width=&quot;1332&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwolAfW5IVQJQwNRzoW_y_Jj-NHTCH_CDG-EIZs3XFUn5X5NGbuF1NSKNJQmo79VNn3qqjKNquBhm0JTsNRC_9Rd6KKar2SIv0NoAZw7Q-P20F87ClT_loK4DQasq-n71bpiOCjuxQS8i8oT6OoMAZ16OFjL9yKxWl44AFqR52CcJNfz_N4tbHN7p08nVH/w398-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.34.19.png&quot; width=&quot;398&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #444444;&quot;&gt;그림1. 파일 업로드 화면&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRYb813kMxcy92rCUso216c1rM7nXNgzM9G2edtd4qJ9gkLIO-aYG2mJtpV50hbXkBdr7mNx-cC1FC7MNF4rhKh-cSUg7DMqyOMzCJIEgQ6dS7rIorWYh-q0xkGOsP6Zaj79Bawi64L_NUvbfi2-wugtLTwIhakfiP1yADQWPCkfcTmgcDYtgcSmA7KuEA/s1392/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.33.50.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1390&quot; data-original-width=&quot;1392&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRYb813kMxcy92rCUso216c1rM7nXNgzM9G2edtd4qJ9gkLIO-aYG2mJtpV50hbXkBdr7mNx-cC1FC7MNF4rhKh-cSUg7DMqyOMzCJIEgQ6dS7rIorWYh-q0xkGOsP6Zaj79Bawi64L_NUvbfi2-wugtLTwIhakfiP1yADQWPCkfcTmgcDYtgcSmA7KuEA/w400-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.33.50.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #444444;&quot;&gt;그림2. 파일을 추가한 화면&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibpC0AQtK37-OinpzClKvFUhW7lu-22cMXcF-Zaa1afO6od23wsNDmKq6Jo09SJqW5sUXOm9Y_U07VlqtjsZuMgoIFUYSTSnoDZjnAQ-jcQajTUHPMUhkQVnGCPQc55ndTnbvapID59yYb91hyphenhyphenB8cB9GEOzxWyKNqd7mMglTMXBHODNPy0h5vBgIdOyDgR/s1350/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.34.08.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1350&quot; data-original-width=&quot;1346&quot; height=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibpC0AQtK37-OinpzClKvFUhW7lu-22cMXcF-Zaa1afO6od23wsNDmKq6Jo09SJqW5sUXOm9Y_U07VlqtjsZuMgoIFUYSTSnoDZjnAQ-jcQajTUHPMUhkQVnGCPQc55ndTnbvapID59yYb91hyphenhyphenB8cB9GEOzxWyKNqd7mMglTMXBHODNPy0h5vBgIdOyDgR/w399-h400/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.34.08.png&quot; width=&quot;399&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #444444;&quot;&gt;그림3. 파일 업로드가 성공한 경우&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;➐ 서버 프로그램 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;XHRUpload 업로드 모듈의 경우 formData 옵션을 사용하면 multipart/form-data 형식으로 서버에 전송되기 때문에 기존 업로드 프로그램을 사용하여 업로드를 구현할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt; @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;PostMapping&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;/images/{imageId:[&lt;/span&gt;&lt;span style=&quot;color: #d7ba7d;&quot;&gt;\\&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;p{Digit}]+}/upload&quot;&lt;/span&gt; }, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;produces&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;MediaType&lt;/span&gt;.&lt;span style=&quot;color: #4fc1ff;&quot;&gt;APPLICATION_JSON_VALUE&lt;/span&gt;)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Image&lt;/span&gt;&amp;gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;upload&lt;/span&gt;(&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;PathVariable&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Long&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;imageId&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RequestParam&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;objectType&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;defaultValue&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;-1&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;required&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;) &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Integer&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;objectType&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RequestParam&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;objectId&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;defaultValue&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;-1&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;required&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;) &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Long&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;objectId&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RequestParam&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;description&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;required&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;) &lt;span style=&quot;color: #4ec9b0;&quot;&gt;String&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;description&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RequestParam&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;link&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;defaultValue&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;false&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;required&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;) &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Boolean&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;createLink&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RequestParam&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;file&quot;&lt;/span&gt;) &lt;span style=&quot;color: #4ec9b0;&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;MultipartFile&lt;/span&gt;&amp;gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;files&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;throws&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;NotFoundException&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;IOException&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;UnAuthorizedException&lt;/span&gt; {&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: #4ec9b0;&quot;&gt;User&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;user&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;SecurityHelper&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getUser&lt;/span&gt;();&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: #4ec9b0;&quot;&gt;List&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Image&lt;/span&gt;&amp;gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;list&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;new&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ArrayList&lt;/span&gt;&amp;lt;&amp;gt;();&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;MultipartFile&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mpf&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;files&lt;/span&gt;) {&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      &lt;span style=&quot;color: #4ec9b0;&quot;&gt;String&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fileName&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;StringUtils&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;cleanPath&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;mpf&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getOriginalFilename&lt;/span&gt;());&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      &lt;span style=&quot;color: #4ec9b0;&quot;&gt;InputStream&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mpf&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getInputStream&lt;/span&gt;();&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      &lt;span style=&quot;color: #4fc1ff;&quot;&gt;log&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;debug&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;upload &amp;lt;file name:{}, size:{}, type:{}&amp;gt;&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fileName&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mpf&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getSize&lt;/span&gt;(), &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mpf&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getContentType&lt;/span&gt;());&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;// 업로드 파일을 처리한다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;list&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;add&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;newImage&lt;/span&gt;);&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    }&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;list&lt;/span&gt;;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;  }&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;5. 대용량 파일 업로드  &lt;/span&gt;&lt;/h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt; Uppy 에서 대용량 파일 업로드는 Tus 프로토콜을 사용하여 구현 할 수 있다.&amp;nbsp;&amp;nbsp;Tus는 대규모 파일 업로드를 효율적으로 처리할 수 있도록 설계된 오픈 프로토콜로 Uppy는 Tus를 통해 파일을 청크 단위로 업로드하고, 중단된 업로드를 재개하는 등의 기능을 제공한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;npm install&amp;nbsp; @uppy/tus&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Uppy 에서는 간단하게&amp;nbsp;&lt;u style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;XHRUpload&amp;nbsp;&lt;/u&gt;파일 업로드 모듈을 &lt;u&gt;Tus&lt;/u&gt; 로 변경해주면 된다.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;Tus&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;@uppy/tus&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;tusFileUploadUrl&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;computed&lt;/span&gt;(()&lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt;{&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/resources/files/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt; props&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;imageId&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/tus`&lt;/span&gt;;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;})&lt;span style=&quot;color: #4fc1ff;&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;uppy&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;use&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Tus&lt;/span&gt;, {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;endpoint&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;tusFileUploadUrl&lt;/span&gt;.&lt;span style=&quot;color: #4fc1ff;&quot;&gt;value&lt;/span&gt;, &lt;span style=&quot;color: #6a9955;&quot;&gt;// Tus 서버 엔드포인트&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;chunkSize&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;5&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1024&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1024&lt;/span&gt;, &lt;span style=&quot;color: #6a9955;&quot;&gt;// 5MB 청크 사이즈&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;(),&lt;/div&gt;&lt;div&gt;  },&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #9cdcfe;&quot;&gt;retryDelays&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; [&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;1000&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;3000&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;5000&lt;/span&gt;]&lt;/div&gt;&lt;div&gt; })&lt;/div&gt;&lt;div&gt;;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클라이언트 부분과 다르게 서버는 Tus 프로토콜에 따른 서버 프로그램을 새로 구현해야한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Tus 프로토콜&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Tus 프로토콜은 클라이언트와 서버 간 4단계로 파일을 업로드합니다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❶ 파일 생성(Create):&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클라이언트는 서버에 새로운 업로드를 생성하도록 요청한다.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;이 요청에는 파일의 크기와 메타데이터가 포함될 수 있다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버는 업로드에 고유한 URL을 생성하고 클라이언트에게 반환한다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;파일 및 메타 정보는 이때만 전송된다. 이후에는 데이터만 전송된다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❷ 파일 업로드(Upload):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;클라이언트는 생성된 URL을 사용하여 파일의 특정 바이트를 서버에 업로드한다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버는 클라이언트가 업로드한 바이트를 확인하고, 다음 업로드 시 어디서부터 시작할지 오프셋(Upload-Offset)을 반환한다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❸ 업로드 재개(Resume):&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;업로드 중단 시 클라이언트는 서버에서 제공한 오프셋을 사용하여 중단된 지점부터 업로드를 재개할 수 있다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;❹ 업로드 완료(Completion):&lt;br /&gt;&lt;/span&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;모든 바이트가 성공적으로 업로드되면 업로드가 완료된다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;프로토콜 메시지&lt;/span&gt;&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OPTIONS: 서버가 Tus 프로토콜을 지원하는지 확인하고, 지원하는 기능을 확인하기 위해 클라이언트가 전송. 서버는 지원하는 버전, 최대 파일 크기 등의 정보를 응답.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;POST&lt;/u&gt;: 새로운 업로드를 생성하기 위해 사용. 서버는 업로드 URL을 응답합니다.&amp;nbsp;&lt;/span&gt;❶&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;HEAD&lt;/u&gt;:업로드 상태를 확인하기 위해 사용. 서버는 현재 업로드된 바이트의 오프셋을 응답.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;PATCH&lt;/u&gt;: 파일의 특정 바이트를 업로드하기 위해 사용. 서버는 업로드된 바이트를 저장하고, 새로운 오프셋을 응답.&amp;nbsp;&lt;/span&gt;❷❸&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DELETE:업로드를 취소하거나 삭제하기 위해 사용. 서버는 업로드된 데이터를 삭제합니다.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWVyYMyNl3sYCq2ez1BXjYd2Rrex10iC72y4rWiDVrm7BIrga0DDpTQfiYZytmbPQlEuSBY4zjH2-9vV1OxREvcoD-D7XgPd54hP3vak39I-UdXuDFFO02Mp1xUrGI9VpPVl7PkUASwkLE6bngAy_ifYEoUCoeF8T87heMg9M_qCmJ-DqMZIue05jWfkEZ/s913/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.23.39.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;913&quot; data-original-width=&quot;598&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWVyYMyNl3sYCq2ez1BXjYd2Rrex10iC72y4rWiDVrm7BIrga0DDpTQfiYZytmbPQlEuSBY4zjH2-9vV1OxREvcoD-D7XgPd54hP3vak39I-UdXuDFFO02Mp1xUrGI9VpPVl7PkUASwkLE6bngAy_ifYEoUCoeF8T87heMg9M_qCmJ-DqMZIue05jWfkEZ/w421-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.23.39.png&quot; width=&quot;421&quot; /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;color: #444444;&quot;&gt;그림4. 파일 업로드 프로세스&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;다음은 파일이 업로드되면 유니크한 아이디를 생성하고 메타 정보는 meta.json 형태로 저장하여 청크파일 업로드를 구현하는 예이다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/donghyuck/25cbb05697ddd7f31d6cfaed65dfb526.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/8621108764348948723/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/08/vue3-uppy.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/8621108764348948723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/8621108764348948723'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/08/vue3-uppy.html' title='코딩 - Vue3 : Uppy 을 이용한 파일 업로드'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwolAfW5IVQJQwNRzoW_y_Jj-NHTCH_CDG-EIZs3XFUn5X5NGbuF1NSKNJQmo79VNn3qqjKNquBhm0JTsNRC_9Rd6KKar2SIv0NoAZw7Q-P20F87ClT_loK4DQasq-n71bpiOCjuxQS8i8oT6OoMAZ16OFjL9yKxWl44AFqR52CcJNfz_N4tbHN7p08nVH/s72-w398-h400-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-08-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.34.19.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-3992522658133560035</id><published>2024-07-18T10:17:00.007+09:00</published><updated>2024-07-20T21:47:55.794+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatgpt"/><category scheme="http://www.blogger.com/atom/ns#" term="GitHub Copilot"/><category scheme="http://www.blogger.com/atom/ns#" term="생성형 AI"/><category scheme="http://www.blogger.com/atom/ns#" term="생성형 AI 코딩"/><title type='text'>사용기 - 생성형 AI 를 이용한 코딩 후기</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;ChatGPT 4o&lt;/span&gt;&lt;/h2&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. 코드 생성&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;존재하는 코드 개선 JWTFilter&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀 Spring Security 필터에 커스텀 JWTFilter 을 추가 하여 사용하고 있다. JWTFilter에서 오류가 발생하면 login 페이지가 아닌 오류 메시지를 JSON 데이터로 응답하게 하려면&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 &lt;u&gt;GitHub Copilot&lt;/u&gt; 의 경우 JWTFilter에서 오류가 발생하면&amp;nbsp;HttpServletResponse 을 사용하여 JSON 데이터를 만들어 응답하라고 답변.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;✓ 제시된 코드는 문제를 해결하지 못함. Spring Security 에 의해서 설정된 login 페이지로 이동한다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0qiyfcK-ttwWM4Ukv4sOVXm6LHx0WbS0pq1PxabYaRnY4dpxwEzw8zsZjQxGZTtzVmPl3DNMOS5QQ0TBU0XXxNQ6C6IQMAfhd2jiHUKVSHGgC0tAMQRL-zo3tnj-b4-lnFOnlHAFDyMRRmMEt9pKwu9-dsYhYvR6vAopgm2PCx2329_xiBGu8lUVt-ceE/s1482/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.25.25.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1482&quot; data-original-width=&quot;1204&quot; height=&quot;640&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0qiyfcK-ttwWM4Ukv4sOVXm6LHx0WbS0pq1PxabYaRnY4dpxwEzw8zsZjQxGZTtzVmPl3DNMOS5QQ0TBU0XXxNQ6C6IQMAfhd2jiHUKVSHGgC0tAMQRL-zo3tnj-b4-lnFOnlHAFDyMRRmMEt9pKwu9-dsYhYvR6vAopgm2PCx2329_xiBGu8lUVt-ceE/w520-h640/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.25.25.png&quot; width=&quot;520&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 &lt;u&gt;ChatGPT&lt;/u&gt; 의 경우 동일 질문에 대한 답으로 CustomAuthenticationEntryPoint 을 구현하는 방법으로 답변&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;✓ 문제를 해결.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpybWW7fmmwgMIDC3ATAV4Pa4nvQNLjAW_0TPaUJVR7WEZmszCjPe_jft6UrFVZpdJpglPjQPC1qcbqvNFhV-uOrgFaxijg2aU_xWNyTyGTZ_vLLoK5HKepg8HNDlOAFV7OAqWKEsZdT7PDXprJHTGgb4y9TuvhAAxdEAF7T7nfSc0Ar_vM2TnjGbZ5XIJ/s1694/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.24.12.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1338&quot; data-original-width=&quot;1694&quot; height=&quot;506&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpybWW7fmmwgMIDC3ATAV4Pa4nvQNLjAW_0TPaUJVR7WEZmszCjPe_jft6UrFVZpdJpglPjQPC1qcbqvNFhV-uOrgFaxijg2aU_xWNyTyGTZ_vLLoK5HKepg8HNDlOAFV7OAqWKEsZdT7PDXprJHTGgb4y9TuvhAAxdEAF7T7nfSc0Ar_vM2TnjGbZ5XIJ/w640-h506/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.24.12.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRaGdddxzGnQvvTLK1GBu0-t4IxX8iRSye0FZAgfX0kPjSyrlYryXn3S_AW8PBIUAlDud6W3CKZ9RQSAlEvq1DUFfcUvzlsblyRlZl3wBlfh3KABFcOw5Nr4_TPXU-4CWx3aihEWmD2asrkwYMmGeigPYh2eeG_JRWpwN7aXJZ72tXb6kbuixSUUepvPZv/s1712/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-18%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.18.57.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1408&quot; data-original-width=&quot;1712&quot; height=&quot;526&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRaGdddxzGnQvvTLK1GBu0-t4IxX8iRSye0FZAgfX0kPjSyrlYryXn3S_AW8PBIUAlDud6W3CKZ9RQSAlEvq1DUFfcUvzlsblyRlZl3wBlfh3KABFcOw5Nr4_TPXU-4CWx3aihEWmD2asrkwYMmGeigPYh2eeG_JRWpwN7aXJZ72tXb6kbuixSUUepvPZv/w640-h526/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-18%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.18.57.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;GitHub Copilot&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. 문서자동화&lt;/span&gt;&lt;/h3&gt;&lt;h4 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;함수 블록 코드를 기반으로 JavaDoc 문서 만들기&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;함수에 문서화를 위하여 JavaDoc 주석 기호를 입력 /** */&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;함수 블록의 코드 로직을 기술 하려면 1. 입력하면 로직 설명을 제시. 순차적으로 2. , 3. 을 입력하여 이어 로직 설명을 제시.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCewyzwRA2QL9XQ0Tj01gTBuI11QJoJONqEjc6BZvL8gXkOLziyEmXeyZpg1w57aMxeYbyEbZtFpHru71eYjXKihJb-uHw6MPDtp6WN4SmoYzmEqgRwS0tzHtkpK0GECPu8sUj8w4Mwxo17JRHAKa3YTcbgGcZv1OLopo8KUeYACRzS0VZRR4bKYH_R1s6/s1746/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.48.07.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1046&quot; data-original-width=&quot;1746&quot; height=&quot;384&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCewyzwRA2QL9XQ0Tj01gTBuI11QJoJONqEjc6BZvL8gXkOLziyEmXeyZpg1w57aMxeYbyEbZtFpHru71eYjXKihJb-uHw6MPDtp6WN4SmoYzmEqgRwS0tzHtkpK0GECPu8sUj8w4Mwxo17JRHAKa3YTcbgGcZv1OLopo8KUeYACRzS0VZRR4bKYH_R1s6/w640-h384/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-15%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.48.07.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;JavaDoc 주석의 첫줄로 이동 공백을 입력하고 기다리면 함수에 대한 요약을 제시.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6jEvNr0w5sQYgkHyc40FhO8np1dkDsqyxyZJHW62Bsjsr2B2vDHJldU2XVYS7OySUrwjffXQEiY-bFimVpu__EqdDPHNN4clVvT_oCUwGtPgzChh-tIu32JbEjiIny1RbHBZh2M9ppX-kJ_4rA99yTecwNVwzq7lJ-VwHFPpIwZdKy8tRK30JltEeWLb7/s1666/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.56.26.png&quot; style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;; margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1472&quot; data-original-width=&quot;1666&quot; height=&quot;566&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6jEvNr0w5sQYgkHyc40FhO8np1dkDsqyxyZJHW62Bsjsr2B2vDHJldU2XVYS7OySUrwjffXQEiY-bFimVpu__EqdDPHNN4clVvT_oCUwGtPgzChh-tIu32JbEjiIny1RbHBZh2M9ppX-kJ_4rA99yTecwNVwzq7lJ-VwHFPpIwZdKy8tRK30JltEeWLb7/w640-h566/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-18%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.56.26.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;h3&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2. 코드 생성&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;소스 코드 기능 개선&lt;/span&gt;&lt;/h4&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🆀&amp;nbsp; alert.value.message.response.data.error.exception 값과 스트링 배열을 비교하여 일치하는 경우 authAtore.loguot () 을 실행하려면 &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;🅰 언어의 특성을 고려하여 비교할 문자열 배열을 정의하고 존재 여부를 검사하여 일치하는 경우 함수를 호출하는 설명과 예제를 제시.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;✓ 참조된 소스가 Vue 언어로 작성된 코드인 것을 확인하여 자바 스크립트 언어 문법으로&amp;nbsp; 정확한 답변을 함&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiARNRTIA1V6B1mfyjiojJWArzN8aMGOOEre9-Z_CeRm8bncvCUudfsiapyW7Y_2DO-lblRjKhzYeXgAX6ixMSGSJAFTkCBH5URM7p3ll7av43Qu7itvPNUWrSfcIiwhLtIXy0rWoc9YGS3lwM18AeGi08YL2_HCpgwuwtFQttqZF7rANJU4B42Zmh1ys75/s1190/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.32.09.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;986&quot; data-original-width=&quot;1190&quot; height=&quot;530&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiARNRTIA1V6B1mfyjiojJWArzN8aMGOOEre9-Z_CeRm8bncvCUudfsiapyW7Y_2DO-lblRjKhzYeXgAX6ixMSGSJAFTkCBH5URM7p3ll7av43Qu7itvPNUWrSfcIiwhLtIXy0rWoc9YGS3lwM18AeGi08YL2_HCpgwuwtFQttqZF7rANJU4B42Zmh1ys75/w640-h530/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.32.09.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/3992522658133560035/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/07/ai.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3992522658133560035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/3992522658133560035'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/07/ai.html' title='사용기 - 생성형 AI 를 이용한 코딩 후기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0qiyfcK-ttwWM4Ukv4sOVXm6LHx0WbS0pq1PxabYaRnY4dpxwEzw8zsZjQxGZTtzVmPl3DNMOS5QQ0TBU0XXxNQ6C6IQMAfhd2jiHUKVSHGgC0tAMQRL-zo3tnj-b4-lnFOnlHAFDyMRRmMEt9pKwu9-dsYhYvR6vAopgm2PCx2329_xiBGu8lUVt-ceE/s72-w520-h640-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.25.25.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-1844954472127446</id><published>2024-07-08T16:13:00.006+09:00</published><updated>2024-07-20T22:04:52.099+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ag-grid"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><category scheme="http://www.blogger.com/atom/ns#" term="spring boot"/><category scheme="http://www.blogger.com/atom/ns#" term="spring jpa"/><category scheme="http://www.blogger.com/atom/ns#" term="Vue3"/><title type='text'>코딩 - Vue3 &amp; Spring : AG-Grid 페이징, 필터 구현하기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;◼︎ 환경&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 13.2.4 (22F66)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : Visual Studio Code, Java 11, Gradle, Docker&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version Control : GitHub&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Java, Vue3&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;Front-End Framework : Vue 3.4.30, Vuetify 3.6.10, ag-grid-vue3 31.3.2&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Back-End Framework : Spring Boot 2.7.12, Spring Security 5.7.7&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DBMS : MySql 8.0.33&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Cloud : OCI (free tier account)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;AG-Grid 을 이용한 그리드 구현&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vue3 에서 AG-Grid 는 다음과 같은 3단계 과정을 통하여 만들 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;① Vue3 용 &lt;u&gt;ag-grid-vue3&lt;/u&gt; 패키지 설치&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;npm install --save ag-grid-vue3&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;② AG-Grid CSS 스타일 추가&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ag-grid-community/styles/ag-grid.css&quot;&lt;/span&gt;; &lt;span style=&quot;color: #6a9955;&quot;&gt;// Mandatory CSS required by the grid&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ag-grid-community/styles/ag-theme-quartz.css&quot;&lt;/span&gt;; &lt;span style=&quot;color: #6a9955;&quot;&gt;// Optional Theme applied to the grid&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;b&gt;③ AG-Grid 설정 &lt;/b&gt;( 그리드를 구현한 vue 파일에서 )&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;code&gt;gridOptions&lt;/code&gt;를 사용하여 그리드의 전반적인 공통 설정을 관리하고, &lt;code&gt;columnDefs&lt;/code&gt;를 사용하여 각 컬럼의 설정을 관리한다. 이를 통해 그리드의 설정을 더 쉽게 체계적으로 관리할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: grey; font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;AgGridVue&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ag-theme-quartz&quot;&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;gridOptions&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;gridOptions&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;columnDefs&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;columnDefs&lt;/span&gt;&quot; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;        &lt;/span&gt;:&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rowData&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;gridData&lt;/span&gt;&quot; &lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        @&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grid-ready&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;onGridReady&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;style&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt;:&lt;span style=&quot;color: #b5cea8;&quot;&gt;600px&lt;/span&gt;;&quot;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;AgGridVue&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;span style=&quot;color: grey; font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;script&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;setup&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;lang&lt;/span&gt;=&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ts&quot;&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ref&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;onMounted&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;vue&#39;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;AgGridVue&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ag-grid-vue3&quot;&lt;/span&gt;; &lt;span style=&quot;color: #6a9955;&quot;&gt;// Vue Data Grid Component&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;type&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;GridApi&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;IGetRowsParams&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;ag-grid-community&#39;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;type&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;GridOptions&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ColDef&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;ag-grid-community&#39;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955; font-family: Nanum Gothic Coding;&quot;&gt;// ag-grid &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;loader&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridData&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;([]);&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridApi&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;GridApi&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;null&lt;/span&gt;&amp;gt;();&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;span style=&quot;color: #6a9955; font-family: Nanum Gothic Coding;&quot;&gt;// ag-grid options for common. &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridOptions&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;GridOptions&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;defaultColDef&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;flex&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;minWidth&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;100&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;resizable&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sortable&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;cellStyle&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #9cdcfe;&quot;&gt;display&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;flex&#39;&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #9cdcfe;&quot;&gt;alignItems&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;center&#39;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;columnTypes&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;agTextColumnFilter&#39;&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filterParams&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;suppressAndOrCondition&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;cellStyle&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;textAlign&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;center&#39;&lt;/span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;number&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;agNumberColumnFilter&#39;&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filterParams&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;suppressAndOrCondition&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;cellStyle&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;textAlign&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;right&#39;&lt;/span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955; font-family: Nanum Gothic Coding;&quot;&gt;// define grid coloums&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;columnDefs&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; [&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;groupId&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headerName&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;ID&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;number&#39;&lt;/span&gt;, &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;      width&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;100&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sortable&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt; },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;name&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headerName&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;Name&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sortable&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt; , &lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;text&quot;&lt;/span&gt;, &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;      flex&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;3&lt;/span&gt; , &lt;span style=&quot;color: #4ec9b0;&quot;&gt;cellRenderer&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt; :&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;GroupCellRenderer&lt;/span&gt;}, // 사용자 정의 셀 렌더러.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;description&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headerName&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;Description&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;string&#39;&lt;/span&gt;, &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;      width&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;50&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sortable&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt; , &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;];&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;onGridReady&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; { &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridApi&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;gridOptions : 그리드의 전반적인 설정을 정의.  (defaultColDef, rowData, paginationPageSize, cacheBlockSize, rowSelection, getRowHeight 등)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;columnDefs: 각 컬럼의 설정을 정의. 각 컬럼에 대해 headerName, field, sortable, filter, cellStyle, cellRenderer 등을 설정. &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;rowData: 그리드에 표시할 데이터를 설정.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;onGridReady:  그리드가 준비되면 gridApi 인스턴스을 저장하여 그리드 제어에 사용&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;h3&gt;서버 사이드 페이징&lt;/h3&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버 사이드 페이징 기능을 사용하지 않는 경우라면 간단하게 아래와 같이 rowData 에 해당하는 gridData 객체에 데이터를 강제로 주입해주기만 하면 쉽게 구현이 가능하지만 페이지, 필터, 소팅 등의 기능들을 서버에서 처리하는 것은 조금 더 많은 수고가 필요하다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;onMounted&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; () &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span class=&quot;hljs-title function_&quot;&gt;fetch&lt;/span&gt;(&lt;span class=&quot;hljs-string&quot;&gt;`https://api.example.com/data`&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    .&lt;span class=&quot;hljs-title function_&quot;&gt;then&lt;/span&gt;(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;response&lt;/span&gt; =&amp;gt;&lt;/span&gt; response.&lt;span class=&quot;hljs-title function_&quot;&gt;json&lt;/span&gt;())
    .&lt;span class=&quot;hljs-title function_&quot;&gt;then&lt;/span&gt;(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;data&lt;/span&gt; =&amp;gt;&lt;/span&gt; {
        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridData&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data.rows&lt;/span&gt;;
     })
     .&lt;span class=&quot;hljs-title function_&quot;&gt;catch&lt;/span&gt;(&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-params&quot;&gt;error&lt;/span&gt; =&amp;gt;&lt;/span&gt; {
         c&lt;span class=&quot;hljs-variable language_&quot;&gt;onsole&lt;/span&gt;.&lt;span class=&quot;hljs-title function_&quot;&gt;error&lt;/span&gt;(error);
     });&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;});&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;유료 버전을 사용하는 경우라면 &lt;u&gt;gridOptions&lt;/u&gt; 의 rowModelType 값을 &#39;serverSide&#39; 로 변경하고 추가로 datasource 를 설정하면 쉽게 구현이 되는것으로 보이지만 무료 커뮤니티 버전은 좀더 복잡한 과정을 진행해야 한다.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;rowModelType&lt;/u&gt; 은 그리드가 데이터를 로드하고 관리하는 방식을 결정한다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;AG&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;-Grid는 다양한 데이터 로딩 및 관리 요구를 충족시키기 위해 여러 가지 rowModelType을 제공하며, 각 타입은 특정 사용 사례에 최적화되어 있다. 무료 버전에서 서버 사이드 페이징을 구현하려면 rowModelType 값을 &lt;u&gt;&lt;b&gt;infinite&lt;/b&gt;&lt;/u&gt; 을 사용하여 구현해야 한다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgn4w4PUCGekH_uSiI8tqo1Wp9R2TNrVdetP997eRi7etHZSrVRYn-6BkOujBA2tRTEpSrxtc775JrHuDm0894S9LC2l1sDsRlX4l83MZuG9eqdfLm5Q3Ywh07qoBLwhgM_TG0j55u1jzdtC01WD7SEDBOhb0C7IJHggc9dlVZhGC3rKkT4zRxb0li9LfQ7&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;272&quot; data-original-width=&quot;610&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgn4w4PUCGekH_uSiI8tqo1Wp9R2TNrVdetP997eRi7etHZSrVRYn-6BkOujBA2tRTEpSrxtc775JrHuDm0894S9LC2l1sDsRlX4l83MZuG9eqdfLm5Q3Ywh07qoBLwhgM_TG0j55u1jzdtC01WD7SEDBOhb0C7IJHggc9dlVZhGC3rKkT4zRxb0li9LfQ7=s16000&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt; &lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;AgGridVue&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;class&lt;/span&gt;=&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;ag-theme-quartz&quot;&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rowModelType&lt;/span&gt;=&quot;&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;infinite&#39;&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;gridOptions&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;gridOptions&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;columnDefs&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;columnDefs&lt;/span&gt;&quot; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;pagination&lt;/span&gt;=&quot;&lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;&quot; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;paginationPageSize&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;pageSize&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     :&lt;span style=&quot;color: #9cdcfe;&quot;&gt;cacheBlockSize&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;cacheBlockSize&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     @&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grid-ready&lt;/span&gt;=&quot;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;onGridReady&lt;/span&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;     &lt;span style=&quot;color: #9cdcfe;&quot;&gt;style&lt;/span&gt;=&quot;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt;:&lt;span style=&quot;color: #b5cea8;&quot;&gt;600px&lt;/span&gt;;&quot;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;AgGridVue&lt;/span&gt;&lt;span style=&quot;color: grey;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;span style=&quot;color: grey;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;페이징 기능을 사용하기 위하여 아래와 같은 설정을 추가한다. 가독성을 고려하여&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;gridOptions 에 추가하지 않고 AgGridVue 의 개별 속성 값을 직접 설정하는&amp;nbsp; 방식을 사용했다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;pagination&lt;/b&gt; :&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;그리드에서 페이징 기능을 사용할지를 결정하는 옵션. 기본적으로 pagination 속성을 true로 설정하면 페이징이 활성화된다. 페이징이 활성화되면 그리드는 한 번에 일정한 수의 행만 표시하고, 사용자가 페이지를 전환할 수 있도록 페이지 내비게이션 컨트롤을 제공한다.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;paginationPageSize&lt;/b&gt; :&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;한 페이지에 표시할 행(row)의 수를 설정하는 옵션. 이 속성을 설정하면 사용자가 그리드 페이지를 전환할 때마다 이 수만큼의 행이 표시되며 기본값은 100이다. (&lt;span style=&quot;color: red;&quot;&gt;참고로 서버에서 데이터를 페이징하여 가져오는 값과는 구분된다.&lt;/span&gt;)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;b&gt;cacheBlockSize&lt;/b&gt;&amp;nbsp;:&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;infinite 또는 serverSide row model을 사용할 때 한 번에 서버에서 가져올 데이터의 블록 크기를 설정하는 옵션. 이 속성은 서버에서 데이터를 페이징 방식으로 가져올 때 유용하며 기본값은 100이다. (&lt;span style=&quot;color: red;&quot;&gt;-&amp;gt; 서버에 전달하는 페이징 크기 값&lt;/span&gt;)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;span&gt;이제 데이터를 가져오는&amp;nbsp;&lt;/span&gt;datasource&amp;nbsp;에 대한 코딩이 필요하다.&amp;nbsp;datasource 설정은 유연성을 고려하여 onGridReady 이벤트에서 설정한다. 주의할 것은 이벤트에서 인자로 전달되는 params 값을 사용하여 페이지 정보를 서버에 전달해야 하는 점이다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortString&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;SortModelItem&lt;/span&gt;[] ) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;( &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt; ) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;].&lt;span style=&quot;color: #9cdcfe;&quot;&gt;colId&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;,&#39;&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;].&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;  &lt;span style=&quot;color: #d4d4d4;&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;&#39;&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;toUpperCase&lt;/span&gt;(); &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;onGridReady&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; { &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridApi&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #dcdcaa;&quot;&gt;getRows&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;IGetRowsParams&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;Math&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;floor&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;startRow&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;pageSize&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;pageSizeValue&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;endRow&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;startRow&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filterModel&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filterModel&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;sortModel&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sortModel&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #c586c0;&quot;&gt;try&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setSort&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;sortModel&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setFilter&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filterModel&lt;/span&gt;); &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setPage&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filtersActive&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Object&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;keys&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filterModel&lt;/span&gt;).&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;line-height: 18px;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;axios&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;post&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;`https://api.example.com/data`&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;JSON&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;stringify&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filterModel&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                    {  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                       &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                           &lt;span style=&quot;color: #9cdcfe;&quot;&gt;page&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                           &lt;span style=&quot;color: #9cdcfe;&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;cacheBlockSize&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                           &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortString&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;sortModel&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                      },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                    },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridData&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;total&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;totalElements&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;successCallback&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridData&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;, &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;totalElements&lt;/span&gt; );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;).&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;error&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;console&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;error&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;}); &lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;successCallback&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridData&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;, &lt;span style=&quot;color: #4fc1ff;&quot;&gt;total&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            } &lt;span style=&quot;color: #c586c0;&quot;&gt;catch&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;error&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;failCallback&lt;/span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;                &lt;span style=&quot;color: #9cdcfe;&quot;&gt;console&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;error&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    };&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;setGridOption&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;datasource&#39;&lt;/span&gt;, &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataSource&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;};&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Menlo, Monaco, Courier New, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;위의 예는 서버에 post 방식으로 sorting, paging, filter 정보를 전달하고 있는데 Spring JPA 를 사용하고 있다면 아주 쉽게 서버 프로그램을 만들어 볼 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;추가로 서버에 데이터를 전송할 때에&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;Map 형식의&amp;nbsp; AG-Grid 필터값을 객체 배열로 변환하고 필터 타입을 약어로 변경하여 서버로 전송하도록 아래와 같은 변환 함수를 사용 변환하여 전송했다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convertAgGridFilterToServerFormat&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;agFilterModel&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;kendoFilters&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Object&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;keys&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;agFilterModel&lt;/span&gt;).&lt;span style=&quot;color: #dcdcaa;&quot;&gt;map&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;colId&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;agFilterModel&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;colId&lt;/span&gt;];&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;switch&lt;/span&gt; (&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filterType&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;text&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convertNumberFilterType&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;number&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convertNumberFilterType&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;boolean&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;eq&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;date&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convertNumberFilterType&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;);;&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;default&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;eq&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;colId&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;operator&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    };&lt;/div&gt;&lt;div&gt;  });&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;logic&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;and&#39;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filters&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;kendoFilters&lt;/span&gt;&lt;/div&gt;&lt;div&gt;  };&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;// 숫자 필터 타입 변환 함수&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convertNumberFilterType&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;  &lt;span style=&quot;color: #c586c0;&quot;&gt;switch&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;) {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;equals&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;eq&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;notEqual&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;ne&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;lessThan&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;lt&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;lessThanOrEqual&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;lte&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;greaterThan&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;gt&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;greaterThanOrEqual&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;gte&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;case&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;contains&#39;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;contains&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;default&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;eq&#39;&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;  }&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;아래는 별도의 store 객체로 분리하여 서버 통신 모듈을 구성한 예이다.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Apple SD Gothic Neo&amp;quot;;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;API_HEADERS&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;authHeader&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;convertAgGridFilterToKendo&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;@/util/helpers&quot;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;axios&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;axios&quot;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;defineStore&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;pinia&quot;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;computed&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ref&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;vue&quot;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;useAlertStore&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;../../alert.store&quot;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;GroupModel&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;@/types/models/GroupModel&quot;&lt;/span&gt;; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;type&lt;/span&gt; { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;SortModelItem&lt;/span&gt; } &lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;ag-grid-community&#39;&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt; &lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;export&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;usePageableGroupsStore&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;defineStore&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;pageable-groups-store&quot;&lt;/span&gt;, () &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// error state store&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;alertStore&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;useAlertStore&lt;/span&gt;();&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// state&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;isLoaded&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;boolean&lt;/span&gt;&amp;gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;GroupModel&lt;/span&gt;[]&amp;gt;([]);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// pageable&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;total&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;&amp;gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;&amp;gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;pageSize&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;&amp;gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;20&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;SortModelItem&lt;/span&gt;[]&amp;gt;([]);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;ref&lt;/span&gt;({ &lt;span style=&quot;color: #9cdcfe;&quot;&gt;logic&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;and&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filters&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt;[] });&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// getters&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;getById&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;computed&lt;/span&gt;(() &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;find&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;===&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  });&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;getByName&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;computed&lt;/span&gt;(() &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;string&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;find&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;===&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  });&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// setters &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setSort&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;newValue&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;SortModelItem&lt;/span&gt;[]) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;newValue&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setFilter&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;newValue&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convertAgGridFilterToKendo&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;newValue&lt;/span&gt;) ;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setPage&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;newVal&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;)&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;void&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;===&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;newVal&lt;/span&gt;) &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;newVal&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;isLoaded&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #6a9955;&quot;&gt;// actions&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;loadById&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;number&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;API_HEADERS&lt;/span&gt;, &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;() };&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;axios&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;get&lt;/span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/groups/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      )&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      })&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; { &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;alertStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;category&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveOrUpdate&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;GroupModel&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;isNew&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;===&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;API_HEADERS&lt;/span&gt;, &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;() };&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;axios&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;post&lt;/span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/groups/&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupId&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;JSON&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;stringify&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        { &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      )&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;isLoaded&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      })&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; { &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;alertStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortString&lt;/span&gt; () {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;( &lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt; ) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortField&lt;/span&gt;() &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;,&#39;&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortDir&lt;/span&gt;()&lt;span style=&quot;color: #d4d4d4;&quot;&gt;||&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;&#39;&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;toUpperCase&lt;/span&gt;(); &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;   &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortField&lt;/span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;].&lt;span style=&quot;color: #9cdcfe;&quot;&gt;colId&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortDir&lt;/span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;sort&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;].&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt; ;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;pagableParams&lt;/span&gt;(){&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;page&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;page&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;pageSize&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sort&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sortString&lt;/span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;filterParams&lt;/span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;var&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {};&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; (&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filters&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filters&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;forEach&lt;/span&gt;( &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      }) &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    } &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #569cd6;&quot;&gt;async&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;function&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;fetch&lt;/span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;API_HEADERS&lt;/span&gt;, &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;authHeader&lt;/span&gt;() };&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt;( &lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filters&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;length&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;){&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;axios&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;post&lt;/span&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/groups:find`&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;JSON&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;stringify&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;         {  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;            &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;pagableParams&lt;/span&gt;(),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;total&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;totalElements&lt;/span&gt;; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;content&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;forEach&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;push&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;isLoaded&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        }).&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;( &lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #4fc1ff;&quot;&gt;alertStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;); &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        }); &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;span style=&quot;color: #c586c0;&quot;&gt;else&lt;/span&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      &lt;span style=&quot;color: #c586c0;&quot;&gt;await&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;axios&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;get&lt;/span&gt;( &lt;span style=&quot;color: #ce9178;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;meta&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;VITE_API_URL&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;/data/secure/mgmt/security/groups`&lt;/span&gt;, { &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #d4d4d4;&quot;&gt;...&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;pagableParams&lt;/span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;headers&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;headers&lt;/span&gt; })&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;then&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;response&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; [];&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;total&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;totalCount&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;items&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;forEach&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;          &lt;span style=&quot;color: #4fc1ff;&quot;&gt;dataItems&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;push&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;item&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;isLoaded&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;true&lt;/span&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      })&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      .&lt;span style=&quot;color: #dcdcaa;&quot;&gt;catch&lt;/span&gt;((&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #4fc1ff;&quot;&gt;alertStore&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;error&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;err&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;      });&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;isLoaded&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;dataItems&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;total&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;page&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;pageSize&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;getById&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;getByName&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setFilter&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;loadById&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;fetch&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveOrUpdate&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setPage&lt;/span&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;setSort&lt;/span&gt;, &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;  };&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;});&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Menlo, Monaco, Courier New, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitQQce-X5j3_dtE0Uvi0DEtSEgI6w2WiaPATC5_3ZammzQJ4IHJG3xfm-mi_8AHLPl82sEn43j-cc70WG1izgmrrMedLvnI0TQB3KbYRy_uUeSEZxb8oj79k856rW6f03otumKK8YyFyCNWvNsSYeh7JyKInk983didq6vjl9AZNVx5LmHZQFPgWqtmzAC/s1117/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-20%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.04.01.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;630&quot; data-original-width=&quot;1117&quot; height=&quot;360&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitQQce-X5j3_dtE0Uvi0DEtSEgI6w2WiaPATC5_3ZammzQJ4IHJG3xfm-mi_8AHLPl82sEn43j-cc70WG1izgmrrMedLvnI0TQB3KbYRy_uUeSEZxb8oj79k856rW6f03otumKK8YyFyCNWvNsSYeh7JyKInk983didq6vjl9AZNVx5LmHZQFPgWqtmzAC/w640-h360/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-07-20%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.04.01.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;서버 프로그램&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Vue 프로그램에서 요청을 처리하기 위한 서버 프로그램은 스프링 컨트롤러를 이용하여 코딩하면 된다. 아래 컨트롤러 예제는 페이징과 소팅 값은 파라메터 형태로&amp;nbsp; 필터 값은 바디 형태로 바인딩 하고 있다. (-&amp;gt; 페이징 및 소팅은 Spring 에서 제공하는 Pageable 을 활용하여 바인딩)&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;PostMapping&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;/data&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;produces&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;MediaType&lt;/span&gt;.&lt;span style=&quot;color: #4fc1ff;&quot;&gt;APPLICATION_JSON_VALUE&lt;/span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    &lt;span style=&quot;color: #569cd6;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Page&lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Group&lt;/span&gt;&amp;gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;findGroups&lt;/span&gt;(@&lt;span style=&quot;color: #4ec9b0;&quot;&gt;RequestBody&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;FilterModel&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;, @&lt;span style=&quot;color: #4ec9b0;&quot;&gt;PageableDefault&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;size&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;100&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;sort&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;userId&quot;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;direction&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Sort&lt;/span&gt;.&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Direction&lt;/span&gt;.&lt;span style=&quot;color: #4fc1ff;&quot;&gt;DESC&lt;/span&gt;) &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Pageable&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;pageable&lt;/span&gt;) { &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;        &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;groupService&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;findGroups&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;filter&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getFilters&lt;/span&gt;(), &lt;span style=&quot;color: #9cdcfe;&quot;&gt;pageable&lt;/span&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;필터는 별도의 필터 클래스를 정의하여 사용한다. 위 코드에서 groupService 는&amp;nbsp; 에 해당하는 소스는 데이터베이스에서 데이터를 조회하기 위하여&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;JPA Repositry 을 기반으로 하는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;GroupRepository 을 호출하게 된다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;GroupRepository 클래스는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;필터에 따른 동적 쿼리를 지원하기 위하여 JpaRepository 와 JpaSpecificationExecutor 을 상속 받도록 한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;Nanum Gothic&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;groupService 서비스 클래스는 ⑴ &lt;u&gt;필터 객체(FilterModel) 배열과 페이징(Pageable) 객체&lt;/u&gt;를 인자로 받아&amp;nbsp; ⑵ &lt;u&gt;Specification 객체를 생성&lt;/u&gt;하고 ⑶ &lt;u&gt;Repository 객체의 findAll 함수를 호출&lt;/u&gt;하여 Page 형식으로 데이터를 응답받아 리턴하는 형태로 구현한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;


&lt;div style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/donghyuck/27eb87a33591f5fb372950416484ea44.js&quot;&gt;&lt;/script&gt;



</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/1844954472127446/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/07/vue3-spring-ag-grid.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1844954472127446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/1844954472127446'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/07/vue3-spring-ag-grid.html' title='코딩 - Vue3 &amp; Spring : AG-Grid 페이징, 필터 구현하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEgn4w4PUCGekH_uSiI8tqo1Wp9R2TNrVdetP997eRi7etHZSrVRYn-6BkOujBA2tRTEpSrxtc775JrHuDm0894S9LC2l1sDsRlX4l83MZuG9eqdfLm5Q3Ywh07qoBLwhgM_TG0j55u1jzdtC01WD7SEDBOhb0C7IJHggc9dlVZhGC3rKkT4zRxb0li9LfQ7=s72-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-6529881178828828038</id><published>2024-06-26T14:57:00.002+09:00</published><updated>2024-10-28T16:25:57.446+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ag-grid"/><category scheme="http://www.blogger.com/atom/ns#" term="Vue3"/><category scheme="http://www.blogger.com/atom/ns#" term="vuetify 3"/><title type='text'>코딩 - Vue3 : AG-Grid 사용하기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;span&gt;◼︎ 환경&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (14-inch, 2021)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : Apple M1 Pro&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 512 GB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS 13.2.4 (22F66)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;TOOLS : Visual Studio Code, Java 11, Gradle, Docker&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Version Control : GitHub&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Programming Language : Java, Vue3&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;u&gt;Front-End Framework : Vue 3.4.30, Vuetify 3.6.10, ag-grid-vue3 31.3.2&lt;/u&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Back-End Framework : Spring Boot 2.7.12, Spring Security 5.7.7&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DBMS : MySql 8.0.33&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Cloud : OCI (free tier account)&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;Kendo UI 을 이용했지만 1년 단위 개발자 라이선스가 부담이 되어 Vue 3에서 사용할 수 있는 그리드들 중에서 AG Grid Community 무료 버전을 사용해보기로 했다.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://www.ag-grid.com/&quot; target=&quot;_blank&quot;&gt;AG Grid Community&lt;/a&gt;는 필터링, 정렬, 그룹핑 등 다양한 기능을 제공하며 대규모&amp;nbsp;데이터 처리에 특히 유용하다. 추가로 무료로 제공되기 때문에 많은 프로젝트에서 널리 사용된다고 한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bkl6r3fM8EBXHZ-Sb9VWNorqRHB7GCt3rvr2b9FUyZtFwVg_SxOh9IYQbBgXW7DZMxPmoituEXQ_anHRLWe6a19WIde4zt8jKzMQJjPNUdx5UNheSqOM8xJoup0KWme9zEh1zxzcULtJZvkObu1RwXtjtuBSBr1s-uOkW_k9LV7mW02aQyTpDQ5KadiX/s2972/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-06-26%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.03.27.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1612&quot; data-original-width=&quot;2972&quot; height=&quot;348&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bkl6r3fM8EBXHZ-Sb9VWNorqRHB7GCt3rvr2b9FUyZtFwVg_SxOh9IYQbBgXW7DZMxPmoituEXQ_anHRLWe6a19WIde4zt8jKzMQJjPNUdx5UNheSqOM8xJoup0KWme9zEh1zxzcULtJZvkObu1RwXtjtuBSBr1s-uOkW_k9LV7mW02aQyTpDQ5KadiX/w640-h348/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-06-26%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.03.27.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1. 설치하기&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;설치는 간단하게 아래 명령을 사용하여 패키지를 설치할 수 있다. 사용하는 것 역시 별도의 설정이 없어도 바로 사용할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic Coding;&quot;&gt;&lt;pre class=&quot;code language-bash&quot; style=&quot;--class-name-color: #0e4491; --color-code-background: color-mix(in srgb, var(--color-bg-secondary), var(--color-bg-primary) 70%); --comment-color: #5d6376; --deleted-color: #f54946; --function-color: #393a34; --important-color: #e90; --keyword-color: #b31ea7; --property-color: #2ea248; --punctuation-color: #393a34; --selector-color: #0e4491; --string-color: #c33c3a; --symbol-color: #0e4491; --tag-color: #984f4e; background-attachment: initial; background-clip: initial; background-image: none; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-radius: var(--radius-md); border: 1px solid color-mix(in srgb,var(--color-border-secondary),var(--color-border-primary)); box-sizing: border-box; font-size: 15px; hyphens: none; line-height: 1.5; margin-bottom: 16px; margin-top: 0px; overflow-wrap: normal; overflow: visible auto; padding: 0px; position: relative; tab-size: 4; word-break: normal;&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot; style=&quot;background-attachment: local; background-clip: initial; background-image: none; background-origin: content-box; background-position: initial; background-repeat: initial; background-size: 3em 3em; border-radius: 0px; border: none; box-sizing: border-box; color: var(--function-color); display: inline-block; hyphens: none; line-height: 1.5; margin: 0px 0px -6px; min-width: 100%; overflow-wrap: normal; overflow-x: auto; padding: 10px 16px 8px; position: relative; tab-size: 4; word-break: normal; word-spacing: normal;&quot;&gt;&lt;span class=&quot;token function&quot; color=&quot;var(--function-color)&quot; style=&quot;box-sizing: border-box; margin: 0px;&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot; color=&quot;var(--function-color)&quot; style=&quot;box-sizing: border-box; margin: 0px;&quot;&gt;install&lt;/span&gt; --save ag-grid-vue3 &lt;/code&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;가장 힘들었던 부분이 특정 컬럼(셀)에 사용자 정의 렌더러을 지정하여 버튼들을 그리고 해당 버튼을 클릭하면 해당 이벤트에 따라 저장/삭제 동작을 구현하는 것이었다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUbQRbn-AhZDpsB6iEZpu-o1NAi-Y47ksKMkQ8Ep1G44pRDbCcJfrhzIkJWhpTMN2buPqvCqxIDq27w7la7d8QACjrf4D2xz1TvpY1zz7MtD6qM0UlI532Q0zVWYdKnd3DUu_JUdPUzGDRKChgAt-uIXrvEeJwAYwOjiZUohe1jMe9sT6brfCfmidMZv5O/s2362/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-06-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.34.43.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1230&quot; data-original-width=&quot;2362&quot; height=&quot;334&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUbQRbn-AhZDpsB6iEZpu-o1NAi-Y47ksKMkQ8Ep1G44pRDbCcJfrhzIkJWhpTMN2buPqvCqxIDq27w7la7d8QACjrf4D2xz1TvpY1zz7MtD6qM0UlI532Q0zVWYdKnd3DUu_JUdPUzGDRKChgAt-uIXrvEeJwAYwOjiZUohe1jMe9sT6brfCfmidMZv5O/w640-h334/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-06-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.34.43.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Actions 에 해당 하는 셀은&lt;/span&gt;&amp;nbsp;ActionCellRenderer.vue 만들어 구현을 했다. 문제는 row 데이터에 따라 버튼을 제어(&lt;span&gt;&amp;nbsp;노출/숨김) 하고 클릭시 이벤트를 받아 서버 통신을 통해서 삭제/저장을 구현하는 화면을 구현하려고 했다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;1) &lt;u&gt;defineProps&lt;/u&gt; 함수를 사용하여 전달된 params 값을 바인딩 하려고 했으나 이부분이 해결되지 않아 params 을 직접 접근하는 방식으로 코드를 작생했다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;props&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;defineProps&lt;/span&gt;&amp;lt;{&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;?:&lt;/span&gt; { [&lt;span style=&quot;color: #9cdcfe;&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;string&lt;/span&gt;]&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt; };&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;?:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;?:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; { [&lt;span style=&quot;color: #9cdcfe;&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;string&lt;/span&gt;]&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt; };&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;        &lt;span style=&quot;color: #9cdcfe;&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;    }&lt;/div&gt;&lt;div&gt;}&amp;gt;();&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt; &lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2) 버튼을 클릭하면&amp;nbsp;&lt;/span&gt;&lt;u&gt;defineEmits&lt;/u&gt; 사용하여 정의한 이벤트를 발생하는 것으로 코드를 만들었지만 부모 즉 ag-grid 구현 화면에 해당 이벤트를 전달하는 방법을 찾지 못해 prams.api 로 전달되는&amp;nbsp;&lt;u&gt;GridApi.dispatchEvent()&lt;/u&gt; 함수를 사용했다.&amp;nbsp; (-&amp;gt; 이부분을 알아내는 것이 가장 힘들었던 것 같다)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;saveRow&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; () &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;props&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;dispatchEvent&lt;/span&gt;({&lt;/div&gt;&lt;div&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;actionCellRenderer:save&#39;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;props&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    });&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;deleteRow&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; () &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #dcdcaa;&quot;&gt;emits&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;delete&#39;&lt;/span&gt;, &lt;span style=&quot;color: #4fc1ff;&quot;&gt;props&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;props&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;dispatchEvent&lt;/span&gt;({&lt;/div&gt;&lt;div&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;actionCellRenderer:delete&#39;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;            &lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;props&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;&lt;/div&gt;&lt;div&gt;    });&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;GridApi.dispatchEvent()&lt;/u&gt; 함수를 사용하여 전달된 이벤트를 ga-grid 화면을 그리는 페이지에서 받기 위해서는 GridApi.addEventListener() 함수를 사용하여 리스트너를 등록해줘야 한다.&amp;nbsp;&amp;nbsp;@grid-ready=&quot;onGridReady&quot; 구문을 사용해서 grid 가 준비됨을 알리는 이벤트가 발생하면 onGridReady 를 실행하고 해당 코드에서 리스트너를 등록했다.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; line-height: 18px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;onGridReady&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;:&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;any&lt;/span&gt;) &lt;span style=&quot;color: #569cd6;&quot;&gt;=&amp;gt;&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridApi&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;params&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;api&lt;/span&gt;; &lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridApi&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;addEventListener&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;actionCellRenderer:save&#39;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;handleSave&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;    &lt;span style=&quot;color: #4fc1ff;&quot;&gt;gridApi&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;addEventListener&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;actionCellRenderer:delete&#39;&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;handleDelete&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;아래는 관련된 소스이다.&lt;/div&gt;
  &lt;div&gt;&lt;br /&gt;&lt;/div&gt;

&lt;script src=&quot;https://gist.github.com/donghyuck/1c84c6e88be04921471af29884de58d5.js&quot;&gt;&lt;/script&gt;
&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
  
  &lt;h3 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;참고자료&lt;/span&gt;&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;a href=&quot;https://www.ag-grid.com/vue-data-grid/getting-started/&quot; target=&quot;_blank&quot;&gt;Vue Data Grid Quick Start&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/6529881178828828038/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/06/vue3-ag-grid.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/6529881178828828038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/6529881178828828038'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/06/vue3-ag-grid.html' title='코딩 - Vue3 : AG-Grid 사용하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9bkl6r3fM8EBXHZ-Sb9VWNorqRHB7GCt3rvr2b9FUyZtFwVg_SxOh9IYQbBgXW7DZMxPmoituEXQ_anHRLWe6a19WIde4zt8jKzMQJjPNUdx5UNheSqOM8xJoup0KWme9zEh1zxzcULtJZvkObu1RwXtjtuBSBr1s-uOkW_k9LV7mW02aQyTpDQ5KadiX/s72-w640-h348-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-06-26%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.03.27.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-483639015604758145.post-5356149879163883324</id><published>2024-05-27T14:05:00.003+09:00</published><updated>2024-05-27T14:05:47.386+09:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Paragon Partition Manager"/><category scheme="http://www.blogger.com/atom/ns#" term="VMware Fusion"/><title type='text'>사용기 - VMware Fusion 기반 윈도우에서 디스크 공간 확장하기</title><content type='html'>&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;VMware Fusion 기반 가상 윈도우를 &lt;u&gt;60GB&lt;/u&gt; 용량에 설치하여 사용 하고 있었다.&lt;/span&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;◼︎ 작업환경&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;Model : MacBook Pro (16-inch, 2019)&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;CPU : 2.3 GHz 8코어 Intel Core i9&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;GPU : AMD Radeon Pro 5500M 4 GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;MENORY : 16GB&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;DISK : 1TB SSD&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;OS : macOS Ventura 13.0.1&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2do8cPRnmdKW3F_uGBwtC1iBjVgZu5sqM7LM4fHPrWtOzp9KfrM4SQdyCfc49AOL8Dgug3C3o2KM3cE3A-uqTwBooCBqL0XUjq3rUxEkCZkb4hqaMh4XfvFe4jGzAM1P11yVvCZK_JvRytk91_C_5eyKwYGp5acOp3inY7lxgl33iocEfvAEvnJbww5_L/s1504/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-02-05%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.24.08.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1290&quot; data-original-width=&quot;1504&quot; height=&quot;548&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2do8cPRnmdKW3F_uGBwtC1iBjVgZu5sqM7LM4fHPrWtOzp9KfrM4SQdyCfc49AOL8Dgug3C3o2KM3cE3A-uqTwBooCBqL0XUjq3rUxEkCZkb4hqaMh4XfvFe4jGzAM1P11yVvCZK_JvRytk91_C_5eyKwYGp5acOp3inY7lxgl33iocEfvAEvnJbww5_L/w640-h548/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-02-05%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.24.08.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;사용하다보니 얼마 전부터 용량이 부족하다는 메시지와 이로 기인한 가상머신이 먹통이 되는 현상이 빈번하게 발생하고 있었다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;가상 머신에 OS 재설치 또는 복제 등의 번거로움 없이 가장 쉽게 하는 방법은 디스크 파티션 관리자 소프트웨어를 사용하는 것이다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;여러 가지 프로그램들이 있겠지만 비상업적인 용도로 무료 사용이 가능한 &lt;a href=&quot;https://www.paragon-software.com/free/pm-express/&quot; target=&quot;_blank&quot;&gt;Paragon Partition Manager&lt;/a&gt; 커뮤니티 에디션을 설치하여 쉽게 파티션을 조정 할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3e2mTKM4pIvE1QZuZvWe9oMZwqV3SJ0ZQ2lPkiF9jyfL6qCd0LrkjwuwKdgZa6AWXheHYnLQzLHRl8kbZrXEB0bSO3cBqji8PUJAe5m75tNh6EUa7n1DPsfIpQM1pr3luYSv4O15IOuULtI4FjJJdCz_-a1nfvniAzJW2gSPvn9Su_fl_ZvXunJW5Qwp0/s2284/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-05-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.58.51.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1536&quot; data-original-width=&quot;2284&quot; height=&quot;269&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3e2mTKM4pIvE1QZuZvWe9oMZwqV3SJ0ZQ2lPkiF9jyfL6qCd0LrkjwuwKdgZa6AWXheHYnLQzLHRl8kbZrXEB0bSO3cBqji8PUJAe5m75tNh6EUa7n1DPsfIpQM1pr3luYSv4O15IOuULtI4FjJJdCz_-a1nfvniAzJW2gSPvn9Su_fl_ZvXunJW5Qwp0/w400-h269/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-05-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.58.51.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;1) 가상머신의 하드디스크 크기는 먼저 가상머신을 종료하고 &lt;u&gt;Settings&lt;/u&gt; &amp;gt;&lt;u&gt; Hard Disk&lt;/u&gt; 메뉴에서 크기를 조정할 수 있다.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPRWE-DbWu_FrlrF9c1R59mdqkitJ3vm3d01soHTPAE6ew0pSLKI9mrP_AYtaHQOZkF-Wh57iUNdJi54sqo760vCNfRjgFwJP0_wNy38DIg3X5bpn-V7sojJsLH2J7_xos8MFAvCCyyrKwAJX5xxs3Sr2YD-Qwdr3Y39f-QM_Xs4ci7N1Cvl7wid61vVx0/s1026/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-05-27_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_36_31.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;668&quot; data-original-width=&quot;1026&quot; height=&quot;260&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPRWE-DbWu_FrlrF9c1R59mdqkitJ3vm3d01soHTPAE6ew0pSLKI9mrP_AYtaHQOZkF-Wh57iUNdJi54sqo760vCNfRjgFwJP0_wNy38DIg3X5bpn-V7sojJsLH2J7_xos8MFAvCCyyrKwAJX5xxs3Sr2YD-Qwdr3Y39f-QM_Xs4ci7N1Cvl7wid61vVx0/w400-h260/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-05-27_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_36_31.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSA3vVUn1IXOZWphixh3zhBBw7EVvw3takAcDm990PThSjSkAC4d71RaswgHeOU2KmVBRdxq4AgoYpzmA5DDC92XpkJrP7uMHGnuV_XFIR1LEedRk6zNYQTzHVyHMrSybQbhKNjuXGTir3rD3Ekj9besi_-Yp0Jyr7Q2HN4YgwN2So1OQTRBJ9aWaz8wxU/s650/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-05-27_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_38_10.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;393&quot; data-original-width=&quot;650&quot; height=&quot;241&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSA3vVUn1IXOZWphixh3zhBBw7EVvw3takAcDm990PThSjSkAC4d71RaswgHeOU2KmVBRdxq4AgoYpzmA5DDC92XpkJrP7uMHGnuV_XFIR1LEedRk6zNYQTzHVyHMrSybQbhKNjuXGTir3rD3Ekj9besi_-Yp0Jyr7Q2HN4YgwN2So1OQTRBJ9aWaz8wxU/w400-h241/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2024-05-27_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_1_38_10.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxwPGHme3Cvr6gcJGQkXTAL7G19hY5HrhetweUd8EAHqXFf8GRRgU119spWzeOorc5SxGaJofLf3_K8GazCDIoNrPvUNtKjbeKYQwMC-nKEEhFffcMeTMgHVOvL2yspQ0JOjich5lq91Uz770JWQvBMHwHurVbBJyz3CEZWGB4RZAyj_M8R53OoEqLvRpi/s650/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-05-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.44.52.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;203&quot; data-original-width=&quot;650&quot; height=&quot;125&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxwPGHme3Cvr6gcJGQkXTAL7G19hY5HrhetweUd8EAHqXFf8GRRgU119spWzeOorc5SxGaJofLf3_K8GazCDIoNrPvUNtKjbeKYQwMC-nKEEhFffcMeTMgHVOvL2yspQ0JOjich5lq91Uz770JWQvBMHwHurVbBJyz3CEZWGB4RZAyj_M8R53OoEqLvRpi/w400-h125/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-05-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.44.52.png&quot; width=&quot;400&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;2)&amp;nbsp;&lt;a href=&quot;https://www.paragon-software.com/free/pm-express/&quot; target=&quot;_blank&quot;&gt;Paragon Partition Manager&lt;/a&gt;&amp;nbsp;커뮤니티 에디션을 가상 머신 윈도우에서 설치하고 resize 기능을 사용하여 디스크의 크기를 확장한다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxGBJfOcqumygGE3F9OYTZ8TArDyT82TjNpOKy-DW_pyBnCk5RJ1WLBbmRQtbRdKbpjnLyEAtVU6nNXrIzAJqCVI-KdrL9prmk1gua-wjv6o-yLI8NchfK7dUnIpzAX-v4I5xt82BYQK4LssH2lCSGA-SUopeW1oEqKuhondMCc2r7kumni0KF90uYK5uo/s1468/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-05-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.54.41.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;884&quot; data-original-width=&quot;1468&quot; height=&quot;386&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxGBJfOcqumygGE3F9OYTZ8TArDyT82TjNpOKy-DW_pyBnCk5RJ1WLBbmRQtbRdKbpjnLyEAtVU6nNXrIzAJqCVI-KdrL9prmk1gua-wjv6o-yLI8NchfK7dUnIpzAX-v4I5xt82BYQK4LssH2lCSGA-SUopeW1oEqKuhondMCc2r7kumni0KF90uYK5uo/w640-h386/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-05-27%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.54.41.png&quot; width=&quot;640&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Nanum Gothic;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andang72.blogspot.com/feeds/5356149879163883324/comments/default' title='댓글'/><link rel='replies' type='text/html' href='http://andang72.blogspot.com/2024/05/vmware-fusion.html#comment-form' title='0개의 덧글'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/5356149879163883324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/483639015604758145/posts/default/5356149879163883324'/><link rel='alternate' type='text/html' href='http://andang72.blogspot.com/2024/05/vmware-fusion.html' title='사용기 - VMware Fusion 기반 윈도우에서 디스크 공간 확장하기'/><author><name>리미트리스</name><uri>http://www.blogger.com/profile/10865563315993368505</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='19' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX3drJ0OWzhKLdqgf-bKmxtC1vK6nJqo5JIzjtKncNTvDgzDjtwIar-h3GY0958WFeMzgEh4XKNzRa7BOCJTyC6TEkAakVNMtLwjJwCQLgfOFwIZfCu-goliYJemRLNw/s220/2011-10-16+19.18.28.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2do8cPRnmdKW3F_uGBwtC1iBjVgZu5sqM7LM4fHPrWtOzp9KfrM4SQdyCfc49AOL8Dgug3C3o2KM3cE3A-uqTwBooCBqL0XUjq3rUxEkCZkb4hqaMh4XfvFe4jGzAM1P11yVvCZK_JvRytk91_C_5eyKwYGp5acOp3inY7lxgl33iocEfvAEvnJbww5_L/s72-w640-h548-c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-02-05%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.24.08.png" height="72" width="72"/><thr:total>0</thr:total></entry></feed>