<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://unvictory2.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://unvictory2.github.io/" rel="alternate" type="text/html" /><updated>2025-03-26T19:51:40+00:00</updated><id>https://unvictory2.github.io/feed.xml</id><title type="html">제발 돼라</title><subtitle>이것저것</subtitle><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><entry><title type="html">유니티 코드가 VS에서 하이라이팅 안 됨</title><link href="https://unvictory2.github.io/capstone/vs-intellisense-highlighting/" rel="alternate" type="text/html" title="유니티 코드가 VS에서 하이라이팅 안 됨" /><published>2025-03-27T00:00:00+00:00</published><updated>2025-03-27T00:00:00+00:00</updated><id>https://unvictory2.github.io/capstone/vs-intellisense-highlighting</id><content type="html" xml:base="https://unvictory2.github.io/capstone/vs-intellisense-highlighting/"><![CDATA[<h2 id="개요">개요</h2>
<p>일단 오늘 이미지 업로드 상태가 이상하다. 되는 것도 있고 안 되는 것도 있고… 켜둔 게 많아서 로딩이 오래 걸리는 거 같긴 하다.</p>

<p>유니티 코드가 VS에서 하이라이팅 안 되고 intelli sense도 안 됐다. (마우스 올려두면 메서드 설명 보여주는 거, 자동완성 등 전부)</p>

<p><img src="https://github.com/user-attachments/assets/e2b47f7c-1029-4d1a-b53d-0d5176f94802" alt="Image" /></p>

<p>이런 식으로 <code class="language-plaintext highlighter-rouge">public, class</code>같은 건 하이라이팅 되는데 <code class="language-plaintext highlighter-rouge">InvokeRepeating, Instantiate</code>같은 애들은 안 되고 마우스를 올려놔도 설명도 안 보여준다. 자동완성도… 작년부터 내내 이랬는데 아예 안 되는 게 아니라 그냥 냅뒀다가 이제서야 고친다. 사실 문제가 없는 건줄 알았음…</p>

<p>내가 시도한 방법들은</p>
<ol>
  <li>유니티 설정의 External Tools에서 Visual Studio가 연결돼있는 거 확인</li>
  <li>동일한 창에서 Regenerate Project Files 클릭</li>
  <li>Visual Studio Installer를 열고 Game Development with Unity 설치</li>
  <li>유니티의 패키지 매니저에서 Visual Studio를 업데이트 해야 하는지 확인</li>
  <li>VS의 솔루션 탐색기에서 Assembly-CSharp 파일이 제대로 로드되었는지 확인</li>
</ol>

<p>이었고, 마지막 방법으로 해결됐다! 근데 마지막 방법으로 된 거라 1~5를 다 해서 해결된 건지, 아니면 5번 하나만 하면 됐던 건지 모르겠다. 그래서 전부 다 쓰는 거기도 하고.</p>

<h2 id="해결">해결</h2>
<h3 id="external-tools-관련-12번">External Tools 관련 (1,2번)</h3>
<ol>
  <li>유니티에서 Edit &gt; Preferences &gt; External Tools로 이동.
<img src="https://github.com/user-attachments/assets/6d799d72-5726-4592-91b5-59ad040851ad" alt="Image" /></li>
  <li>External Script Editor가 VS로 잘 돼있는지 확인</li>
  <li><code class="language-plaintext highlighter-rouge">Regenerate proejct files</code> 눌러보기 (눌러도 별 일이 일어나진 않았다)</li>
</ol>

<h3 id="visual-studio-installer-3번">Visual Studio Installer (3번)</h3>
<ol>
  <li>윈도우 검색 메뉴에서 <code class="language-plaintext highlighter-rouge">Visual Studio Installer</code>를 치면 놀랍게도 이미 깔려있다. 아마 VS 깔때 알아서 깔린듯?</li>
  <li>열어보면 내 VS 버전이 뜬다. <code class="language-plaintext highlighter-rouge">수정</code> 버튼을 누르고 <code class="language-plaintext highlighter-rouge">유니티를 이용한 게임 개발</code>이 깔려있지 않다면 깔아준다. 사실 이게 안 깔려 있고 설치 목록 중 Intellisense가 있길래 이거 하고 해결될줄…<br />
<img src="https://github.com/user-attachments/assets/c7aab6ca-3a38-4772-90ed-452c7c0a22df" alt="Image" /></li>
</ol>

<h3 id="package-manager-4번">Package Manager (4번)</h3>
<ol>
  <li>Window &gt; Package Manager로 이동하여 Visual Studio Editor 패키지가 최신 버전인지 확인하고 필요시 업데이트한다. 난 다른 업데이트 가능한 패키지들의 업데이트 버튼이 있는 위치에 <code class="language-plaintext highlighter-rouge">Unlock</code>이라는 버튼만 있길래 눌러봤는데 별 일은 안 일어났다. 다시 잠그고 싶었지만 어떻게 하는지 몰라서 실패.<br />
<img src="https://github.com/user-attachments/assets/f3aff7cc-50b4-4be9-b60f-868ec2ad9be7" alt="Image" /></li>
</ol>

<h3 id="솔루션-탐색기-5번">솔루션 탐색기 (5번)</h3>
<ol>
  <li>VS로 가서 우측의 솔루션 탐색기를 본다. 없으면 <code class="language-plaintext highlighter-rouge">Ctrl + Alt + L</code>로 연다.<br />
<img src="https://github.com/user-attachments/assets/e8d8d302-603c-41ae-92c9-7dc0b3972d4a" alt="Image" /></li>
  <li>위쪽에 “프로젝트 세팅에 따라 추가 설치가 필요할 수 있습니다” 같은 말이 있으면 그걸 하면 된다. 오른쪽 아래였나 위에 작은 글씨로 설치 혹은 그 비슷한 뜻의 버튼이 있었다.</li>
  <li>안 뜬다면, <code class="language-plaintext highlighter-rouge">Assembly-CSharp</code>이 제대로 로드되었는지 확인한다. 옆에 (언로드됨)이라고 써있거나 하면 안 된 거다. 우클릭 해보면 뭘 설치하는 버튼이 있고 누르면 뭘 설치하라고 할텐데, 설치하면 해결된다!<br />
<img src="https://github.com/user-attachments/assets/fb4e2d8b-4fc9-48f4-98e5-e0d30016b7d6" alt="Image" /></li>
</ol>

<h2 id="참고">참고</h2>
<p>해결되긴 했는데, 유니티에서 연 C# 코드에만 적용된다! 교수님이 프로젝트 말고 그냥 스크립트만 올려주신 단독 <code class="language-plaintext highlighter-rouge">.cs</code> 파일을 열어보니 처음이랑 똑같은 상태다.<br />
단독으로 열었을 때 : <br />
<img src="https://github.com/user-attachments/assets/4ee94643-9b76-4435-b825-68c773c14815" alt="Image" /></p>

<p>다른 유니티 프로젝트에 이 스크립트 넣고 유니티에서 열었을 때 : <br />
<img src="https://github.com/user-attachments/assets/b9e5499b-0bdd-4084-bd06-acd8d2d5b7b7" alt="Image" /></p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Capstone" /><summary type="html"><![CDATA[유니티 관련 단어 한정 하이라이팅, intelli sense도 안 된다]]></summary></entry><entry><title type="html">Rigged Humanoid 캐릭터에 외부 애니메이션 적용하기</title><link href="https://unvictory2.github.io/capstone/apply-animations-copy/" rel="alternate" type="text/html" title="Rigged Humanoid 캐릭터에 외부 애니메이션 적용하기" /><published>2025-03-03T00:00:00+00:00</published><updated>2025-03-03T00:00:00+00:00</updated><id>https://unvictory2.github.io/capstone/apply-animations%20copy</id><content type="html" xml:base="https://unvictory2.github.io/capstone/apply-animations-copy/"><![CDATA[<h2 id="개요">개요</h2>
<p>내가 구매한 캐릭터 에셋엔 애니메이션이 포함돼 있지 않다. 하지만 “Has Attached Skeletons”라고 써있었기 때문에 따로 애니메이션을 적용시킬 수 있을 거라고 생각했고 오늘 하려는 작업이 그거다.</p>

<p>저렴한 에셋들은 애니메이션과 함께 오는 경우가 거의 없거나 같이 오는 종류수가 적다. 대신 대부분 Rigged(Attached Skeletons와 동일 의미라고 추정한다)인 상태긴 하다.</p>

<h2 id="과정">과정</h2>
<h3 id="1-구조-파악">1. 구조 파악</h3>
<p>일단 내가 쓰는 에셋의 모델을 찾는다. <code class="language-plaintext highlighter-rouge">Prefab</code>이 있고 <code class="language-plaintext highlighter-rouge">Model</code>이 따로 있기 때문에 주의해야 한다.</p>

<p><img src="https://github.com/user-attachments/assets/6ab95486-4f3c-459d-8984-3b673298ef18" alt="Image" /></p>

<p>내 경우 보면 왼쪽이 <code class="language-plaintext highlighter-rouge">Model</code>이고, 오른쪽이 <code class="language-plaintext highlighter-rouge">Prefab</code>이다.<br />
모델에 얼굴(이것도 따로 모델 폴더에 같이 있음)을 붙인 게 <code class="language-plaintext highlighter-rouge">Prefab</code>. <code class="language-plaintext highlighter-rouge">Hierachy</code>에 넣고 스크립트를 주며 쓰는 건 프리팹이지만, 오늘 할 초반부의 작업은 모델로 진행한다. 애초에 Inspector뷰에서 Rig 탭을 찾아야 되는데 이게 모델한테만 있다.</p>

<h3 id="2-humanoid-적용">2. Humanoid 적용</h3>
<p><img src="https://github.com/user-attachments/assets/96f371a0-6bfc-42c4-bedf-0596d408f138" alt="Image" /></p>

<p>내가 쓰는 프리팹의 모델을 찾은 후, 해당 모델을 클릭하고 Inspector뷰를 본다. <code class="language-plaintext highlighter-rouge">Rig</code> 탭에서 <code class="language-plaintext highlighter-rouge">Animation Type</code>이 <code class="language-plaintext highlighter-rouge">Humanoid</code>로 돼있는지 확인한다. 난 <code class="language-plaintext highlighter-rouge">Generic</code>으로 돼있어서 바꿨다. 이후 밑의 <code class="language-plaintext highlighter-rouge">Apply</code>를 누른다.</p>

<h3 id="3-avatar-확인">3. Avatar 확인</h3>
<p><img src="https://github.com/user-attachments/assets/7f905969-92f2-4592-a278-65fd0c460de1" alt="Image" /></p>

<p>잘 됐다면 아까는 비활성화 돼있었던 <code class="language-plaintext highlighter-rouge">Configure</code>라는 버튼이 활성화된다. 이 버튼을 클릭해본다.</p>

<p><img src="https://github.com/user-attachments/assets/84823a3c-3bae-4e9f-8bbb-78fd3fca45de" alt="Image" /></p>

<p>Inspector뷰가 <code class="language-plaintext highlighter-rouge">Avatar Configuration</code>이라는 화면으로 바뀐다. Avatar 에셋은 3D 모델의 본 구조의 매핑 정보를 저장하고 있으며, 본 구조가 동일하다면 다른 모델에서 사용한 Avatar 에셋을 재사용할 수 있다.<br />
실선으로 된 동그라미들은 필수, 점선은 선택이라고 한다. <code class="language-plaintext highlighter-rouge">Body</code>, <code class="language-plaintext highlighter-rouge">Head</code>, <code class="language-plaintext highlighter-rouge">Hand</code> 등을 확인해보고, 위 탭 중 <code class="language-plaintext highlighter-rouge">Muscles&amp;Settings</code>에서 여러 자세도 취해보자. Scene뷰에서 각종 자세에 따라 바뀌는 모습을 확인해볼 수 있다. 매핑이 잘 됐는지, 자세들은 이상하지 않은지 확인해보면 된다.</p>

<p><img src="https://github.com/user-attachments/assets/a9b7cb87-0315-4bbb-94c6-066d4d468c55" alt="Image" /></p>

<p>확인했으면 디렉토리에 있는 모델에 아까는 없던 하늘색 사람 모양의 <code class="language-plaintext highlighter-rouge">Avatar</code>가 생성된 것도 확인한다.</p>

<h3 id="4-animator-controller">4. Animator Controller</h3>
<p><img src="https://github.com/user-attachments/assets/927fba60-49ce-4f73-a0f2-b174cc22dbc8" alt="Image" /></p>

<p>이제 다음 작업을 해보자. <code class="language-plaintext highlighter-rouge">Animator Controller</code>를 하나 만들자. 나는 <code class="language-plaintext highlighter-rouge">Assets/Animation/Controllers/</code>의 경로에 만들었다.</p>

<p><img src="https://github.com/user-attachments/assets/db0f3210-4487-4c34-8bdb-78d945eb0c11" alt="Image" /></p>

<p>생성된 컨트롤러를 선택하고 Inspector뷰에서 <code class="language-plaintext highlighter-rouge">Open</code> 버튼을 누른다. Scene뷰 대신 Animator뷰가 열릴 거다. 여기서 상황에 따른 각종 애니메이션을 설계할 수 있다.</p>

<p><img src="https://github.com/user-attachments/assets/bd107572-4e27-405a-bc77-6b01484673f2" alt="Image" /></p>

<p>컨트롤러에 애니메이션을 드래그해서 넣어보자. 적용할 애니메이션은 미리 에셋 스토어에서 무료로 받아놨다. 컨트롤러에서 주황색으로 새 애니메이션이 추가된 걸 확인할 수 있다.</p>

<h3 id="5-hierachy의-prefab에-적용">5. Hierachy의 Prefab에 적용</h3>

<p><img src="https://github.com/user-attachments/assets/b245f986-9090-4dea-b9a4-bc4e4a4083a5" alt="Image" /></p>

<p>지금까지 작업하던 모델의 프리팹이 이미 <code class="language-plaintext highlighter-rouge">Hierachy</code>에 없다면 넣고, 있다면 선택한다. Inspector뷰에서 <code class="language-plaintext highlighter-rouge">Add Component</code>를 누른 뒤 <code class="language-plaintext highlighter-rouge">Animator</code>를 추가한다.</p>

<p><img src="https://github.com/user-attachments/assets/4142ad01-47a7-4572-9cfa-a29bfc4d5c14" alt="Image" /></p>

<p><img src="https://github.com/user-attachments/assets/41b00a98-174d-4dd6-8a25-e7810b978423" alt="Image" /></p>

<p>직전에 생성한 컨트롤러와 아까 생성된 걸 확인한 Avatar를 드래그해서 Animator에 적용한다.</p>

<h3 id="6-성공">6. 성공!</h3>

<p><img src="https://github.com/user-attachments/assets/4b08eeb5-4ef3-402d-a8a7-c717d97c87e3" alt="Image" /></p>

<p>Play 해보자. Play 전엔 T자로 서있던 캐릭터가 Idle 모션을 하고 있다!<br />
재사용 방법들이나 Avatar가 정확히 뭔지, Animation 종류엔 뭐가 있는지 같은 개념도 설명하면 좋겠으나 오늘은 피곤해서 다음에 생각해봐야겠다.</p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Capstone" /><summary type="html"><![CDATA[애니메이션 미포함 에셋을 받은 경우]]></summary></entry><entry><title type="html">글에 비디오 넣기</title><link href="https://unvictory2.github.io/blog%20writing/inserting_video/" rel="alternate" type="text/html" title="글에 비디오 넣기" /><published>2025-03-02T00:00:00+00:00</published><updated>2025-03-02T00:00:00+00:00</updated><id>https://unvictory2.github.io/blog%20writing/inserting_video</id><content type="html" xml:base="https://unvictory2.github.io/blog%20writing/inserting_video/"><![CDATA[<h2 id="후보">후보</h2>
<ol>
  <li>유튜브에 업로드 하고 유튜브 영상으로 삽입</li>
  <li>이미지처럼 github issues 사용해서 삽입 &gt; 그냥 쌩링크고 링크 눌러야 새 탭에서 영상 재생</li>
  <li>내 리포지토리에 첨부하고 html 태그로 재생하기</li>
</ol>

<p>2는 재생이 번거롭고 유튜브에 올리긴 귀찮아서 3번으로 하기로 했다.</p>

<p><br /></p>

<h2 id="방법">방법</h2>
<p><img src="https://github.com/user-attachments/assets/de1510b6-ef21-484d-b286-0eac7d61097f" alt="Image" /></p>

<p>루트에 있는 <code class="language-plaintext highlighter-rouge">asset</code> 폴더 내부에 <code class="language-plaintext highlighter-rouge">videos</code> 폴더 만들고 거기다 넣고싶은 영상을 집어넣는다. 본인이 기억만 하면 아무 루트나 상관 없음.</p>

<p>글 쓸 때 이런 식으로 사용한다.</p>
<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;video</span> <span class="na">width=</span><span class="s">"100%"</span> <span class="na">height=</span><span class="s">"auto"</span> <span class="na">controls</span><span class="nt">&gt;</span>
  <span class="nt">&lt;source</span> <span class="na">src=</span><span class="s">"/assets/videos/카메라%20문제%20Gameview.mp4"</span> <span class="na">type=</span><span class="s">"video/mp4"</span><span class="nt">&gt;</span>
  Your browser does not support the video tag.
<span class="nt">&lt;/video&gt;</span>
</code></pre></div></div>
<p>``은 변수로 쓰는 거라 바꿀 필요 없다. 뒤에 있는 경로는 파일 경로를 써주면 되는 거고. <code class="language-plaintext highlighter-rouge">%20</code>은 url에서 띄어쓰기 문제 생기지 말라고 넣어준 거다. 다음부턴 파일명에 띄어쓰기 안 넣는 것도 하나의 방법일듯.</p>

<p>글에선 이렇게 보인다.</p>

<p><img src="https://github.com/user-attachments/assets/8bd90c82-e361-4a91-8c6e-a4a1774ffea5" alt="Image" /></p>

<p>이 방법의 문제점은 영상을 많이 넣을수록 블로그 리포 크기가 늘어날 거라는 점? 근데 위에 3개는 1MB라 아직 별 상관 없을 거 같다.</p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Blog Writing" /><summary type="html"><![CDATA[리포에 첨부 후 html 태그 사용]]></summary></entry><entry><title type="html">[BUG] 카메라가 캐릭터 따라가게 하기</title><link href="https://unvictory2.github.io/capstone/follow-camera/" rel="alternate" type="text/html" title="[BUG] 카메라가 캐릭터 따라가게 하기" /><published>2025-03-02T00:00:00+00:00</published><updated>2025-03-02T00:00:00+00:00</updated><id>https://unvictory2.github.io/capstone/follow-camera</id><content type="html" xml:base="https://unvictory2.github.io/capstone/follow-camera/"><![CDATA[<h2 id="문제">문제</h2>
<h3 id="설명">설명</h3>
<video width="100%" height="auto" controls="">
  <source src="/assets/videos/카메라%20문제%20Gameview.mp4" type="video/mp4" />
  Your browser does not support the video tag.
</video>

<video width="100%" height="auto" controls="">
  <source src="/assets/videos/카메라%20문제%20Sceneview.mp4" type="video/mp4" />
  Your browser does not support the video tag.
</video>

<p>영상을 넣는 게 처음이라 어떻게 올라가는지 모르겠다.</p>

<p>캐릭터가 회전하면 카메라도 같이 회전한다. 그래서 캐릭터가 어느 방향으로 움직이든 직진하는 걸로 보인다.</p>

<p>다른 3d 게임들을 보면 :</p>
<ol>
  <li>캐릭터 이동시 카메라는 뒤에 붙어있긴 하지만 돌진 않는다</li>
  <li>마우스 회전시 카메라도 돌고 캐릭터도 돈다. w 누르면서 카메라 회전시 움직이는 방향 바뀜.</li>
</ol>

<p>1번에서부터 문제가 생긴 거다.</p>

<h3 id="현-코드">현 코드</h3>
<div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">System.Collections</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">System.Collections.Generic</span><span class="p">;</span>
<span class="k">using</span> <span class="nn">UnityEngine</span><span class="p">;</span>

<span class="k">public</span> <span class="k">class</span> <span class="nc">FollowCam</span> <span class="p">:</span> <span class="n">MonoBehaviour</span>
<span class="p">{</span>
    <span class="c1">// 따라가야 할 대상</span>
    <span class="k">public</span> <span class="n">Transform</span> <span class="n">targetTr</span><span class="p">;</span>
    <span class="k">private</span> <span class="n">Transform</span> <span class="n">camTr</span><span class="p">;</span>

    <span class="c1">// 따라가야 할 대상으로부터 얼마나 떨어져 있을지</span>
    <span class="p">[</span><span class="nf">Range</span><span class="p">(</span><span class="m">2.0f</span><span class="p">,</span> <span class="m">20.0f</span><span class="p">)]</span> <span class="c1">// 변수 입력 범위 제한, 인스펙터 뷰에 슬라이드바</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">distance</span> <span class="p">=</span> <span class="m">10.0f</span><span class="p">;</span>

    <span class="c1">// Y축으로 이동할 높이, 카메라 높이</span>
    <span class="p">[</span><span class="nf">Range</span><span class="p">(</span><span class="m">0.0f</span><span class="p">,</span> <span class="m">10.0f</span><span class="p">)]</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">height</span> <span class="p">=</span> <span class="m">2.0f</span><span class="p">;</span>

    <span class="c1">//카메라 LookAt의 offset 값</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">targetOffset</span> <span class="p">=</span> <span class="m">2.0f</span><span class="p">;</span>

    <span class="c1">// 카메라 반응 속도</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="n">damping</span> <span class="p">=</span> <span class="m">0.1f</span><span class="p">;</span>

    <span class="k">private</span> <span class="n">Vector3</span> <span class="n">velocity</span> <span class="p">=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">zero</span><span class="p">;</span>

    <span class="c1">// Start is called before the first frame update</span>
    <span class="k">void</span> <span class="nf">Start</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">// Main Camera 자신의 Transform 컴포넌트 추출</span>
        <span class="n">camTr</span> <span class="p">=</span> <span class="n">GetComponent</span><span class="p">&lt;</span><span class="n">Transform</span><span class="p">&gt;();</span>
    <span class="p">}</span>

    <span class="c1">// Update에서 이동 로직 한 후 실행하기 위해</span>
    <span class="k">void</span> <span class="nf">LateUpdate</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">// 추적해야 할 대상의 뒤쪽으로 distance만큼, 위로 height만큼 이동</span>
        <span class="c1">// 타깃의 위치 + (타겟의 뒤쪽 방향 * 떨어질 거리) + (y축 방향 * 높이)</span>
        <span class="n">Vector3</span> <span class="n">pos</span> <span class="p">=</span> <span class="n">targetTr</span><span class="p">.</span><span class="n">position</span>
            <span class="p">+</span> <span class="p">(-</span><span class="n">targetTr</span><span class="p">.</span><span class="n">forward</span> <span class="p">*</span> <span class="n">distance</span><span class="p">)</span>
            <span class="p">+</span> <span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">up</span> <span class="p">*</span> <span class="n">height</span><span class="p">);</span>

        <span class="c1">// 구면 선형 보간 사용, 위치 부드럽게 바꾸기</span>
        <span class="c1">//camTr.position = Vector3.Slerp(camTr.position, pos, Time.deltaTime*damping);</span>

        <span class="c1">// SmoothDamp로 위치 보간</span>
        <span class="n">camTr</span><span class="p">.</span><span class="n">position</span> <span class="p">=</span> <span class="n">Vector3</span><span class="p">.</span><span class="nf">SmoothDamp</span><span class="p">(</span><span class="n">camTr</span><span class="p">.</span><span class="n">position</span><span class="p">,</span> <span class="n">pos</span><span class="p">,</span> <span class="k">ref</span> <span class="n">velocity</span><span class="p">,</span> <span class="n">damping</span><span class="p">);</span>

        <span class="c1">// 피벗 좌표 향해 회전</span>
        <span class="n">camTr</span><span class="p">.</span><span class="nf">LookAt</span><span class="p">(</span><span class="n">targetTr</span><span class="p">.</span><span class="n">position</span> <span class="p">+</span> <span class="p">(</span><span class="n">targetTr</span><span class="p">.</span><span class="n">up</span> <span class="p">*</span> <span class="n">targetOffset</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><br /></p>

<h2 id="해결">해결</h2>
<h3 id="1-vector-수정">1. Vector 수정</h3>
<p>40행의 <code class="language-plaintext highlighter-rouge">-targetTr.forward</code>를 <code class="language-plaintext highlighter-rouge">Vector3.back</code>로 바꾼다. 모델의 로컬 좌표 기준으로 계산하던 걸 월드 좌표 기준으로 계산하게 바꾸는 거다. 이러면 더이상 카메라가 캐릭터와 함께 회전하지 않고, 일정 거리를 유지하되 계속 같은 방향에서 캐릭터를 관찰한다.<br />
(<code class="language-plaintext highlighter-rouge">Vector3.back</code>은 월드 좌표계에서 항상 -Z 방향을 가리키므로, 캐릭터의 회전과 무관하게 일정한 방향을 유지)</p>
<h3 id="2-lookat-삭제">2. LookAt 삭제</h3>
<p>50행의 <code class="language-plaintext highlighter-rouge">camTr.LookAt(targetTr.position + (targetTr.up * targetOffset));</code>를 삭제한다. 오류 해결을 위해서라기보단 더이상 필요하지 않기 때문이다. 이전엔 카메라가 계속 회전하기 때문에 회전 후 캐릭터를 바라봐야 해서 이 코드가 있었다. 그러나 이제 회전하지 않기 때문에 없어도 아무 지장이 없고, 있어도 아무 효과가 없다. <br />
카메라 위치를 조정하면서 효과가 있다는 걸 알게 됐다. 카메라를 가까이 둘 경우 캐릭터가 움직이면 카메라가 약간씩 회전하는 효과를 낸다. 어찌됐든 삭제하는 게 맞다.</p>

<p>이제 카메라가 회전하지 않고 멀리서 관찰만 한다!</p>
<video width="100%" height="auto" controls="">
  <source src="/assets/videos/카메라%20문제%20해결.mp4" type="video/mp4" />
  Your browser does not support the video tag.
</video>

<p><br /></p>

<h2 id="개념">개념</h2>
<h3 id="vector3forward와-transformforward">Vector3.forward와 transform.forward</h3>
<p>이 둘은 다르다.<br />
<code class="language-plaintext highlighter-rouge">Vector3.forward</code>는 (0,0,1)과 같은 뜻이다. 언제 어떻게 써도 (0,0,1)이다.</p>

<p><code class="language-plaintext highlighter-rouge">transform.forward</code>는 <u>월드 공간을 기준으로 한 현재 게임 오브젝트의 앞 방향 벡터</u>이다. 예를 들어, 내 캐릭터가 보고 있는 앞 방향이 월드 기준으론 x축이라고 하자. 그럼 <code class="language-plaintext highlighter-rouge">transform.forward</code>는 (1,0,0)이라는 거다. 내 캐릭터의 앞 방향을 월드 기준으로 해석하면 x축이니까 말이다.</p>

<p>이 상황에서 <code class="language-plaintext highlighter-rouge">Translate(transform.forward)</code> 하면 <code class="language-plaintext highlighter-rouge">Translate(1,0,0)</code>이란 뜻이고, 앞(오브젝트가 쳐다보는 방향)이 아니라 옆으로 움직인다. <code class="language-plaintext highlighter-rouge">Translate</code>는 오브젝트 기준으로 움직이니까 오브젝트 기준 x축 방향, 즉 옆으로 움직이라고 명령한 게 돼버린 거다.</p>

<p><u>값은 월드 기준으로 `transform.forward`해서 가져오고, 해석은 오브젝트 기준으로 `Translate` 해서 문제가 발생하는 거다.</u></p>

<p>해결 방법은</p>
<ol>
  <li><code class="language-plaintext highlighter-rouge">Translate</code>로는 언제나 <code class="language-plaintext highlighter-rouge">Vector3.forward</code>로만 이동, 방향은 회전으로만 바꾸기.
    <div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
 <span class="p">{</span>
     <span class="n">Vector3</span> <span class="n">dir</span> <span class="p">=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">zero</span><span class="p">;</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">UpArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">DownArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">back</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">RightArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">right</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">LeftArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">left</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="n">dir</span> <span class="p">=</span> <span class="n">dir</span><span class="p">.</span><span class="n">normalized</span><span class="p">;</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">dir</span><span class="p">.</span><span class="n">magnitude</span> <span class="p">&gt;</span> <span class="m">0.5f</span><span class="p">)</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">LookAt</span><span class="p">(</span><span class="n">transform</span><span class="p">.</span><span class="n">position</span> <span class="p">+</span> <span class="n">dir</span><span class="p">);</span>
     <span class="p">}</span>
 <span class="p">}</span>
</code></pre></div>    </div>
  </li>
  <li><code class="language-plaintext highlighter-rouge">Space.World</code>를 <code class="language-plaintext highlighter-rouge">Translate</code> 함수의 인자로 넣어서 월드 기준으로 해석하게 하기.<br />
이렇게 하면 Translate 함수가 월드 좌표계를 기준으로 이동을 계산하므로, 캐릭터의 로컬 좌표계와 무관하게 일관된 방향으로 이동한다.
    <div class="language-cs highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">void</span> <span class="nf">Update</span><span class="p">()</span>
 <span class="p">{</span>
     <span class="n">Vector3</span> <span class="n">dir</span> <span class="p">=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">zero</span><span class="p">;</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">UpArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">,</span> <span class="n">Space</span><span class="p">.</span><span class="n">World</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">forward</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">DownArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">back</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">,</span> <span class="n">Space</span><span class="p">.</span><span class="n">World</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">back</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">RightArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">right</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">,</span> <span class="n">Space</span><span class="p">.</span><span class="n">World</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">right</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">Input</span><span class="p">.</span><span class="nf">GetKey</span><span class="p">(</span><span class="n">KeyCode</span><span class="p">.</span><span class="n">LeftArrow</span><span class="p">))</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">Translate</span><span class="p">(</span><span class="n">Vector3</span><span class="p">.</span><span class="n">left</span> <span class="p">*</span> <span class="m">2.0f</span> <span class="p">*</span> <span class="n">Time</span><span class="p">.</span><span class="n">deltaTime</span><span class="p">,</span> <span class="n">Space</span><span class="p">.</span><span class="n">World</span><span class="p">);</span>
         <span class="n">dir</span> <span class="p">+=</span> <span class="n">Vector3</span><span class="p">.</span><span class="n">left</span><span class="p">;</span>
     <span class="p">}</span>
     <span class="n">dir</span> <span class="p">=</span> <span class="n">dir</span><span class="p">.</span><span class="n">normalized</span><span class="p">;</span>
     <span class="k">if</span> <span class="p">(</span><span class="n">dir</span><span class="p">.</span><span class="n">magnitude</span> <span class="p">&gt;</span> <span class="m">0.5f</span><span class="p">)</span>
     <span class="p">{</span>
         <span class="n">transform</span><span class="p">.</span><span class="nf">LookAt</span><span class="p">(</span><span class="n">transform</span><span class="p">.</span><span class="n">position</span> <span class="p">+</span> <span class="n">dir</span><span class="p">);</span>
     <span class="p">}</span>
 <span class="p">}</span>
</code></pre></div>    </div>
  </li>
</ol>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Capstone" /><summary type="html"><![CDATA[캐릭터를 따라 회전하는 카메라, 각도가 변하지 않는 카메라]]></summary></entry><entry><title type="html">[BUG] GameView 화면이 너무 낮다</title><link href="https://unvictory2.github.io/capstone/low-resolution/" rel="alternate" type="text/html" title="[BUG] GameView 화면이 너무 낮다" /><published>2025-03-02T00:00:00+00:00</published><updated>2025-03-02T00:00:00+00:00</updated><id>https://unvictory2.github.io/capstone/low-resolution</id><content type="html" xml:base="https://unvictory2.github.io/capstone/low-resolution/"><![CDATA[<h2 id="문제">문제</h2>
<p>이전 글 영상에서 볼 수 있는데, GameView 화면이 이상하게 저화질이다.<br />
SceneView에선 멀쩡한데 GameView만 픽셀이 보이는 수준이다!</p>

<p><img src="https://github.com/user-attachments/assets/1ad6be7d-af45-41c3-870c-d4b2bddce835" alt="Image" /></p>

<h2 id="해결">해결</h2>
<p>위 사진에 있는 GameView의 <code class="language-plaintext highlighter-rouge">Scale</code>이 5배로 돼있어서 생기는 문제였다. 1배로 바꿔주면 정상적인 화질로 돌아온다. 대신 캐릭터가 너무 작아질 거다.</p>

<p>그건 카메라 거리 설정도 Scale이 5배인 거 기준으로 해놨기 때문이다. 이것도 고쳐줘야 한다. <code class="language-plaintext highlighter-rouge">Distance</code>, <code class="language-plaintext highlighter-rouge">Height</code>, <code class="language-plaintext highlighter-rouge">Target Offset</code>을 손보면 된다.</p>

<p><img src="https://github.com/user-attachments/assets/6f7cdd56-10a4-4218-96c3-c8869dabe11d" alt="Image" /></p>

<p>위처럼 엄청 높은 값으로 돼있는 <code class="language-plaintext highlighter-rouge">Distance</code>를 먼저 가깝게 바꾸고, 나머지는 화면 보면서 바꾸면 끝.</p>

<p><img src="https://github.com/user-attachments/assets/453ba20b-0a86-4e72-8db3-f636adc14968" alt="Image" /></p>

<p>깨끗해졌다.</p>

<p><img src="https://github.com/user-attachments/assets/53fd8229-d01a-4f33-bed9-bfe0f825a0be" alt="Image" /></p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Capstone" /><summary type="html"><![CDATA[Scale 1로 하고 카메라 가까이 붙이자]]></summary></entry><entry><title type="html">[네프 플젝] 프로그램 동작과 프론트 백 상호작용 정리</title><link href="https://unvictory2.github.io/network%20programming/project-plan/" rel="alternate" type="text/html" title="[네프 플젝] 프로그램 동작과 프론트 백 상호작용 정리" /><published>2024-11-20T00:00:00+00:00</published><updated>2024-11-20T00:00:00+00:00</updated><id>https://unvictory2.github.io/network%20programming/project-plan</id><content type="html" xml:base="https://unvictory2.github.io/network%20programming/project-plan/"><![CDATA[<h2 id="서론">서론</h2>
<p>자바 소캣을 기반으로 하는 네트워크 프로그래밍 프로젝트로 게임을 만들게 됐다. 내 역할은 서버쪽이다.</p>

<p><br /></p>

<h2 id="흐름-정리">흐름 정리</h2>
<p>게임의 흐름을 먼저 정리해보자.</p>

<ol>
  <li>서버 접속 및 대기방 입장
    <ul>
      <li>플레이어가 서버에 접속하면 자동으로 대기방에 입장</li>
      <li>충분한 플레이어가 모일 때까지 대기</li>
      <li>대기 중 채팅 가능</li>
    </ul>
  </li>
  <li>게임 시작 및 역할 분배
    <ul>
      <li>충분한 플레이어가 모이면 게임 시작</li>
      <li>플레이어들이 시민과 라이어로 나뉨</li>
      <li>주제와 제시어 설정 (예: 주제 - 스포츠, 제시어 - 축구)</li>
      <li>UI에 각 플레이어를 나타내는 버튼 표시</li>
    </ul>
  </li>
  <li>제시어 설명 단계
    <ul>
      <li>모든 플레이어가 돌아가며 제시어에 대해 설명</li>
      <li>각 플레이어에게 정해진 시간 제공 (타이머 표시)</li>
      <li>시민: 라이어가 알아차리지 못하도록 조심스럽게 설명</li>
      <li>라이어: 시민인 척 그럴듯하게 설명</li>
      <li>채팅 시 이모티콘 사용 가능</li>
    </ul>
  </li>
  <li>자유 토론 시간
    <ul>
      <li>플레이어들이 누가 라이어인지 추리하고 논의</li>
      <li>과거 각 인원의 제시어 설명 내용 확인 가능 (정보 버튼 사용)</li>
      <li>제한 시간 적용</li>
    </ul>
  </li>
  <li>투표 단계
    <ul>
      <li>라이어로 의심되는 플레이어에 대해 투표</li>
      <li>제한 시간 적용</li>
    </ul>
  </li>
  <li>최후변론 및 제거 결정
    <ul>
      <li>지목된 플레이어의 최후변론 (음성으로 진행 가능)</li>
      <li>지목된 플레이어만 말할 수 있음</li>
      <li>다른 플레이어들이 제거 여부 결정</li>
      <li>제한 시간 적용</li>
    </ul>
  </li>
  <li>결과 확인
    <ul>
      <li>제거된 플레이어가 시민일 경우: 게임 계속, UI에서 해당 플레이어 버튼에 X 표시</li>
      <li>제거된 플레이어가 라이어일 경우: 제시어 맞히기 기회 제공
        <ul>
          <li>라이어가 맞히면: 라이어 승리</li>
          <li>라이어가 못 맞히면: 시민 승리</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>밤 단계
    <ul>
      <li>라이어들끼리 제시어에 대해 논의</li>
      <li>시민들은 대기</li>
      <li>제한 시간 적용</li>
    </ul>
  </li>
  <li>
    <p>다음 라운드로 반복 (3번 단계로 돌아감) 또는 게임 종료</p>
  </li>
  <li>게임 종료 후 대기방으로 복귀
    <ul>
      <li>플레이어들이 자동으로 대기방으로 돌아감</li>
      <li>새로운 게임 시작을 기다림</li>
    </ul>
  </li>
</ol>

<h3 id="추가적인-특징">추가적인 특징:</h3>
<ul>
  <li>각 단계마다 타이머가 적용되어 제한 시간이 끝나면 자동으로 다음 단계로 넘어감</li>
  <li>UI에는 현재 주제, 제시어(시민에게만 표시), 타이머, 채팅 창, 입력 필드 등이 포함됨</li>
  <li>플레이어의 상태(현재 플레이어, 사망 여부 등)가 UI에 반영됨</li>
  <li>게임 진행 중 언제든지 과거 대화 내용을 확인할 수 있는 기능 제공</li>
  <li>대기방에서 플레이어 수, 준비 상태 등을 확인할 수 있는 UI 제공</li>
</ul>

<h3 id="나중에-추가를-고려해볼-사항들">나중에 추가를 고려해볼 사항들:</h3>
<ol>
  <li>그림을 포함할 방안
    <ul>
      <li>제시어를 그림으로 제시</li>
      <li>제시어를 그림으로 표현</li>
      <li>사망시 피자국 같은 그림 전송</li>
    </ul>
  </li>
  <li>추가적인 요소
    <ul>
      <li>자동 매칭</li>
      <li>친구 목록 (데베 연동 필요)</li>
    </ul>
  </li>
</ol>

<p><br /></p>

<h2 id="서버-측면에서-게임의-각-단계별로-필요한-처리와-구현-방법-정리">서버 측면에서 게임의 각 단계별로 필요한 처리와 구현 방법 정리</h2>

<ol>
  <li>서버 초기화 및 대기 - 기존 수업 내용과 같음
    <ul>
      <li>서버 소켓을 생성하고 지정된 포트에서 리스닝 시작 &gt; 포트 지정</li>
      <li>acceptThread를 생성하여 클라이언트의 접속을 대기 ServerSocket.accept()</li>
      <li>Vector<ClientHandler>를 생성하여 연결된 클라이언트들을 관리</ClientHandler></li>
    </ul>
  </li>
  <li>클라이언트 접속 처리
    <ul>
      <li>클라이언트 접속 시 ClientHandler 객체 생성 및 Vector에 추가</li>
      <li>ClientHandler 스레드 시작 (클라이언트와의 통신 담당) &gt; 스레드 생성</li>
      <li>대기방 인원 수 확인 및 게임 시작 가능 여부 체크</li>
    </ul>
  </li>
  <li>게임 시작 준비
    <ul>
      <li>충분한 인원이 모이면 게임 시작 신호를 모든 클라이언트에 전송 ObjectOutputStream
        <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="o">(</span><span class="n">users</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">&gt;=</span> <span class="no">MIN_PLAYERS</span><span class="o">)</span> <span class="o">{</span>
 <span class="nc">ChatMsg</span> <span class="n">startMsg</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ChatMsg</span><span class="o">(</span><span class="s">"SERVER"</span><span class="o">,</span> <span class="nc">ChatMsg</span><span class="o">.</span><span class="na">MODE_GAME_START</span><span class="o">);</span>
 <span class="n">broadcasting</span><span class="o">(</span><span class="n">startMsg</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div>        </div>
      </li>
      <li>플레이어 역할 분배 (시민, 라이어)
```java
class Player {
  String id;
  boolean isAlive;
  boolean isSpeaking;
  boolean isLiar;
  // 기타 필요한 정보들
}</li>
    </ul>

    <p>List<Player> players = new ArrayList&lt;&gt;();
for (ClientHandler client : users) {
   Player player = new Player(client.getUid());
   players.add(player);
}</Player></p>

    <p>Random random = new Random();
int liarIndex = random.nextInt(players.size());
players.get(liarIndex).setLiar(true);</p>
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>- 주제와 제시어 선정
```java
for (int i = 0; i &lt; players.size(); i++) {
   Player player = players.get(i);
   ClientHandler client = users.get(i);
      
   ChatMsg roleMsg = new ChatMsg("SERVER", ChatMsg.MODE_ROLE_ASSIGN);
   roleMsg.setRole(player.isLiar() ? "LIAR" : "CITIZEN");
   roleMsg.setTopic(selectedTopic);
   if (!player.isLiar()) {
      roleMsg.setWord(selectedWord);
   }
      
   client.send(roleMsg);
}
</code></pre></div>    </div>
  </li>
  <li>게임 진행
a. 제시어 설명 단계
    <ul>
      <li>각 플레이어에게 순서대로 발언권 부여 isSpeaking</li>
      <li>타이머 스레드 시작 (각 플레이어의 발언 시간 제한)</li>
      <li>플레이어의 설명을 받아(objectinputstream) 다른 모든 플레이어에게 브로드캐스트 (옵젝 스트림 계속 사용)</li>
    </ul>

    <p>b. 자유 토론 시간</p>
    <ul>
      <li>타이머 스레드 시작 (전체 토론 시간 제한)</li>
      <li>플레이어들의 메시지를 받아 모두에게 브로드캐스트</li>
    </ul>

    <p>c. 투표 단계</p>
    <ul>
      <li>투표 시작 신호 전송(클라 투표 화면으로 바꾸게)</li>
      <li>새 스레드. DataInputStream으로 각 플레이어의 투표를 받고 다 받으면 집계까지. 이후 투표 결과 계산 및 모든 플레이어에게 결과 전송 (기존 objstream)</li>
    </ul>

    <p>d. 최후변론 및 제거 결정</p>
    <ul>
      <li>지목된 플레이어에게 최후변론 기회 부여 (음성 데이터 처리 필요 &gt; 어케 하는 건지 알아보기)</li>
      <li>다른 플레이어들의 최종 결정을 받아 처리 (투표 스레드 재사용)</li>
      <li>결과에 따라 게임 진행 또는 종료 처리</li>
    </ul>

    <p>e. 밤 단계 (라이어 추리 시간)</p>
    <ul>
      <li>라이어들에게만 메시지 전송 가능하도록 설정</li>
      <li>라이어의 추리 결과 접수 및 판정</li>
    </ul>
  </li>
  <li>게임 종료 처리
    <ul>
      <li>게임 결과를 모든 플레이어에게 전송</li>
      <li>플레이어들을 대기방으로 돌려보내기</li>
    </ul>
  </li>
</ol>

<p>추가 고려사항:</p>

<ol>
  <li>타이머 스레드 구현 - 프론트에 이미 돼있긴 함
    <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nc">GameTimer</span> <span class="kd">extends</span> <span class="nc">Thread</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">remainingTime</span><span class="o">;</span>
    <span class="c1">// 타이머 로직 구현</span>
<span class="o">}</span>
</code></pre></div>    </div>
  </li>
  <li>메시지 처리
    <ul>
      <li>ChatMsg 클래스를 확장하여 게임의 다양한 상황을 처리할 수 있는 메시지 타입 정의</li>
    </ul>
  </li>
  <li>동기화 처리
    <ul>
      <li>여러 스레드가 동시에 접근하는 공유 자원(플레이어 목록, 게임 상태 등) 생각 잘 해야</li>
    </ul>
  </li>
  <li>예외 처리
    <ul>
      <li>클라이언트 연결 끊김, 네트워크 오류 등에 대한 견고한 예외 처리</li>
      <li>뭐 이건 수업때 배운대로</li>
    </ul>
  </li>
  <li>로깅
    <ul>
      <li>게임 진행 상황, 에러 등을 로그로 기록하여 디버깅 및 모니터링에 활용? 서버에 띄우면 좋을거같고</li>
    </ul>
  </li>
</ol>

<p>스레드 어떻게?? 게임상태관리, 클라통신, 채팅, 타이머 4개?</p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Network Programming" /><summary type="html"><![CDATA[언제 어떤 소캣을 열고, 각 데이터는 어떻게 저장하고 등]]></summary></entry><entry><title type="html">문제 해결 - 에뮬레이터 종료시 컴퓨터 먹통</title><link href="https://unvictory2.github.io/miraework%20project/emulator-freeze/" rel="alternate" type="text/html" title="문제 해결 - 에뮬레이터 종료시 컴퓨터 먹통" /><published>2024-10-16T00:00:00+00:00</published><updated>2024-10-16T00:00:00+00:00</updated><id>https://unvictory2.github.io/miraework%20project/emulator-freeze</id><content type="html" xml:base="https://unvictory2.github.io/miraework%20project/emulator-freeze/"><![CDATA[<p><img src="https://github.com/user-attachments/assets/2be6b033-0901-4079-b681-c549bfbce14a" alt="화면 캡처 2024-10-16 021754" /></p>

<p>안드로이드 에뮬레이터가 정신이 나가버렸다. 화면 끄기나 종료를 누르면 컴퓨터가 멈춘다. 마우스/키보드 입력이 안 되고 화면은 나오는 상태가 지속된다. 헤드폰에서 음악은 계속 나오다가 한참 기다리면 끊긴다. 결국 전원 버튼 눌러서 다시시작 해야된다. 오늘만 7번째인거 같다. 다시 시작한 이후에 해당 에뮬레이터는 먹통이 돼서 지웠다가 다시 만들어야 한다.</p>

<p>해결 방법은</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">flutter doctor</code> 해보기</li>
  <li>에뮬레이터 종료를 작업관리자나 <code class="language-plaintext highlighter-rouge">adb emu kill</code> 커멘드로 하기
인 거 같다. 첫 번째 방법은 했더니 약관 동의 안 한 게 있다고 해서 그거만 했다.</li>
</ul>

<p>오 첫 번째 방법만 하고 지금 끄기 버튼으로 껐는데 컴퓨터가 멀쩡하다. 드디어 멀쩡해진 건가? 다음엔 안 되면 두 번째 방법으로 하는 게 좋겠다. 저건 매번 해야되는 거라 훨씬 귀찮을듯…</p>

<h2 id="후기">후기!!!!!!</h2>
<p>나머지 방법들 다 안 되고, <u>무조건 작업관리자로 끌 것!!! </u><br />
<code class="language-plaintext highlighter-rouge">adb emu kill</code> 안 됨, <code class="language-plaintext highlighter-rouge">flutter doctor</code> 했었어도 다음에 꺼보니까 또 안 됨</p>

<p><a href="https://www.reddit.com/r/androiddev/comments/8vy1vz/anyone_have_problems_with_android_studio_freezing/">참고링크1</a></p>

<p><a href="https://livelikesloth.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4-%EC%97%90%EB%AE%AC%EB%A0%88%EC%9D%B4%ED%84%B0-%EB%81%84%EB%A9%B4-%EC%BB%B4%ED%93%A8%ED%84%B0-%EB%A9%88%EC%B6%A4-%ED%98%84%EC%83%81">참고링크2</a></p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Miraework Project" /><summary type="html"><![CDATA[close 버튼 누르지 말아라]]></summary></entry><entry><title type="html">PART 2 - 태스크 프롬프트</title><link href="https://unvictory2.github.io/prompt%20engineering/part2/" rel="alternate" type="text/html" title="PART 2 - 태스크 프롬프트" /><published>2024-09-18T00:00:00+00:00</published><updated>2024-09-18T00:00:00+00:00</updated><id>https://unvictory2.github.io/prompt%20engineering/part2</id><content type="html" xml:base="https://unvictory2.github.io/prompt%20engineering/part2/"><![CDATA[<h2 id="chapter-4---llm의-기본-기능을-고려한-기법">📝CHAPTER 4 - LLM의 기본 기능을 고려한 기법</h2>

<p>###</p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Prompt Engineering" /><summary type="html"><![CDATA[프롬프트 엔지니어링 - 챗GPT, 바드, 빙, 하이퍼클로바X까지 한 권으로 끝내기]]></summary></entry><entry><title type="html">PART 1 - 프롬프트 엔지니어링의 이론적 패경</title><link href="https://unvictory2.github.io/prompt%20engineering/part1/" rel="alternate" type="text/html" title="PART 1 - 프롬프트 엔지니어링의 이론적 패경" /><published>2024-09-15T00:00:00+00:00</published><updated>2024-09-15T00:00:00+00:00</updated><id>https://unvictory2.github.io/prompt%20engineering/part1</id><content type="html" xml:base="https://unvictory2.github.io/prompt%20engineering/part1/"><![CDATA[<h2 id="chapter-1---프롬프트-엔지니어링은-질문을-잘하는-것이-아니다">📝CHAPTER 1 - 프롬프트 엔지니어링은 질문을 잘하는 것이 아니다</h2>

<h3 id="프롬프트의-정의">프롬프트의 정의</h3>
<ul>
  <li>프롬프트의 본래 정의 : 컴퓨터가 명령을 받을 준비가 됐을 때 사용자에게 띄우는 문구</li>
  <li>업계의 통설적 정의 : 사람이 AI에게 제공하는 입력 문구</li>
</ul>

<p>프롬프트 엔지니어링은 질문을 잘하는 법이라고 알려져 있지만, 본래 프롬프트의 정의를 적용해보면 <strong>좋은 질문</strong>을 하는 법이 아니라, <strong>좋은 답변</strong>을 얻는 방법이라고 볼 수 있다.</p>

<h3 id="목표">목표</h3>
<p>어느 쪽 정의든 결과적으로 다음 프로세스를 따른다는 점에서는 완전히 같다.</p>
<ol>
  <li>AI에 제공할 명령어를 설계</li>
  <li>이를 토대로 AI로부터 더 유용한 반응(답변)을 유도</li>
</ol>

<p>업계의 통설적 정의에 따르면 “그 이후 더 좋은 방법론을 탐구하고 체계적으로 정리”하는 과정이 필요하나 본래 정의에서는 필요하지 않음. 본래 정의에서는 필요한 만큼의 효용성만 달성되면 충분하다고 보기 때문. 앞으로의 내용에선 2번 과정에 집중할 예정이다.</p>

<p><br /></p>

<h2 id="chapter-2---모든-것은-어텐션으로부터-시작되었다">📝CHAPTER 2 - 모든 것은 어텐션으로부터 시작되었다</h2>

<h3 id="어텐션-attention">어텐션 (Attention)</h3>
<ul>
  <li>챗GPT, 바드, 라마, 람다, 코파일럿 등의 AI들은 전부 구글이 개발한 <u>트랜스포머</u>라는 AI 기술을 이리저리 개조해서 만들어진 AI</li>
  <li>이 트랜스포머는 <u>어텐션</u>이라는 기술을 바탕으로 만들어짐</li>
  <li>즉 현대의 초거대 AI는 태생적으로 어텐션의 특징을 계승</li>
</ul>

<p>참고로 이건 2023년 10월 책이라 그런지 바드가 시연회에서 할루시네이션을 보였다는 건 써있으나 Gemini에 대한 건 써있지 않다.</p>

<h3 id="원리와-쓸모">원리와 쓸모</h3>
<p>어텐션을 수학적으로 설명하면 매우 어려우나, 우리가 영어 독해를 하는 과정에 비유하면 쉽다 : 중요해 보이는 부분에 동그라미를 치고, 뒷부분을 읽고 와서 앞부분과 이어 붙이고 등의 과정이 어텐션이다. (중요해 보이는 내용을 표시하고 요약하는 과정을 비유한듯)</p>

<p>그럼 어텐션은 왜 쓸모 있는 걸까? AI가 대량의 텍스트를 읽고 이해하는데 큰 도움이 되기 때문이다. 한 페이지 분량의 내용을 읽고 기억할 수 있는 AI가 있다고 가정하자. 이 AI에게 몇십권 분량의 글을 모두 읽고 기억하게 한다면 정상적으로 동작하지 않을 거다. 하지만 책을 처음부터 끝까지 모두 읽기 보다는, <u>가볍게 훑어보며 중요해보이는 부분에만 표시하며 내용을 압축</u>하게 하면 어떨까? 나중에 이 정보가 필요할 때 미리 압축해둔 내용을 빠르게 읽고 올 수 있다. 이게 바로 어텐션의 역할이다.</p>

<p>AI는 내가 제공한 정보뿐만 아니라 검색 결과로 나온 정보에 대해서도 어텐션을 실시한다. 또 챗GPT의 경우 대답을 할 때 어텐션을 이용해 지금까지의 대화를 빠르게 훑고 온다. 이렇듯 AI의 뛰어난 성능의 기반에는 어텐션이 있다.</p>

<p><br /></p>

<h2 id="chapter-3---당신은-llm과-그-사용법을-오해하고-있다">📝CHAPTER 3 - 당신은 LLM과 그 사용법을 오해하고 있다</h2>

<h3 id="할루시네이션은-잘못된-걸까">할루시네이션은 잘못된 걸까?</h3>
<ul>
  <li>할루시네이션 : AI가 잘못된 정보를 마치 진실처럼 전달하는 현상</li>
  <li>챗GPT나 바드 같은 AI를 제작하는 과정에서 지식을 체계적으로 주입하고 암기시키는 과정은 존재하지 않는다.</li>
  <li>LLM은 인간이 언어를 사용하는 방식에 대해 이해하고 학습한 AI지, 지식을 정확하게 전달하기 위해 만들어진 AI가 아니다.</li>
</ul>

<h3 id="ai의-지식-저장-방식">AI의 지식 저장 방식</h3>
<ul>
  <li>손실 압축 : 인간의 뇌가 정보를 저장하는 방법. 전체 정보 중 불필요한 부분은 버리고, 중요한 부분은 남기는 과정. 예를 들어 어제 먹은 수박의 줄무늬나 씨앗의 개수는 잊지만, 어떤 상황에서 먹었는지에 대한 관념은 기억한다.</li>
  <li>인코딩 : AI분야에서 손실 압축에 해당되는 개념. 담당하는 구조물은 인코더. 외부의 정보를 AI에 입력하는 과정을 의미하는데, AI의 추상화 능력과 이해력과 연관된다.</li>
  <li>디코딩 : 압축된 정보를 끄집어내어 표현하는 과정. AI의 작문 솜씨나 그림 솜씨와 연관돼있음. (표현력)</li>
</ul>

<h3 id="ai의-지식-저장-형태">AI의 지식 저장 형태</h3>

<p>가상 실험을 해보자.</p>
<ol>
  <li>딱 3개의 뉴런을 가지고 있는 가상의 벌레를 상상해보자.</li>
  <li>뉴런1은 단맛, 뉴런2는 신맛, 뉴런3은 아삭아삭한 식감에 반응한다.</li>
  <li>벌레는 사과, 수박, 딸기를 차례대로 먹는다. 반응한 뉴런은 1, 반응하지 않은 뉴런은 0이라고 부른다.</li>
  <li>
    <ul>
      <li>사과를 먹으면 시고 아삭 -&gt; <code class="language-plaintext highlighter-rouge">(0,1,1)</code></li>
      <li>수박을 먹으면 달고 아삭 -&gt; <code class="language-plaintext highlighter-rouge">(1,0,1)</code></li>
      <li>딸기를 먹으면 새콤달콤 -&gt; <code class="language-plaintext highlighter-rouge">(1,1,0)</code></li>
      <li>숫자 3개의 묶음으로 각 과일에 대한 정보를 손실 압축해냈다.</li>
    </ul>
  </li>
</ol>

<ul>
  <li>이 묶음을 각자 x,y,z축 좌표값으로 보면 <u>각 정보는 3차원 공간의 벡터값</u>이고, 레이턴트 벡터(latent vector)라고 부른다. 벡터가 놓이는 공간은 레이턴트 스페이스(latent space)라고 부른다. 인간의 뇌는 뉴런이 훨씬 더 많기 때문에 이 공간이 더 크다.</li>
  <li>비슷한 정보는 레이턴트 스페이스에서도 가까운 곳에 있고, 그 반대도 마찬가지다.</li>
  <li>디코더는 레이턴트 벡터의 정보를 우리가 이해할 수 있는 데이터로 팽창한다. 숫자들의 조합에서 그림을 그려내거나, 설명문을 작성하는 등.</li>
</ul>

<p>이를 응용한 추론 기능도 알아보자.</p>

<ol>
  <li>벌레에게 모르는 음식을 먹였는데 반응이 <code class="language-plaintext highlighter-rouge">(1,0,1)</code>이다.</li>
  <li><code class="language-plaintext highlighter-rouge">(1,0,1)</code>이면 수박이라고 추론할 수 있다. -&gt; 새 정보가 레이턴트 스페이스의 어디에 위치하는 벡터인지를 토대로 정보를 추론할 수도 있다.</li>
  <li>하지만 치킨을 먹었어도 <code class="language-plaintext highlighter-rouge">(1,0,1)</code>이라는 신호가 떴을 거다. 즉 벌레는 치킨과 수박을 구분할 수 없다.</li>
  <li>매콤함이나 느끼함 등을 구분하는 뉴런이 없기 때문에 구분하지 못한다. ( = 뇌세포의 개수가 적다, 레이턴트 스페이스의 부피가 너무 작다)</li>
</ol>

<p>이에 대한 해결 방안은?</p>
<ul>
  <li>OpenAI : 뇌세포가 많으면 AI의 성능이 올라갈 거다.</li>
  <li>메타 : 부피도 중요하지만 설계 자체를 세밀하게 하는 게 더 중요하다.</li>
</ul>

<h3 id="ai-산업의-역사">AI 산업의 역사</h3>
<ol>
  <li>2013 : 구글의 <code class="language-plaintext highlighter-rouge">Word2Vec</code>
    <ul>
      <li>빈칸 맞추기 퀴즈와 어울리는 단어 찾기 퀴즈 두 개로 단어의 의미 학습.</li>
      <li>어떤 빈칸에 어떤 단어가 오면 좋겠다던가, 비슷한 구조의 문장에서 자주 등장하는 유사한 의미의 단어에 대한 정보 등을 레이턴트 스페이스에 벡터 형태로 표시.</li>
      <li>문장을 입력 받음 &gt; 인코더로 손실 압축 &gt; 관심 단어의 의미만 벡터로 압축</li>
    </ul>
  </li>
  <li>2014 : 구글의 <code class="language-plaintext highlighter-rouge">Seq2Seq</code>
    <ul>
      <li>단어를 넘어 문장의 의미를 통째로 이해 가능.</li>
      <li>인코더-디코더 구조 : 문장 입력 &gt; 인코더 손실 압축 &gt; 벡터화 &gt; 디코더 압축 해제 &gt; 문장 출력</li>
      <li>이 구조는 <u>현대의 LLM까지 그대로 계승</u>된 철학이다.</li>
    </ul>
  </li>
  <li>어텐션
    <ul>
      <li>용량의 한계가 있었으나 위에서 설명한 어텐션의 등장으로 해결했다.</li>
      <li>인코더나 디코더에 어텐션을 사용해 획기적으로 좋은 결과물을 얻어냈다.</li>
    </ul>
  </li>
  <li>2017 : 구글의 <code class="language-plaintext highlighter-rouge">Transformer</code> (GPT의 T)
    <ul>
      <li>‘그냥 인코더와 디코더의 개수를 늘리고, 전부 어텐션을 붙이면 이해력과 표현력이 좋아지지 않을까?’라는 발상을 구현한 AI.</li>
      <li>Seq2Seq에 비해서 경이로운 성능을 보여줌, 현대 LLM들이 죄다 트랜스포머를 사용하는 게 그 반증.</li>
    </ul>
  </li>
  <li>2018 : OpenAI의 <code class="language-plaintext highlighter-rouge">GPT</code>와 구글의 <code class="language-plaintext highlighter-rouge">BERT</code>
    <ul>
      <li>GPT는 디코더(표현력)만 쌓아놓은 AI, BERT는 인코더(이해력)만 쌓아놓은 AI.</li>
      <li>BERT의 성능이 압도적이었다.</li>
    </ul>
  </li>
  <li>2020 : OpenAI의 <code class="language-plaintext highlighter-rouge">GPT-3</code>
    <ul>
      <li>BERT의 논문에는 “AI의 부피를 두 배 키웠더니 성능은 5%밖에 증가하지 않더라”는 말이 있었기에, AI의 부피보다는 설계를 잘 하는 게 중요하다고 생각하는 게 합리적이다.</li>
      <li>그러나 OpenAI는 부피를 늘리면 성능이 증가하기는 한다는 걸 보고 BERT보다 583배 큰 GPT-3를 만들었다.</li>
      <li>성능은 고작 몇 퍼센트 차이지만, 이를 기반으로 만들어진 챗GPT의 파급력을 보면 효율은 별로여도 무시할만한 차이는 아닌듯하다.</li>
      <li>이런 AI를 초거대 AI라고 부르며 LLM 역시 초거대 AI의 일종이다.</li>
    </ul>
  </li>
</ol>

<h3 id="pre-training이란">Pre-Training이란?</h3>
<ul>
  <li>GPT는 <code class="language-plaintext highlighter-rouge">Generative Pre-trained Transformer</code>의 약자</li>
  <li><code class="language-plaintext highlighter-rouge">Generative</code>는 뭔가를 생성한다는 뜻이고, <code class="language-plaintext highlighter-rouge">Transformer</code>는 위에서 나온 구글의 AI</li>
  <li><code class="language-plaintext highlighter-rouge">Pre-trained</code>란 어떤 분야의 매우 깊은 경험을 가진 사람을 데려다가 비슷하지만 약간은 다른 임무에 투입하는 것. 책에선 소바 삶기와 스파게티 삶기가 예시로 나온다.</li>
  <li>GPT나 웬만한 다른 LLM들은, 언어와는 관련이 있지만 채팅과는 무관한 임무에서 경력을 쌓고 채팅에서 활용된다.</li>
</ul>

<p>그럼 뭘로 경력을 쌓는 걸까? 2013년부터 하던 단어 퀴즈와 크게 다르지 않다.<br />
문장의 일부를 트랜츠포머에게 보여주고 다음에 올 단어로 올바른 단어를 맞추게 한다. 이 과정에서도 어텐션이 작동한다.</p>
<ul>
  <li>원본 문장 : 강아지는 식탐이 많은 동물이다.</li>
  <li>1단계 : 강아지는 ??? 인 상황 : GPT가 그 뒤에 오는 단어는 <code class="language-plaintext highlighter-rouge">식탐이</code>라고 예측</li>
  <li>2단계 : 강아지는 식탐이 ??? 인 상황 : <code class="language-plaintext highlighter-rouge">많은</code>이 와야 한다고 예측</li>
  <li>3단계 : 강아지는 식탐이 많은 ??? 인 상황 : <code class="language-plaintext highlighter-rouge">동물이다</code>가 와야 한다고 예측</li>
</ul>

<p>이 과정에서 인간이 단어를 나열하는 순서에 숨겨진 문법 구조와 논리 전개 순서를 학습한다. 이런 단어 퀴즈를 1000억 원이 넘는 슈퍼컴퓨터로 매월 전기세만 50억 이상 지출하면서 1년 내내 단어 퀴즈를 풀고 있는 거다.</p>

<p>그 결과 <u>다음에 올 단어를 기가 막히게 잘 맞히는 AI</u>가 만들어지고 이게 채팅을 하면 챗GPT가 된다.<br />
<u>AI가 지식을 따로 암기하거나 공부하는 과정은 없으며,</u> 방대한 텍스트를 학습하다 보니 덩달아 학습하게 된 것 뿐이다. 그 흔적은 희석되어 레이턴트 스페이스 위에 남아 있어 우리의 질문에 그럴싸한 답을 생성해낸다.</p>

<p>즉 LLM의 본질은 :</p>
<ul>
  <li>척척박사 아님</li>
  <li>인간의 언어를 굉장히 잘 이해한 AI</li>
  <li>어텐션에 의존하는 특징이 있어 한계도 있음</li>
</ul>

<p>프롬프트 엔지니어링은 이를 이해하고 어텐션과 관련된 특징을 활용하여 나은 결과를 만들어내는 AI 활용 방법이다.</p>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Prompt Engineering" /><summary type="html"><![CDATA[프롬프트 엔지니어링 - 챗GPT, 바드, 빙, 하이퍼클로바X까지 한 권으로 끝내기]]></summary></entry><entry><title type="html">[미래일경험 프로젝트] 패키지 직접 수정하기</title><link href="https://unvictory2.github.io/miraework%20project/customizing-package/" rel="alternate" type="text/html" title="[미래일경험 프로젝트] 패키지 직접 수정하기" /><published>2024-08-20T00:00:00+00:00</published><updated>2024-08-20T00:00:00+00:00</updated><id>https://unvictory2.github.io/miraework%20project/customizing-package</id><content type="html" xml:base="https://unvictory2.github.io/miraework%20project/customizing-package/"><![CDATA[<p><img src="https://github.com/user-attachments/assets/109e680f-6cb7-4bc9-85db-60faed944403" alt="question" /></p>

<p>이 방법은 흔치 않은 방법이라고 하셔서 PR이나 Issues를 사용한 방법을 사용하려 했는데 전혀 받아들여질 기미가 보이지 않았다. 다른 패키지를 찾기에는 이미 시간도 에너지도 부족했고…<br />
어쨌든 수정 후 적용하는 방식은</p>
<ul>
  <li>패키지 fork &gt; 수정 &gt; 해당 리포지토리 주소로 import</li>
  <li>소스코드 다운 &gt; 수정 &gt; 프로젝트 디렉토리 내부에 넣어서 그 주소를 import</li>
</ul>

<p>이렇게 2가지로 보이는데 나는 후자로 선택했다. 직접 내 프로젝트에 포함시키는 방법인만큼 큰 패키지라면 하기 부담스러운 방법일듯 하다. 진행 방법은 생각보다 굉장히 간단하다.</p>

<ol>
  <li>원하는 패키지의 깃허브로 간다. 주로 소개글이 있는 곳에 깃허브 주소도 같이 있다.</li>
  <li>초록색 Code 버튼을 누르고 Download Zip으로 받아서, 압축을 푼다.</li>
  <li>원하는 수정을 한다.</li>
  <li>패키지를 내 프로젝트 디렉토리 안 아무데나 넣는다. 나는 루트 디렉토리에 <code class="language-plaintext highlighter-rouge">local_packages</code>라는 폴더를 만들고 그 안에다 넣었다. 구조는 다음과 같다.</li>
</ol>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>📦desktop_widget
 ┣ 📂📜내 프로젝트의 파일들
 ┣ 📜pubspec.yaml
 ┗ 📂local_packages
   ┗ 📂flutter_calendar_view-master
     ┣ 📂📜해당 패키지 파일들
     ┗ 📜pubspec.yaml
</code></pre></div></div>
<ol>
  <li>루트의 <code class="language-plaintext highlighter-rouge">pubspec.yaml</code>로 가서 다음과 같이 calendar_view의 경로를 수정한다. 이 파일은 인덴트에 민감하니 잘 맞춰준다. 이 코드로 인해 해당 경로에서 <code class="language-plaintext highlighter-rouge">name: calendar_view</code>라는 내용을 가지고 있는 <code class="language-plaintext highlighter-rouge">pubspect.yaml</code> 파일을 찾게 된다. 이게 끝이다!
    <div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">dependencies</span><span class="pi">:</span>
  <span class="na">flutter</span><span class="pi">:</span>
<span class="err"> </span><span class="na">sdk</span><span class="pi">:</span> <span class="s">flutter</span>
  <span class="s">calendar_view</span><span class="err">:</span>
 <span class="na">path</span><span class="pi">:</span> <span class="s">./local_packages/flutter_calendar_view-master/</span>
</code></pre></div>    </div>
  </li>
</ol>]]></content><author><name>unVictory2</name><email>seungeon7878@gmail.com</email></author><category term="Miraework Project" /><summary type="html"><![CDATA[프로젝트 폴더 내부에 넣는 방법]]></summary></entry></feed>