<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>byungju.log</title>
        <link>https://velog.io/</link>
        <description>개발 외의 일들에 더 흥미를 가지는 개발자. Interested in Web, Generative AI, UI/UX.</description>
        <lastBuildDate>Sat, 13 Apr 2024 06:57:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>byungju.log</title>
            <url>https://images.velog.io/images/byungjur_96/profile/60a59e3d-7c3e-4c15-b47a-2fc74abb4bf2/52337578_2327130663986839_3432702871311745024_o.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. byungju.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/byungjur_96" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[SDS (Score Distillation Sampling) Loss]]></title>
            <link>https://velog.io/@byungjur_96/SDS-Score-Distillation-Sampling-Loss</link>
            <guid>https://velog.io/@byungjur_96/SDS-Score-Distillation-Sampling-Loss</guid>
            <pubDate>Sat, 13 Apr 2024 06:57:44 GMT</pubDate>
            <description><![CDATA[<h2 id="overview">Overview</h2>
<ul>
<li>Google Research에서 연구한 <a href="https://dreamfusion3d.github.io/">DreamFusion</a>(ICLR ‘23)에서 처음 제안됨</li>
<li>Text-to-3D Generation Model에서 사용하는 Diffusion Model 기반의 score Loss</li>
<li>2D Diffusion Model이 parametric image generator의 prior로 작동하는 Probability Density distillation에 기반한 Loss</li>
<li>DreamFusion의 architecture에서 오른쪽 부분과 관련된 Loss Function
<img src="https://velog.velcdn.com/images/byungjur_96/post/06aca10c-4a08-49ae-8972-3cf635e24f0c/image.png" alt=""></li>
</ul>
<h2 id="introduction">Introduction</h2>
<ul>
<li>3D Data Synthesis를 위해서는 1. 학습을 위한 큰 규모의 labeled 3D data 2. 3D Denoising architecture가 필요하지만 둘 다 존재 X</li>
<li>기존 Diffusion Model : 학습 데이터와 같은 종류/차원(Pixel Space)에서 Sampling을 수행함</li>
<li>Goal : Create 3D Models that look like good images when rendered from random angles<ul>
<li>3D Model로는 DIP(입력받은 $$\theta$$ 를 이미지로 만들어주는 generator)를 사용</li>
</ul>
</li>
<li>3D Model의 output $$x=g(\theta)$$이 diffusion model의 샘플처럼 보이도록 Diffusion Model의 구조를 이용하여 parameter $$\theta$$를 최적화함</li>
</ul>
<h2 id="method">Method</h2>
<ul>
<li><p>Data point $$x=g(\theta)$$에 대해 loss를 최소화하는 방법</p>
<ul>
<li>$$\theta^*=argmin_{\theta}\left[\mathcal{L}<em>{diff}(\phi,x=g(\theta))\right]$$ ($\mathcal{L}</em>{diff}$: Diffusion Model의 Loss)</li>
</ul>
</li>
<li><p>BUT, 실험 결과 realistic한 sample을 생성하지 못함</p>
</li>
<li><p>Gradient of $$\mathcal{L}_{diff}$$
<img src="https://velog.velcdn.com/images/byungjur_96/post/b87673e7-de3a-4246-a64b-0bc3b6278f18/image.png" alt=""></p>
<ul>
<li>U-Net Jacobian Term은 계산 비용도 너무 크고 작은 noise 차이에 따라 좌우된다 
→ 생략하는 것이 DIP를 최적화하는 데 효과적임</li>
</ul>
</li>
</ul>
<ul>
<li>$\nabla_\theta \mathcal{L}<em>{SDS}(\phi, x=g(\theta)) \triangleq \mathbb{E}</em>{t, \epsilon} \left[ w(t) (\hat{\epsilon}_\phi(z_t;y,t)-\epsilon)\frac{\partial x}{\partial\theta} \right]$<ul>
<li>$x$ : NeRF로 생성된 이미지 (입력 이미지 X)</li>
<li>$g(\theta)$ : NeRF parameter θ를 가진 differentiable generator</li>
<li>$y$ : Text Embedding 값 (Image-to-3D의 경우 입력 이미지를 넣으면 됨) → condition이라고 볼 수 있음</li>
<li>$z_t = \alpha_t g(\theta) + \sigma_t\epsilon$</li>
</ul>
</li>
<li>Diffusion Model에서 학습된 score function을 이용한 weighted probability density distillation loss(<a href="https://arxiv.org/abs/1711.10433">논문</a>)의 gradient라고 볼 수 있음 (Appendix A.4)</li>
</ul>
<h2 id="code">Code</h2>
<ul>
<li>논문에 나온 수도 코드에 대한 설명
<img src="https://velog.velcdn.com/images/byungjur_96/post/d0fefc8b-e1fb-4457-a8c6-3388c415a557/image.png" alt=""></li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><code>github</code> DreamFusionAcc : Minimal PyTorch implementation of Dreamfusion [<a href="https://github.com/chinhsuanwu/dreamfusionacc">Link</a>]</li>
<li>[개념 정리] SDS (Score Distillation Sampling) Loss : Text-to-3D Loss [<a href="https://xoft.tistory.com/53">Link</a>]</li>
<li>Score Distillation Sampling [<a href="https://ostin.tistory.com/301">Link</a>]</li>
<li>[Paper Review] DreamFusion 논문 리뷰 [<a href="https://jaehoon-daddy.tistory.com/92#recentEntries">Link</a>]</li>
<li>[논문리뷰] DreamFusion: Text-to-3D using 2D Diffusion [<a href="https://jang-inspiration.com/dreamfusion#7abd2a0172be4768b532e4f4edd99190">Link</a>]</li>
<li>PR-416: DreamFusion [<a href="https://www.youtube.com/watch?v=IAvMfXRTFKk&amp;ab_channel=ScenetheElla">Link</a>]</li>
<li>[논문 리뷰] Dreamfusion : Text to 3D using 2d diffusion [<a href="https://youtu.be/PPr9kCtsVFs?si=4NbdIuLGrlEfWdKK">Link</a>]</li>
<li>Differentiable Image Parameterizations [<a href="https://distill.pub/2018/differentiable-parameterizations/">Link</a>]</li>
<li>[논문리뷰] Parallel WaveNet: Fast High-Fidelity Speech Synthesis (ICML18) [<a href="https://music-audio-ai.tistory.com/19">Link</a>]</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ngrok]]></title>
            <link>https://velog.io/@byungjur_96/ngrok</link>
            <guid>https://velog.io/@byungjur_96/ngrok</guid>
            <pubDate>Mon, 17 Oct 2022 15:56:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>외부 인터넷망에서 간단하게 localhost로 접속하도록 도와주는 ngrok 사용 방법</p>
</blockquote>
<h2 id="1-ngrok란">1. ngrok란?</h2>
<p><code>ngrok</code> 란 외부 인터넷 망에서 로컬 PC로 접속하는 방법을 제공하는 툴이다. 
설치 페이지에는 &#39;secure tunnels to localhost&#39;라고 설명되어 있다.
일반적으로 외부 인터넷 망에서 로컬 PC로 접속할 때에는 방화벽 때문에 보안 상의 문제도 있고, 신경써야 할 점들이 존재한다.
하지만 <code>ngrok</code> 를 사용하면 그런 부분을 신경쓰지 않고 평소 로컬 PC에서 작업을 하던 프로세스 그대로 외부 인터넷 망으로 공유할 수 있다는 장점이 있다.</p>
<h2 id="2-ngrok-설치-방법">2. ngrok 설치 방법</h2>
<p>설치 방법은 매우 간단하다.
<a href="https://dashboard.ngrok.com/get-started/setup">공식 사이트</a>에 접속하여 운영체제에 맞는 버전을 다운받아주면 된다.
리눅스나 맥의 경우에는 command line을 이용하여 설치가 가능하다.</p>
<pre><code class="language-bash"># linux : snap으로 설치
sudo snap install ngrok

# mac : brew로 설치
brew install --cask ngrok</code></pre>
<p>이때 brew 사용 시 <code>--cask</code> 옵션을 사용하면 GUI 어플리케이션을 설치한다.</p>
<h2 id="3-ngrok-사용-방법">3. ngrok 사용 방법</h2>
<p>사용방법 역시 간단하다.
<code>localhost</code> 에서 3000번 포트를 사용하고 있을 때, 아래 명령어를 사용하면 된다.</p>
<pre><code class="language-bash">ngrok http 3000</code></pre>
<p><img src="https://velog.velcdn.com/images/byungjur_96/post/3b34afa9-611d-4571-8ed8-c78a545a00f0/image.png" alt="">
그러면 위와 같은 창이 뜨는 것을 알 수 있다.
여기서 &#39;Forwarding&#39;에 표시된 주소로 접속하면 외부 인터넷망에서도 접속이 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/byungjur_96/post/91b7db4d-fea8-4042-8d80-99c8f2dde824/image.png" alt="">
&#39;Web Interface&#39;는 ngrok에서 받은 http request에 대한 내용과 접속 로그를 확인할 수 있다.
<img src="https://velog.velcdn.com/images/byungjur_96/post/71ea274f-82f1-49b4-8df4-c8de37182e1f/image.png" alt="">
request에 대한 inspect 뿐만 아니라 <code>ngrok</code>의 설정 옵션과 접속 속도와 같은 status 정보도 확인이 가능하다.
Web Interface의 경우 default 포트는 <code>4040</code> 이다.</p>
<p>참고로 기본적인 세션 유지시간은 2시간이다.
만약 세션이 더 길게 필요한 경우, <code>ngrok</code> 사이트에 가입하여 인증 토큰을 발급받으면 세션 시간 제한 없이 사용이 가능하다.
<img src="https://velog.velcdn.com/images/byungjur_96/post/94ae6e98-9f8a-41ef-8926-4f4a225bd7bd/image.png" alt=""></p>
<p>사이트 가입은 어렵지 않으며, 사이트 가입이 완료되면 &#39;AuthToken&#39; 탭에서 토큰을 확인할 수 있다.
토큰을 발급 받고 아래 명령어를 이용하면 세션이 만료되지 않는 <code>ngrok</code> 를 사용할 수 있다.</p>
<pre><code class="language-bash">ngrok http 3000 --authtoken [AuthToken]</code></pre>
<p><img src="https://velog.velcdn.com/images/byungjur_96/post/49d852ba-7e18-42bd-b5d3-11153098cfa9/image.png" alt="">
위의 명령어를 사용했을 때는 Session Expires와 같은 정보 대신에 Account 정보가 뜨는 것을 확인할 수 있다.</p>
<h2 id="4-마무리">4. 마무리</h2>
<p><code>ngrok</code>의 경우 웹 개발 과정에서 디자이너나 기획자에게 진행 상황을 공유할 때 방화벽이나 보안에 대해 신경쓰지 않고 손쉽게 공유해줄 수 있는 툴이다.
실제 서비스에서 사용하는 것은 무리겠지만, 진행 중인 프로젝트를 간단히 팀원들에게 공유하기에 아주 좋은 툴이라고 생각한다.
추가적으로 <code>tmux</code>나 <code>pm2</code> 등을 이용하면 터미널 종료로 인한 세션 만료 걱정 없이 사용이 더 편리하다.
(단, <code>pm2</code> 는 예전에 썼었던 것 같은 가물가물한 기억이라 아닐 수도 있음...)</p>
<h2 id="참고자료">참고자료</h2>
<ul>
<li><a href="https://yunwoong.tistory.com/131">ngrok으로 외부에서 접속가능한 로컬 네트워크 환경 구성하기</a></li>
<li><a href="https://www.dongyeon1201.kr/1894e929-83f6-4c96-a130-a0fcc5a68888">ngrok</a></li>
<li><a href="https://blog.outsider.ne.kr/1159">ngrok으로 로컬 네트워크의 터널 열기</a></li>
<li><a href="https://tagilog.tistory.com/m/576">homebrew-cask란? 설치 방법과 사용법</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PyTorch] Anaconda에 커널 추가하기]]></title>
            <link>https://velog.io/@byungjur_96/PyTorch-anaconda-%EB%82%B4%EC%97%90-%EC%BB%A4%EB%84%90-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@byungjur_96/PyTorch-anaconda-%EB%82%B4%EC%97%90-%EC%BB%A4%EB%84%90-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 10 Jul 2022 13:43:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Anaconda 내에 Kernel을 추가해서 프로젝트 별로 패키지를 쉽게 관리하기</p>
</blockquote>
<h2 id="1-가상-환경-설치-및-활성화하기">1. 가상 환경 설치 및 활성화하기</h2>
<p>먼저 아나콘다 내에 생성되어 있는 가상 환경 목록을 확인해보자.
<code>conda env list</code> 명령어를 사용하면 가상 환경의 목록을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/byungjur_96/post/2554bde0-5031-4468-9ce2-9b327ac7ff29/image.png" alt="">
이제 새로운 가상 환경을 생성해보자. 
가상환경을 추가하려면 <code>conda create -n [가상환경 이름]</code> 명령어를 이용하면 된다.
일반적으로는 위의 명령어로 가상 환경이 새로 생성되지만, 아래와 같은 오류가 발생하는 경우가 있다.
<img src="https://velog.velcdn.com/images/byungjur_96/post/b52da335-0d81-4344-9d10-408a077aee67/image.png" alt=""></p>
<p>이때는 <code>source ~/opt/anaconda3/etc/profile.d/conda.sh</code> 명령어를 터미널에 입력해주면 된다.
<code>~/opt/anaconda3/</code> 는 각자 로컬에서<code>anaconda3</code> 폴더가 존재하는 디렉토리를 입력해주면 된다.
profile 변경 값을 conda shell script 파일에 적용하는 것이라고 한다.
사실 처음에는 &#39;왜 옛날에는 됐던 커맨드가 왜 안 되지? 바뀐건가?&#39; 이러면서 그냥 계속 했었는데, 지금 에러 메세지를 보니까 설명대로 차분히 진행했으면 됐을지도 모르겠단 생각이 든다.</p>
<p>참고자료 : <a href="https://gbjeong96.tistory.com/47">가상환경 실행오류</a></p>
<h2 id="2-jupyter-notebook에-가상환경-kernel-추가하기">2. jupyter notebook에 가상환경 kernel 추가하기</h2>
<p>Python 가상 환경을 만들어도 jupyter notebook 내에 kernel이 있어야 활용이 가능하다. 그러기 위해서 jupyter notebook에 가상환경 kernel을 추가해야 한다. 먼저 가상 환경을 활성화시킨다.</p>
<pre><code class="language-bash">conda activate [venv]</code></pre>
<p>이후 가상 환경 내에서 jupyter notebook을 설치한다.</p>
<pre><code class="language-bash">pip3 install ipykernel</code></pre>
<p>마지막으로 jupyter notebook에 가상 환경 kernel을 추가해주면 된다.</p>
<pre><code class="language-bash">python3 -m ipyternel install --user --name [venv] --display-name &quot;[kernel name]&quot;</code></pre>
<p> <code>[venv]</code> 자리에 가상 환경 이름을 입력하고, <code>[kernel name]</code> 자리에 Kernel 이름을 설정해주면 된다.
(<code>[kernel name]</code>의 경우 쌍따옴표로 감싸줘야 한다.)</p>
<p>가상 환경을 종료하는 방법은 다음과 같다.</p>
<pre><code class="language-bash">conda deactivate</code></pre>
<p>참고자료 : <a href="https://medium.com/@5eo1ab/jupyter-notebook%EC%97%90-%EA%B0%80%EC%83%81%ED%99%98%EA%B2%BD-kernel-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0-ed5261a7e0e6">jupyter notebook에 가상환경 kernel 추가하기</a></p>
<h2 id="3-macos에서-터미널을-이용하여-jupyter-notebook-실행하기">3. MacOS에서 터미널을 이용하여 jupyter notebook 실행하기</h2>
<p>기존에는 &#39;Anaconda Navigator&#39;를 사용하여 jupyter notebook을 실행시켰다.
그런데 다른 작업들은 대부분 터미널로 하면서 notebook 실행만 GUI를 이용한다는 게 번거롭게 느껴졌다.
그래서 찾아보니 <code>jupyter notebook</code> 명령어만으로 된다는데, 나는 실행이 안됐다.
결국 <code>python3 -m notebook</code> 명령어를 이용하여 jupyter를 실행시킬 수 있다.
MacOS의 차이인지, 내가 뭔가 설치를 안해서 그런지 모르겠지만 일단 후자를 통해서 잘 해결했다.</p>
<p>참고자료 : <a href="https://stackoverflow.com/questions/35313876/after-installing-with-pip-jupyter-command-not-found">After installing with pip, &quot;jupyter: command not found&quot;</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코딩 테스트 개요]]></title>
            <link>https://velog.io/@byungjur_96/%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%B6%9C%EC%A0%9C-%EA%B2%BD%ED%96%A5-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@byungjur_96/%EC%BD%94%EB%94%A9-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%B6%9C%EC%A0%9C-%EA%B2%BD%ED%96%A5-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Sat, 26 Jun 2021 05:14:12 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>코딩 테스트를 공부하면서 배운 내용들을 정리하는 게시물들입니다. 개인적인 정리 용도로 정리를 하는 것이기 때문에 참고용으로만 봐주시면 감사하겠습니다. 또한 참고한 자료들의 출처는 하단에 표기하였습니다. 좋은 자료를 제공해주시는 분들께 항상 감사드리며, 저작권 문제/내용 오류가 있다면 누구라도 자유롭게 이야기해주시면 감사하겠습니다.</p>
</blockquote>
<h2 id="1-코딩-테스트">1. 코딩 테스트</h2>
<h3 id="1-코딩-테스트의-유형">1) 코딩 테스트의 유형</h3>
<h4 id="i-온라인-코딩-테스트">i) 온라인 코딩 테스트</h4>
<ul>
<li>인터넷 검색을 허용</li>
<li>표준 라이브러리 사용법 검색 가능</li>
<li>초기 단계의 시험 </li>
</ul>
<h4 id="ii-오프라인-코딩-테스트">ii) 오프라인 코딩 테스트</h4>
<ul>
<li>인터넷 검색이 허용되지 않는 경우가 많음</li>
<li>온라인 코딩 테스트 이후에 진행되는 경우가 많음</li>
</ul>
<h3 id="2-코딩-테스트-팁">2) 코딩 테스트 팁</h3>
<ul>
<li>자신만의 소스 코드 관리하기</li>
<li>자신이 자주 사용하는 알고리즘 코드를 라이브러리화하기 -&gt; 팀노트! (<a href="https://github.com/ndb796/Python-Competitive-Programming-Team-Notes">예시</a>)</li>
</ul>
<h3 id="3-코딩-테스트-최신-출제-경향">3) 코딩 테스트 최신 출제 경향</h3>
<p>가장 출제 빈도가 높은 알고리즘 유형: 그리디, 구현, DFS/BFS
그외: 최단 경로, 다이나믹 프로그래밍, 그래프 이론, 이진 탐색, 정렬</p>
<h2 id="2-알고리즘-성능-평가">2. 알고리즘 성능 평가</h2>
<h3 id="1-복잡도">1) 복잡도</h3>
<ul>
<li><strong>알고리즘의 성능</strong>을 나타내는 척도 (시간 복잡도, 공간 복잡도)</li>
<li>복잡도가 낮을수록 좋은 알고리즘</li>
<li><em><strong>빅오 표기법(Big-O Notation)</strong></em> 을 이용하여 연산 횟수 측정 가능</li>
</ul>
<h3 id="2-알고리즘-설계-tip-python">2) 알고리즘 설계 Tip (Python)</h3>
<ul>
<li><p>일반적으로 연산 횟수가 5억을 넘어가는 경우 5~15초 가량이 소요</p>
</li>
<li><p>초당 2,000만 번의 연산을 진행한다고 생각하기</p>
</li>
<li><p>코딩 테스트 문제에서의 시간 제한은 통산 1~5초 사이
ex) 시간 제한이 1초인 문제의 경우</p>
<ul>
<li>N &lt; 500 : <em>O</em> (N^3)</li>
<li>N &lt; 2,000 : <em>O</em> (N^2)</li>
<li>N &lt; 100,000 : <em>O</em> (N <em>log</em> N)</li>
<li>N &lt; 10,000,000 : <em>O</em> (N)</li>
</ul>
</li>
<li><p>수행시간 측정 소스코드 예제</p>
<pre><code class="language-python">import time
start_time = time.time()  # 측정 시작
</code></pre>
</li>
</ul>
<h1 id="프로그램-소스-코드">프로그램 소스 코드</h1>
<p>end_time = time.time()  # 측정 종료
print(&quot;time:&quot;, end_time - start_time)  # 수행 시간 출력</p>
<p>```</p>
<h2 id="3-reference">3. Reference</h2>
<ol>
<li><strong>(이코테 2021 강의 몰아보기)</strong> 1.코딩 테스트 출제 경향 분석 및 파이썬 문법 부수기 [<a href="https://www.youtube.com/watch?v=m-9pAwq1o3w&amp;list=PLRx0vPvlEmdAghTr5mXQxGpHjWqSz0dgC&amp;index=2">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] 네비게이션 가드]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-%EB%84%A4%EB%B9%84%EA%B2%8C%EC%9D%B4%EC%85%98-%EA%B0%80%EB%93%9C</link>
            <guid>https://velog.io/@byungjur_96/vue.js-%EB%84%A4%EB%B9%84%EA%B2%8C%EC%9D%B4%EC%85%98-%EA%B0%80%EB%93%9C</guid>
            <pubDate>Wed, 13 Jan 2021 20:23:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>네비게이션 가드를 통해 잘못된 페이지 이동 시 리다이렉트/취소하여 Nativation을 보호하기</p>
</blockquote>
<h2 id="1-purpose">1. Purpose</h2>
<p>웹페이지 내에서 페이지 간의 이동을 할 때, URL에 따라서 유효하지 않은 URL인 경우가 있을 수 있다. 몇 가지 상황에 따라 예시를 분류하자면,</p>
<ol>
<li><p>먼저 <a href="https://router.vuejs.org/kr/guide/essentials/dynamic-matching.html">동적 라우트 매칭</a>을 통해 컴포넌트로 이동하는 경우, 상황에 따라 올바르지 않은 자료형 or 범위의 parameter를 임의로 입력할 수도 있다. 예를 들어 <code>https://example.com/history/&lt;year&gt;</code> 라는 주소를 생각해보자. parameter로 연도를 받아서 그 값에 따라 데이터를 불러오는 화면이라면, parameter로 문자열이 들어온다면(ex. <code>https://example.com/history/hello</code> ) 제대로 된 데이터를 불러올 수 없을 것이다.  </p>
</li>
<li><p>흔한 경우는 아니지만, 만약 페이지 이동 시에 이동 전 화면에 따라 다음 화면에서 표시하는 내용이 달라질 수도 있다.</p>
</li>
<li><p>그 외에도 특정 화면에 대한 접근 권한을 체크할 때에도 많이 사용한다고 한다.</p>
</li>
</ol>
<p>위와 같이 내가 공부한 바로는 크게 3가지 정도의 경우로 나눌 수 있을 것 같다.</p>
<h2 id="2-usage">2. Usage</h2>
<p>네비게이션 가드의 종류는 크게 3가지로 나눌 수 있다. 각각에 대해서 조금 더 자세히 알아보자. 이때 각각의 예시는 [1]Vue Router 공식 문서를 참고하였다.</p>
<h3 id="1-전역-가드">1) 전역 가드</h3>
<p>전역 가드는 &#39;전역(Global)&#39;이라는 단어가 개발 분야에서 일반적으로 사용되는 것처럼 모든 네비게이션에 대해 발생되는 네비게이션 가드이다. 즉, 페이지 이동이 발생할 때마다 실행되는 코드라고 보면 될 것 같다.</p>
<pre><code class="language-javascript">const router = new VueRouter({ ... })

router.beforeEach((to, from, next) =&gt; {
  // ...
})</code></pre>
<p>위에서처럼 <code>beforeEach</code> 라는 메서드를 통해서 실행되며, 이 메서드는 3개의 parameter가 있다. <code>to</code> 의 경우 현재의 라우트, 즉 네비게이션을 통해 이동할 객체를 의미한다. <code>from</code> 의 경우는 현재 라우트로 오기 전 라우트를 의미한다. <code>from</code> 과 <code>to</code> 모두 자료형은 라우트 객체이다. <code>next()</code> 는 &#39;hook을 해결하기 위해&#39; 반드시 호출되어야 한다. &#39;hook을 해결한다&#39;는 표현은 조금 추상적으로 이해가 된다. 대략적으로 이해한 바에 따르면, 유저의 사용 흐름 상에서 네비게이션 자체는 일시정지, <code>next()</code> 는 다시 재생하기 정도의 기능으로 이해하면 되지 않을까 싶다. <code>next()</code> 를 parameter 없이 사용한다면, 이동하려고 했던 라우트로 이동하지만, 만약 인자를 전달한다면 (ex. <code>next(&#39;/&#39;)</code> , <code>next({ path: &#39;/&#39; })</code>) 해당 라우트로 리다이렉트 한다. 이 경우 새로운 네비게이션이 시작된다고 한다. 그 외에도 <code>next(false)</code> 와 같이 인자로 <code>false</code> 값을 전달하면 <code>from</code> 의 라우트로 다시 이동하게 된다. 아마 접근 권한 등을 확인할 때 사용하지 않을까 싶다(?)</p>
<h3 id="2-라우트-별-가드">2) 라우트 별 가드</h3>
<p>전역 가드와 다르게 특정 라우트 객체에 대해서만 네비게이션 가드를 설정할 수 있다. 이 경우 <code>beforeEnter</code> 를 사용한다. 사용 방법의 경우 전역 가드와 동일하다.</p>
<pre><code class="language-javascript">const router = new VueRouter({
  routes: [
    {
      path: &#39;/foo&#39;,
      component: Foo,
      beforeEnter: (to, from, next) =&gt; {
        // ...
      }
    }
  ]
})</code></pre>
<h3 id="3-컴포넌트-내부-가드">3) 컴포넌트 내부 가드</h3>
<p>라우트 별 가드와 유사하면서도 조금씩 다르다. <code>beforeRouteEnter</code> 나 <code>beforeRouteLeave</code> 를 컴포넌트 안에 직접 정의하여 네비게이션 가드를 사용할 수 있다.</p>
<pre><code class="language-javascript">const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 이 컴포넌트를 렌더링하는 라우트 앞에 호출됩니다.
    // 이 가드가 호출 될 때 아직 생성되지 않았기 때문에
    // `this` 컴포넌트 인스턴스에 접근 할 수 없습니다!
  },
  beforeRouteLeave (to, from, next) {
    // 이 컴포넌트를 렌더링하는 라우트가 이전으로 네비게이션 될 때 호출됩니다.
    // `this` 컴포넌트 인스턴스에 접근 할 수 있습니다.
  }
}</code></pre>
<p>하지만 <code>beforeRouteEnter</code> 의 경우 컴포넌트 생성 이전이기 때문에 <code>this</code> 에 접근을 할 수는 없다. 이 경우, <code>next()</code> 함수에서의 콜백을 통해 인스턴스에 접근할 수 있다.</p>
<pre><code class="language-javascript">beforeRouteEnter (to, from, next) {
  next(vm =&gt; {
    // `vm`을 통한 컴포넌트 인스턴스 접근
  })
}</code></pre>
<p>반대로 이름과 라이프 사이클을 생각하면 당연하지만, <code>beforeRouteLeave</code> 에서는 <code>this</code> 에 직접 접근할 수 있다. 주로 사용자가 저장하지 않은 편집 내용을 두고 실수로 페이지를 이동하는 것을 방지하는데 사용된다고 한다.</p>
<h3 id="cf-parameter-변경-사항에-반응하기">cf. parameter 변경 사항에 반응하기</h3>
<p>동적 라우트 매칭에서 parameter만 변경되는 경우, 컴포넌트의 라이프 사이클 훅이 호출되지 않는다. 따라서 네비게이션 가드 중 하나인 <code>beforerouteUpdate</code> 를 사용하면 새로운 훅을 만들 수 있다.</p>
<pre><code class="language-javascript">const User = {
  template: &#39;...&#39;,
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don&#39;t forget to call next()
  }
}</code></pre>
<h2 id="3-reference">3. Reference</h2>
<ol>
<li><strong>(공식 문서)</strong> 네비게이션 가드 [<a href="https://router.vuejs.org/kr/guide/advanced/navigation-guards.html">link</a>]</li>
<li>네비게이션 가드 [<a href="https://beomy.tistory.com/75">link</a>]</li>
<li><strong>(공식 문서)</strong> 동적 라우트 매칭 - Params 변경 사항에 반응하기 [<a href="https://router.vuejs.org/kr/guide/essentials/dynamic-matching.html#params-%EB%B3%80%EA%B2%BD-%EC%82%AC%ED%95%AD%EC%97%90-%EB%B0%98%EC%9D%91%ED%95%98%EA%B8%B0">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] 컴포넌트/엘리먼트 re-rendering 하는 법]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%98%EB%A6%AC%EB%A8%BC%ED%8A%B8-re-rendering-%ED%95%98%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@byungjur_96/vue.js-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%98%EB%A6%AC%EB%A8%BC%ED%8A%B8-re-rendering-%ED%95%98%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Wed, 13 Jan 2021 18:58:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Vue 프로젝트에서 컴포넌트, 혹은 HTML 엘리먼트를 re-rendering하는 방법</p>
</blockquote>
<h2 id="1-purpose">1. Purpose</h2>
<p>이번에 진행한 프로젝트의 경우 여러 개의 작품들을 전시하는 서비스였는데, 크게 2가지 카테고리로 분류되며 각 카테고리에는 여러 작품들이 포함되었다. 각 카테고리 별로 작품을 구분하며 카테고리 이름을 클릭하면 해당 카테고리 내의 작품들의 목록이 나타나는 형식이었는데, 어떤 경우 작품들의 목록이 제대로 업데이트되지 않는 경우가 발생하였다. 분명 화면에 표시되는 목록들의 정보가 저장되어 있는 Array의 데이터는 업데이트가 제대로 되었는데, HTML 엘리먼트들이 업데이트되지 않았다. 이를 해결하기 위해 Vue 내에서 특정 상황에 HTML 요소를 업데이트할 수 있는 방법을 찾아보게 되었다.</p>
<h2 id="2-usage">2. Usage</h2>
<p>정말 간단하다! 각 element(혹은 component)에 <code>key</code> 값을 바인딩해주면 된다. Vue에서는 HTML 요소의 <code>key</code> 값이 변경되는 경우 해당 요소를 업데이트한다. 아래 예시를 통해 조금 더 직관적으로 이해해보자.</p>
<ol>
<li><code>lst</code> 라는 Array에는 작품의 이름들이 저장되어 있으며, <code>v-for</code> 를 통해 각 작품들의 이름이 화면에 표시된다고 가정하자.</li>
</ol>
<pre><code class="language-html">    &lt;!-- HTML --&gt;
    &lt;!-- lst = [&#39;a1&#39;, &#39;a2&#39;, &#39;a3&#39;]; --&gt;
    &lt;div&gt;
      &lt;template v-for=&quot;a in lst&quot;&gt; {{ a }} &lt;/template&gt;
    &lt;/div&gt;</code></pre>
<ol start="2">
<li><p>이때, <code>lst = [&#39;b1&#39;, &#39;b2&#39;, b3&#39;]</code> 라는 명령어를 통해 <code>lst</code> 의 값을 새로 할당했다고 하자. 분명  JavaScript 내에서의 <code>lst</code> 값은 변경되었지만, 화면의 HTML 엘리먼트의 경우 이전의 <code>lst</code> 값을 가지고 화면을 렌더링하였기 때문에 그 값이 바뀌지 않는다.</p>
</li>
<li><p>이때, 코드가 아래와 같이 바뀌었다고 가정하자. 1번의 코드에서 <code>:key</code> 만 추가된 것이다.</p>
<pre><code class="language-html"> &lt;div&gt;
   &lt;template v-for=&quot;a in lst&quot; :key=&quot;a&quot;&gt; {{ a }} &lt;/template&gt;
 &lt;/div&gt;</code></pre>
</li>
<li><p>위와 같이 코드를 수정한 경우 2번을 통해 <code>lst</code> 값이 업데이트된 경우, <code>key</code> 값 역시 업데이트 되었기 때문에 업데이트된 <code>lst</code> 값에 맞춰서 화면의 요소들도 re-rendering 된다.</p>
</li>
</ol>
<p>예시가 복잡할 뿐이지 이해만 한다면 정말정말 간단한 방법이다! 첫번째 Reference의 경우 Vue Router에서의 parameter 변화에 따라 화면을 업데이트하는 여러 방법을 소개하는데, 각 방법의 장단점도 설명해주는만큼 Vue에 정말 관심이 많다면 한 번쯤 읽어보는 것을 추천한다 :)</p>
<h2 id="3-reference">3. Reference</h2>
<ol>
<li>Best Practice for Reacting to Params Changes with Vue Router [<a href="https://stackoverflow.com/questions/40404787/best-practice-for-reacting-to-params-changes-with-vue-router">link</a>]</li>
<li>The correct way to force Vue to re-render a component [<a href="https://michaelnthiessen.com/force-re-render">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] express로 backend 연동하기]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-express%EB%A1%9C-backend-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@byungjur_96/vue.js-express%EB%A1%9C-backend-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 13 Jan 2021 18:23:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>express를 이용하여 Vue 프로젝트를 서버에 올릴 때 URI를 매칭하는 방법</p>
</blockquote>
<h2 id="1-terminology">1. Terminology</h2>
<h3 id="1-spa">1) SPA</h3>
<p>SPA란 &#39;Single Page Application&#39;의 약자로, <em>최초에 하나의 HTML 페이지를 로드한 이후 사용자의 인터렉션에 따라 동적으로 페이지를 업데이트하는 웹 어플리케이션</em> 을 의미한다. 따라서, 일반적인 웹 어플리케이션의 경우 페이지 간의 이동 시에 대상 URL을 서버에 요청해 전체 페이지에 해당하는 HTML 콘텐츠를 받아오는 반면에 SPA의 경우 Ajax를 이용하여 필요한 데이터를 받아와서 화면에 표시한다.</p>
<p>SPA를 사용하면 페이지 이동 시에 필요한 리소스만 부분적으로 로딩을 하기 때문에 전체 페이지에 해당하는 HTML을 모두 받아오는데 드는 오버해드가 줄어들어 어플리케이션의 속도가 향상되며, 더 나은 사용자 경험을 제공할 수 있다는 장점이 있다.</p>
<p>반면에 JS 파일로 번들링하여 한 번에 받기 때문에 초기 구동 속도가 그리며, 검색 엔진 최적화(SEO, Search Engine Optimization)가 어렵다는 한계 역시 존재한다. (이는 SSR로 해결 가능하다.)</p>
<h3 id="2-webpack">2) Webpack</h3>
<p>Webpack이란 여러 개의 JavaScript 파일을 Module Bundling이란 기법을 통해 하나의 파일로 통합시켜주는 Static Module Bundler이다. 여러 개의 JavaScript 파일을 브라우저에서 로딩하는 것보다 시간과 비용을 많이 절약할 수 있으며, 뿐만 아니라 이번 포스팅의 관련된 내용에서는 &#39;Vue 어플리케이션을 express 프레임워크 프로젝트로 번들링&#39;하는 역할을 한다고 한다. (항상 문제 안생기게 사용만 계속 해왔지만, Front-End를 하면 할수록 Webpack의 중요함을 크게 느끼게 되는 것 같다. 언제 기회가 된다면 Webpack에 대해서도 한 번쯤 꼼꼼히 짚어보는 기회가 있으면 좋을 것 같다.)</p>
<h2 id="2-purpose">2. Purpose</h2>
<p>처음에 진행 중인 프로젝트를 배포할 때에는, 단순히 Vue 프로젝트를 npm serve 하였을 때 나오는 페이지만 제대로 구현이 완료되면 포트 번호 정도만 바꿔주면 배포가 완료된 것이라고 생각하였다. 하지만, 웹 호스팅 업체를 통한 서비스 배포는 조금 다른 개념이었고, 혹시나 하는 마음에 배포 후 메인 화면에서 다른 화면으로 전환하는 순간 오류가 발생하는 것을 확인해보았다. 이전에 그러려니 하고 넘어간 SPA, Webpack과 같은 개념들이 서비스 배포 전 가벼운 마음으로 시작한 검토 과정에서 발목을 붙잡았고, 그 해결책에 비해 상당히 오랜 시간을 삽질로 고생하였다. 명쾌하게 설명하기엔 아직 내가 갈 길이 멀고, 간단하게 설명하자면 &#39;<em>Vue 프로젝트를 express를 통해 배포하는 법</em> &#39; 정도로 정리할 수 있을 것 같다.</p>
<h2 id="3-usage">3. Usage</h2>
<ol>
<li><p><code>npm</code> 을 통해서 express를 설치하고 <code>./backend</code> 의 이름으로 프로젝트를 생성한다. 이후 <code>npm</code> 을 실행시켜서 express가 제대로 작동하는 지 확인한다.</p>
<pre><code class="language-bash"> npm install express-generator
 express --view=pug backend</code></pre>
</li>
<li><p>Vue 프로젝트를 Webpack으로 빌드할 때 결과물을 <code>./backend</code> 폴더 내의 <code>public</code> 으로 변경한다. (이전에 작성한 <a href="https://velog.io/@byungjur_96/vue.js-Github-Pages%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0#cf-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80%EC%9D%98-%EC%9D%BC%EB%B6%80%EB%A7%8C-vue%EB%A1%9C-%EA%B5%AC%EC%84%B1%EB%90%9C-%EA%B2%BD%EC%9A%B0">이 게시물</a>을 참고하여 <code>vue.config.js</code> 파일을 수정하면 된다.)
⚠️ 서버 동작 중에 빌드를 하면 오류가 발생할 수 있으므로 서버 종료 후 빌드해야 한다.</p>
</li>
<li><p>Vue Router와 express의 연동을 위해 <code>npm</code> 을 통해서 <code>connect-history-api-fallback</code> 모듈을 설치한다. 이후  <code>./backend</code> 폴더 내의 <code>app.js</code> 파일에  모듈을 등록한다.</p>
<pre><code class="language-javascript"> let app = express();
 app.use(require(&#39;connect-history-api-fallback&#39;)());</code></pre>
</li>
</ol>
<h2 id="4-reference">4. Reference</h2>
<ol>
<li>Vue와 Express를 합쳐서 통합 프로젝트 만들기 [<a href="https://www.hanumoka.net/2018/11/13/vue-20181113-vue-how-to-make-vue-express-project/">link</a>]</li>
<li><strong>(공식 문서)</strong> HTML 히스토리 모드 서버 설정 예제 [<a href="https://router.vuejs.org/kr/guide/essentials/history-mode.html#%EC%84%9C%EB%B2%84-%EC%84%A4%EC%A0%95-%EC%98%88%EC%A0%9C">link</a>]</li>
<li>Vue의 라우터 [<a href="https://k39335.tistory.com/67">link</a>]</li>
<li>Vue Router (개념 및 구현) [<a href="https://kshman94.tistory.com/132">link</a>]</li>
<li>아하 프론트 개발기(1) — SPA와 SSR의 장단점 그리고 Nuxt.js [<a href="https://medium.com/aha-official/%EC%95%84%ED%95%98-%ED%94%84%EB%A1%A0%ED%8A%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-1-spa%EC%99%80-ssr%EC%9D%98-%EC%9E%A5%EB%8B%A8%EC%A0%90-%EA%B7%B8%EB%A6%AC%EA%B3%A0-nuxt-js-cafdc3ac2053">link</a>]</li>
<li>Webpack과 express 프레임워크를 사용한 Vue App 개발환경 구축하기 [<a href="https://pinokio0702.tistory.com/68">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] cdn CSS 파일 추가하기]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-cdn-CSS-%ED%8C%8C%EC%9D%BC-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@byungjur_96/vue.js-cdn-CSS-%ED%8C%8C%EC%9D%BC-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 11 Jan 2021 18:41:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Vue 프로젝트 내에 cdn CSS 파일을 추가하는 방법</p>
</blockquote>
<h2 id="1-purpose">1. Purpose</h2>
<p>일반적으로 html 파일 내에서 외부 CSS 파일을 추가하기 위해서는 <code>&lt;link&gt;</code> 태그를 주로 이용한다. 하지만 컴포넌트 단위 개발을 진행하는 Vue의 경우 기본적으로 <code>.vue</code> 확장자 파일 내에 <code>&lt;style&gt;</code> 태그도 함께 존재한다. 하지만, 부트스트랩과 같이 cdn을 활용하여 웹 상의 CSS 파일을 불러오기 위해서 <code>&lt;style&gt;</code> 태그 내에 <code>&lt;link&gt;</code> 태그를 넣어도 해당 CSS 파일이 적용되지 않는다. 따라서 cdn CSS 파일은 다른 방법으로 추가해야 한다.</p>
<h2 id="2-usage">2. Usage</h2>
<p>상상 이상으로 정말정말 간단하다! Component를 구성하는 <code>vue</code> 파일 내에서 <code>&lt;style&gt;</code> 태그 내에 <code>import</code> 문을 작성해주면 된다. 즉, 아래와 같이 구성하면된다.</p>
<pre><code class="language-html">&lt;style&gt;
  @import &quot;https://cdn-css-file.css&quot;;
&lt;/style&gt;</code></pre>
<h2 id="3-reference">3. Reference</h2>
<ol>
<li>How to add cdn css file to Vue Cli 3 project? [<a href="https://stackoverflow.com/questions/51314997/how-to-add-cdn-css-file-to-vue-cli-3-project">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] Github Pages로 배포하기]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-Github-Pages%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@byungjur_96/vue.js-Github-Pages%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 11 Jan 2021 18:10:52 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Vue로 제작한 정적 홈페이지를 Github Pages를 통해 배포하는 방법</p>
</blockquote>
<h2 id="1-purpose">1. Purpose</h2>
<p>Github Pages 는 Github에서 정적 홈페이지를 쉽게 배포할 수 있도록 도와주는 툴이다. 일반적으로는 <code>index.html</code> 의 이름을 가진 HTML 템플릿을 최상단 디렉토리에 포함하고 있는 repository에 대해서 <code>&lt;user_name&gt;.github.io/&lt;directory_name&gt;</code> 과 같은 형태로 웹페이지를 호스팅할 수 있다. 이때, <code>Vue</code> 와 같은 프레임워크를 사용하는 경우에는 이와 같은 방법으로 정적 홈페이지 배포를 할 수 없기 때문에 약간의 설정이 필요하다.</p>
<h2 id="2-usage">2. Usage</h2>
<p>Vue 프로젝트를 Github Pages에 배포하기 위해서는 Vue 프로젝트 내에 <code>vue.config.js</code> 라는 이름의 파일을 생성한다. (해당 파일은 Vue CLI 환경 설정 및 Webpack 설정을 변경할 수 있는 파일이다.) 이후, 해당 파일 내에 아래와 같이 내용을 채운다. 이 파일은 프로젝트를  <code>build</code> 할 때의 세팅값을 설정할 수 있다.</p>
<pre><code class="language-javascript">// vue.config.js
module.exports = {
    publicPath: &#39;/&lt;repository_name&gt;&#39;,
    outputDir: &#39;docs&#39;
}</code></pre>
<p>여기서 <code>publicPath</code> 는 웹페이지를 배포할 때 Base URL을 선택하는 옵션이다. 실제로 Vue CLI 3.3 이전의 버전에서는 <code>baseURL</code>이라는 옵션으로 사용되었다고 한다. Default 값은 <code>\</code> 이다. 즉, 루트 도메인이 <code>https://www.example.com</code> 이고, <code>publicPath</code> 가 <code>/sub-route/</code> 라면, 해당 어플리케이션은 <code>https://www.example.com/sub-route/</code> 에 배포가 되는 것이다.</p>
<p><code>outputDir</code> 의 경우에는 빌드된 파일들을 어디에 생성할 지를 결정하는 옵션이다. Default 값은 <code>dist</code> 이며, Github Pages에 배포하기 위해서는 <code>docs</code> 로 바꿔야 한다.</p>
<p>이후 Github Repository에 웹페이지를 push한 후, Repository 설정을 확인해보면 <strong>GitHub Pages</strong>에 관한 설정이 있다. 여기서 <code>Branch</code> 를 <code>master</code> 로, 그리고 그 옆에 <code>directory</code> 는 <code>docs</code> 로 설정하고 저장을 하면, <code>https://&lt;user_name&gt;.github.io/&lt;repository_name&gt;</code> 와 같은 디렉토리에 해당 웹페이지가 배포된 것을 확인할 수 있다.</p>
<h3 id="cf-웹페이지의-일부만-vue로-구성된-경우">cf. 웹페이지의 일부만 Vue로 구성된 경우</h3>
<p>이번에 수업 과제를 Github Pages로 배포하던 도중에 문제가 생겼다. 나의 Repository는 아래와 같은 구조를 가지고 있었다.</p>
<pre><code>- Repository
  ↳ HW2
    ↳ HW2-1
    ↳ HW2-2
    ↳ HW2-3
  ↳ HW3
    ↳ project_name</code></pre><p>근데 여기서, Navigtaion 및 HW2 전체는 기본적으로 순수 HTML로 구성되어 있는 반면, HW3만 별개로 Vue로 구현한 프로젝트였다. 해당 프로젝트를 하나의 Repository에서 배포하기 위해서 고민을 했었는데, 결과적으로는 <code>vue.config.js</code> 내의 <code>outputDir</code> 를 <code>&lt;repository_name&gt;/HW3/project_name/docs</code> 와 같은 식으로 설정해주었다. 여기서 중요한 점은 <code>outputDir</code> 에 <code>docs</code> 까지 다 적어주었다는 점이다. 또한, 이 경우 설정에서 <code>directory</code> 를 <code>docs</code> 가 아닌 <code>(root)</code> 로 설정해주어야 한다. 즉, <code>root</code> 에 있는 <code>docs</code> 폴더의 파일을 배포하는 것이 아니기 때문에 <code>docs</code> 폴더가 있는 위치까지 직접  <code>outputDir</code> 을 통해서 설정해 주었다고 생각하면 좋을 것 같다.</p>
<h2 id="3-reference">3. Reference</h2>
<ol>
<li>Vue CLI 애플리케이션 github pages로 배포하기 [<a href="https://blog.naver.com/1126pc/221721147398">link</a>]</li>
<li>[Vue.js] Vue CLI build 할 때 외부 참조 파일 변경 방법(publicPath) [<a href="https://blog.naver.com/mgveg/221980424679">link</a>]</li>
<li>vue.config.js 옵션에 관한 공식문서 [<a href="https://cli.vuejs.org/config/#vue-config-js">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] 404 Error 핸들링]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-404-Error-%ED%95%B8%EB%93%A4%EB%A7%81</link>
            <guid>https://velog.io/@byungjur_96/vue.js-404-Error-%ED%95%B8%EB%93%A4%EB%A7%81</guid>
            <pubDate>Thu, 31 Dec 2020 09:12:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Vue.js에서 404 Not Found 페이지 설정 및 리다이렉트는 어떻게 할까?</p>
</blockquote>
<h2 id="1-terminology">1. Terminology</h2>
<h3 id="1-404-not-found">1) 404 Not Found</h3>
<p>404 Not Found 에러는 <strong>&quot;서버 자체는 존재하지만 서버에서 요청한 것을 찾을 수 없을 때&quot;</strong> 나타나는 오류다. 보통 사용자가 요청하는 페이지나 파일을 찾을 수 없을 때 발생한다. 서버 문제를 제외한다면, 보통 사용자의 오타, 또는 변경되기 이전의 URL로의 접속이 가장 큰 원인이라고 볼 수 있다.</p>
<h3 id="2-redirect">2) Redirect</h3>
<p>리다이렉트라는 용어 그대로 다시(re) 지시한다(direct)는 뜻이다. HTTP 리다이렉트는 HTTP 표준으로 정의되어 있으며, 최초 요청을 받은 웹서버는 리다이렉트되어야 할 주소를 응답 메세지 헤더 안의 location 안에 담아 HTTP 응답 상태코드로 <code>302</code> 를 보낸다. 또한. 클라이언트는 상태코드가 <code>302</code> 인 HTTP 응답 메세지를 받은 경우 헤더 안의 location URL로 다시 요청한다.</p>
<h2 id="2-purpose">2. Purpose</h2>
<p>먼저 404 페이지의 목적은 사용자가 존재하지 않는 페이지에 접속을 시도해도 사용자가 계속 홈페이지에 남아있도록 하는 것이라고 한다. 그러기 위해서 조건에 부합하지 않거나, 존재하지 않는 주소에 대해 사전에 만들어 놓은 404 페이지로 리다이렉트하기 위해서다.</p>
<h2 id="3-usage">3. Usage</h2>
<h3 id="1-page-not-found-컴포넌트와-라우팅-매치하기">1) Page Not Found 컴포넌트와 라우팅 매치하기</h3>
<pre><code class="language-javascript">const routes = [
    {
        path: &quot;/404&quot;,
        name: &quot;notFound&quot;,
        component: NotFound
    },
];</code></pre>
<p>Page Not Found 페이지를 <code>NotFound</code> 컴포넌트에 구현을 한 뒤에 <code>/404</code> 경로와 매칭시킨다.</p>
<h3 id="2-존재하지-않는-경로들-404-페이지로-리다이렉트하기">2) 존재하지 않는 경로들 404 페이지로 리다이렉트하기</h3>
<pre><code class="language-javascript">// Vue 2.x
const routes = [
    {
        path: &#39;*&#39;,
        redirect: &quot;/404&quot;
          // 아래처럼 바로 NotFound 경로를 매칭해도 됨
          // component: NotFound
    },
];</code></pre>
<p>모든 페이지들을 경로와 매칭시킨 이후, route  포함되지 않은 모든 경로(default 값)에 대해서 <code>/404</code> 페이지로 리다이렉트한다. <code>&#39;*&#39;</code> 의 의미는 위에서 어떤 경로와도 매칭이 되지 않은 경우 해당 경로로 이동하라는 의미로 이해하면 된다.</p>
<blockquote>
<p>Vue 3에서부터 default 값과의 매칭이 <code>pathMatch</code> 로 바뀌었다.
따라서 Vue 3에서부터는 아래와 같은 방법으로 사용한다.</p>
</blockquote>
<pre><code class="language-javascript">// Vue 3.x
const routes = [
    {
        path: &#39;/:pathMatch(.*)*&#39;,
        redirect: &quot;/404&quot;
    },
];</code></pre>
<h3 id="cf-기타-케이스">cf. 기타 케이스</h3>
<p>동적 라우팅 매칭에서 parameter에 따라서 페이지가 존재하지 않을 수도 있다. </p>
<ol>
<li><code>user/:id</code> 와 같은 경로에 대해, 잘못된 형식의 id (ex. 숫자 id인데 문자열을 입력한 경우)를 입력한 경우</li>
<li>페이지 접속에 권한이 필요한 경우 (ex. 네이버 카페에서 게시판 별 접근 권한)</li>
</ol>
<p>이와 같이 동적 라우팅에 올바른 parameter가 사용되었는지 확인하기 위해서 Vue-Router의 <a href="%22https://router.vuejs.org/kr/guide/advanced/navigation-guards.html%22">네비게이션 가드</a>를 이용하여 잘못된 접근을 막을 수 있다.</p>
<h2 id="4-reference">4. Reference</h2>
<ol>
<li>404 not found 에러의 의미와 해결 방법 [<a href="https://blog.naver.com/lw_10page/221640822337?viewType=pc">link</a>]</li>
<li>리다이렉트(REDIRECT)란? [<a href="https://dololak.tistory.com/147">link</a>]</li>
<li>[번역] &#39;404 에러페이지&#39; 24가지 분석 - 1 [<a href="https://brunch.co.kr/@hyeminimi/31">link</a>]</li>
<li>Why Your 404 Page is Important and How to Make it Brilliant Instead of Boring [<a href="https://www.webhostingsecretrevealed.net/blog/web-design/why-your-404-page-is-important-and-how-to-make-it-brilliant-instead-of-boring/">link</a>]</li>
<li>Vue-router redirect on page not found (404) [<a href="https://stackoverflow.com/questions/40193634/vue-router-redirect-on-page-not-found-404">link</a>]</li>
<li>Removed <code>*</code> (star or catch all) routes [<a href="https://next.router.vuejs.org/guide/migration/#removed-star-or-catch-all-routes">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] 페이지 이동 시 Offset 변경]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99-%EC%8B%9C-Offset-%EC%9D%B4%EB%8F%99</link>
            <guid>https://velog.io/@byungjur_96/vue.js-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99-%EC%8B%9C-Offset-%EC%9D%B4%EB%8F%99</guid>
            <pubDate>Mon, 28 Dec 2020 07:42:51 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>페이지 이동 시 Vue 라이프 사이클에 기반하여 offset을 변경하는 방법</p>
</blockquote>
<h2 id="1-purpose">1. Purpose</h2>
<p>Vue를 이용한 홈페이지 내에서는 라우팅 이동을 할 때 Page Offset (화면에서 어느 위치에 있었는지)가 유지된다. 즉, 이전 화면의 맨 아래에서 다른 화면으로 이동할 경우 새로운 홈페이지의 맨 아래에 위치하게 된다는 것이다. VanilaJS에서는 <code>window.scrollTo(x, y)</code> 를 그냥 이용하면 되지만, Vue.js는 컴포넌트 단위로 작동하기 때문에 기본적인 함수 사용은 동일하지만 조금 다르다.</p>
<h2 id="2-usage">2. Usage</h2>
<p>위에서 언급한 것과 같이 <code>window.scrollTo(x, y)</code> 를 사용하면 된다. 다만, 컴포넌트 단위의 개발을 하는 Vue의 경우 <code>window</code> 와 같은 전역 객체를 사용하기 쉽지 않기 때문에 Vue 라이프 사이클에 기반하여 사용하여야 한다. (자세한 내용은 추구 Vue 라이프 사이클 대한 포스팅에서 언급 예정) 일단 해당 컴포넌트 페이지로 이동하였을 때 화면의 최상단으로 이동하기 위해서는 아래와 같은 코드를 사용하면 된다.</p>
<pre><code class="language-javascript">mounted () {
  window.scrollTo(0, 0)
}</code></pre>
<p>정말 짧은 코드이지만 간단히 설명을 하자면, <code>mounted</code> 는 해당 컴포넌트를 마운트하였을 때 실행하는 코드이다. 즉, 해당 컴포넌트를 마운트하자마자 Page Offset을 (0, 0)으로 이동한다는 의미이다. 혹시라도 Vue 라이프 사이클에 대한 이해가 부족한 경우 <a href="https://kr.vuejs.org/v2/guide/instance.html#%EB%9D%BC%EC%9D%B4%ED%94%84%EC%82%AC%EC%9D%B4%ED%81%B4-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8">공식 문서</a>에서 확인 가능하다.</p>
<h2 id="3-reference">3. Reference</h2>
<ol>
<li>Vue.js scroll to top on route change [<a href="https://renatello.com/vue-js-scroll-top">link</a>]</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vue.js] Named Routes]]></title>
            <link>https://velog.io/@byungjur_96/vue.js-Named-Routes</link>
            <guid>https://velog.io/@byungjur_96/vue.js-Named-Routes</guid>
            <pubDate>Mon, 28 Dec 2020 07:21:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Vue Router의 Named Routes를 통해 하위 라우팅과 상위 라우팅의 구분하기</p>
</blockquote>
<h1 id="1-purpose">1. Purpose</h1>
<p>vue를 이용하여 프로젝트를 진행하는 경우 라우팅을 자주 사용하게 된다. 라우팅을 이용하다보면 하위 경로에 대한 라우팅을 하게 되는 경우가 있다. 예를 들면 <code>BASE-URL/user</code> 라는 주소와, <code>BASE-URL/user/123</code> 과 같은 주소를 하나의 프로젝트에서 쓴다는 것이다. 이때, <code>router-link</code> 태그를 이용하여 경로 이동을 할 때 path를 통해 이동하는 경우에는 Vue Router에서 선언 순서에 따라서 제대로 라우팅 경로가 매칭이 되지 않는 경우가 생긴다. 즉, <code>BASE-URL/user</code> 에 매칭해야 할 컴포넌트가 <code>BASE-URL/user</code>에 해당하는 컴포넌트인지, <code>BASE-URL/user/123</code>에 해당하는 컴포넌트인지 확실히 구분하기 어려워 진다는 의미이다. 이런 혼동을 방지하기 위해서 Vue Router에서는 Named Routes라는 개념을 사용한다.</p>
<h1 id="2-usage">2. Usage</h1>
<p>Named routes를 사용하기 위해서는 우선 router 선언을 할 때 속성으로 <code>name</code> 을 설정해주어야 한다.</p>
<pre><code class="language-javascript">const router = new VueRouter({
  routes: [
    {
      path: &#39;/user/:userId&#39;,
      name: &#39;user&#39;,
      component: User
    }
  ]
})</code></pre>
<p>위의 경우에서 User 컴포넌트로 이동하기 위해서는 크게 두가지 방법이 있다.</p>
<h3 id="1-path를-이용하기">1. path를 이용하기</h3>
<pre><code class="language-html">&lt;router-link :to=&quot;{path:`user/${userId}`}&quot;&gt;User&lt;/router-link&gt;</code></pre>
<h3 id="2-name을-이용하기">2. name을 이용하기</h3>
<pre><code class="language-html">&lt;router-link :to=&quot;{ name: &#39;user&#39;, params: {userId: 123}}&quot;&gt;User&lt;/router-link&gt;</code></pre>
<p>만약 <code>/user</code> 페이지가 다른 화면을 나타내야 하는 경우, 2번과 같이 name을 이용하여 라우팅 이동을 진행하는 것이 권장된다.</p>
<p>추가로 <code>router.push()</code> 함수를 이용하여 이동을 할 수도 있다.</p>
<pre><code class="language-javascript">router.push({ name: &#39;user&#39;, params: { userId: 123 }})</code></pre>
<blockquote>
<p>❗️ 나중에 찾아보니 Named Route는 주로 한 화면 안에 여러 개의 컴포넌트를 표시하기 위해 사용하고, 위와 같이 하위 라우팅을 관리하기 위해서는 <a href="https://router.vuejs.org/kr/guide/essentials/nested-routes.html">Nested Route</a>를 사용한다고 한다. 내가 사용할 때에는 제대로 작동하지 않았는데, 나중에 기회가 되면 다시 시도해봐야 겠다.</p>
</blockquote>
<h1 id="3-reference">3. Reference</h1>
<ol>
<li>Vue Router 공식 홈페이지(영문) [<a href="https://router.vuejs.org/guide/essentials/named-routes.html">link</a>]</li>
<li>Vue Router 공식 페이지(국문) [<a href="https://router.vuejs.org/kr/guide/essentials/named-routes.html">link</a>]</li>
<li><strong>[기타]</strong> Named Views [<a href="https://router.vuejs.org/guide/essentials/named-views.html#nested-named-views">link</a>]</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>