<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>pc_jin.log</title>
        <link>https://velog.io/</link>
        <description>개발 블로그🌐 개발일지💻</description>
        <lastBuildDate>Tue, 03 Jan 2023 14:25:08 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>pc_jin.log</title>
            <url>https://velog.velcdn.com/cloudflare/pc_jin/daf8b41e-80d4-4ef6-967c-36a75774f23b/1561903529165.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. pc_jin.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/pc_jin" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[TIL] 20230103]]></title>
            <link>https://velog.io/@pc_jin/TIL-20230103</link>
            <guid>https://velog.io/@pc_jin/TIL-20230103</guid>
            <pubDate>Tue, 03 Jan 2023 14:25:08 GMT</pubDate>
            <description><![CDATA[<h2 id="마무리">마무리</h2>
<h3 id="버전-비교">버전 비교</h3>
<p>두 버전을 비교하는 코드를 작성했다.
예를 들어 시스템에서 요구하는 최소 버전이 있는데, 사용자의 버전이 <strong>시스템의 최소 요구 버전을 만족</strong>하는지 확인하는 함수</p>
<ul>
<li><p>최초작성</p>
<pre><code class="language-js">function checkValidVersion(systemVersion, userVersion) {
let sepSystemVersion = systemVersion.split(&#39;.&#39;);
let sepUserVersion = systemVersion.split(&#39;.&#39;);

if(sepSystemVersion[0] &lt; sepUserVersion[0]){
  return true
}else if(sepSystemVersion[0] === sepUserVersion[0]) {
  if(sepSystemVersion[1] &lt; sepUserVersion[1]) {
    return true
  }else if(sepSystemVersion[1] === sepUserVersion[1]) {
    if(sepSystemVersion[2] &lt;= sepUserVersion[2]) {
      return true
    }
  }
}
return false
}</code></pre>
</li>
</ul>
<hr>
<ul>
<li><p>중복코드 제거</p>
<pre><code class="language-js">function checkValidVersion(systemVersion, userVersion) {
let sepSystemVersion = systemVersion.split(&#39;.&#39;);
let sepUserVersion = systemVersion.split(&#39;.&#39;);

if(sepSystemVersion[0] &lt; sepUserVersion[0]) return true
if((sepSystemVersion[0] === sepUserVersion[0]) &amp;&amp; (sepSystemVersion[1] &lt; sepUserVersion[1])) {
  return true
}else if((sepSystemVersion[1] === sepUserVersion[1]) &amp;&amp; (sepSystemVersion[2] &lt;= sepUserVersion[2])) {
  return true
}
return false
}</code></pre>
</li>
</ul>
<hr>
<ul>
<li><p>추후 유지보수를 위한 모듈화</p>
<pre><code class="language-js">function checkValidVersion(systemVersion, userVersion) {
let sepSystemVersion = systemVersion.split(&#39;.&#39;);
let sepUserVersion = systemVersion.split(&#39;.&#39;);

if(compareVersion(sepSystemVersion[0], sepUserVersion[0], &quot;&lt;&quot;)) return true
if(compareVersion(sepSystemVersion[0], sepUserVersion[0], &quot;===&quot;) &amp;&amp; compareVersion(sepSystemVersion[1], sepUserVersion[1], &quot;&lt;&quot;)) {
  return true;
}else if(compareVersion(sepSystemVersion[1], sepUserVersion[1], &quot;===&quot;) &amp;&amp; compareVersion(sepSystemVersion[2], sepUserVersion[2], &quot;&lt;=&quot;)) {
  return true;
}
return false;
}
</code></pre>
</li>
</ul>
<p>function compareVersion(systemVersion, userVersion, compareOperator) {
  switch (compareOperator) {
    case &quot;===&quot;:
      return systemVersion === userVersion;
    case &quot;&lt;=:
      return systemVersion &lt;=userVersion;
    case &quot;&lt;&quot;:
      return systemVersion &lt; userVersion;
    default:
      new Error(&quot;유효하지 않은 연산자 입니다.&quot;);
  }
}</p>
<p>```</p>
<blockquote>
<p>위 코드보다 조금 더 효율적이고 유지보수에 용이한 코드를 생각해 보자!</p>
</blockquote>
<h3 id="느낀점">느낀점</h3>
<p>중복 코드 줄이는 것까지야 생각할 수 있었지만, 추후의 유지보수를 위해 공통 코드를 모듈화 하는 것은 회사 선배분의 조언이 없었다면 생각조차 할 수 없었다.
<strong>switch문</strong>을 사용하는 방식 말고 <strong>eval()</strong> 이라는 자바스크립트 메서드를 통해서 더 간결하게 줄였었는데, 보안문제와 효율성 문제로 인해서 다시 switch문으로 변경하였다.
취업 준비를 하면서 포트폴리오랑 자소서에 <strong>유지보수가 가능한 코드를 작성하는 개발자가 되겠다</strong>고 적었었는데, 그때 그 마음을 잊은것은 아닌지 다시한번 돌아보는 계기가 되었다.</p>
<h1 id="아직-멀었다">아직 멀었다...</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 20230102]]></title>
            <link>https://velog.io/@pc_jin/TIL-20230102</link>
            <guid>https://velog.io/@pc_jin/TIL-20230102</guid>
            <pubDate>Mon, 02 Jan 2023 13:43:16 GMT</pubDate>
            <description><![CDATA[<h2 id="마무리">마무리</h2>
<p>그렇다... 난 나와의 약속을 지키지 못했다.
이번주 복싱🥊 안가는 날 <strong>JWT</strong>랑 <strong>SpringSecurity</strong> 정리 하겠다.
새해 첫 약속 🤙</p>
<h3 id="ojt-프로젝트에-jwt·springsecurity-적용">OJT 프로젝트에 JWT·SpringSecurity 적용</h3>
<p>이건 마무리가 되었고, 이제 기존에 있던 게시판 기능에 회원 테이블을 추가해서 게시판과 회원의 연관관계를 설정해주는 일이 남아 있다.</p>
<blockquote>
<ul>
<li><p><strong>오늘의 삽질</strong>
현재 IntelliJ를 2020.1.1 버전을 쓰고 있는데, 이게 JVM 1.4.20까지만 지원을 해서(OJT는 JVM 1.6.21) 다운그레이드를 했다. 사실 컴파일하고 빌드하는 것은 아무 문제 없었지만 빨간줄이 계속 떠서 거슬려서 다운그레이들 실행했다.
그런데... 잘되던 기능이 갑자기 안되는것...</p>
<p>  알고 보니 1.6.21에서는 List 타입을 JSON으로 전송하지만, 1.4.20에서는 그러지 못한것..
  해결방법은 jackson 의존성 추가</p>
<blockquote>
<pre><code class="language-shell">// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
implementation(&quot;com.fasterxml.jackson.core:jackson-databind:2.0.1&quot;)</code></pre>
</blockquote>
</li>
</ul>
</blockquote>
<pre><code>&gt; 
&gt; Java Object를 JSON으로 변환하거나 JSON을 Java Object로 변환하는데 사용할 수 있는 Java 라이브러리
&gt; 
&gt; 

# 열심히 살아보자 1년!</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 20221228]]></title>
            <link>https://velog.io/@pc_jin/TIL-20221228</link>
            <guid>https://velog.io/@pc_jin/TIL-20221228</guid>
            <pubDate>Wed, 28 Dec 2022 14:14:38 GMT</pubDate>
            <description><![CDATA[<h2 id="마무리">마무리</h2>
<p>어제에 이어서 OJT프로젝트에 <strong>Spring Security</strong>와 <strong>JWT</strong>를 적용하고 있는 중
토큰만 생성하면 끝일 줄 알았는데, <strong>AccessToken</strong>, <strong>RefreshToken</strong>을 적용하려니까 조금 어려움이 있다. </p>
<h3 id="크게-4단계로-구분-하였음">크게 4단계로 구분 하였음</h3>
<blockquote>
<ol>
<li>AccessToken과 RefreshToken 모두 만료되었을 때 =&gt; 재로그인</li>
<li>AccessToken만 만료 =&gt; RefreshToken 유효성 검사후, AccessToken 재발급</li>
</ol>
<p>+) RereshToken 만료일 근접하면 RefreshToken 재발급
3. RefreshToken만 만료 =&gt; RefreshToken 재발급
4. 두 토큰 모두 유효할 때 =&gt; 요청 정상 처리</p>
</blockquote>
<p>이렇게 진행하려고 한다!</p>
<hr>
<h3 id="그래서-토큰은-어디에-저장할-건데">그래서 토큰은 어디에 저장할 건데?</h3>
<blockquote>
<p>토큰 저장 위치는 Cookie, LocalStorage, SessionStorage 이정도?</p>
<blockquote>
</blockquote>
<p><a href="https://simsimjae.tistory.com/482">참고1</a>
<a href="https://velog.io/@ppyooy336/JWT-Token-%EC%A0%80%EC%9E%A5-%EC%9C%84%EC%B9%98">참고2</a></p>
<p>뭐 이렇다고하는데, 사실 더 잘 정리한 곳이 있긴했는데, 못찾겠다 나중에 찾으면 추가해놔야지..</p>
</blockquote>
<p>포트폴리오용 프로젝트를 진행할 때 Cookie에 값을 저장했었는데, 확실히 서버에서도 접근이 가능해서 편하게 사용했던 것 같다.
이번에는 LocalStorage에 토큰 값을 저장해서 사용하려고 한다.</p>
<hr>
<p>너무 아무생각없이 코드만 짠것 같다.
SpringSecurity의 UserDetails, UserDetailsService 등 기본 개념들도 주말에 잘 정리해놔야겠다!</p>
<h1 id="올해-마무리-잘하자">올해 마무리 잘하자!</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 20221226]]></title>
            <link>https://velog.io/@pc_jin/TIL-20221226</link>
            <guid>https://velog.io/@pc_jin/TIL-20221226</guid>
            <pubDate>Mon, 26 Dec 2022 13:40:45 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/pc_jin/post/93695bb8-773b-4caf-8d9d-85e90b0513c6/image.png" alt=""></p>
<h2 id="마무리">마무리</h2>
<p>오랜만에 다시적는 TIL, 연말이라 약속도 많고....는 핑계고 그냥 <span style="background:#FFA07A">귀찮았다.</span></p>
<p><strong><span style="background:#C07A; text-align: center;">이제 다시 퇴근 후 공부도 시작!</span></strong></p>
<hr>
<p>여태까지 OJT에서 구현했던 코드에 간단한 <strong>테스트 코드</strong>를 적용해보았다. 
그리고 이어서 <strong>Spring Security</strong>와 <strong>JWT</strong>를 적용하고 있는 중이다.</p>
<h3 id="이번주-정리-예정">이번주 정리 예정</h3>
<blockquote>
<ul>
<li>Spring Security</li>
</ul>
</blockquote>
<ul>
<li>JWT</li>
<li>Authentication / Authorization</li>
</ul>
<p><a href="https://flexboxfroggy.com/#ko">flex box 개구리 ㅋ</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue] class binding]]></title>
            <link>https://velog.io/@pc_jin/Vue-class-binding</link>
            <guid>https://velog.io/@pc_jin/Vue-class-binding</guid>
            <pubDate>Thu, 01 Dec 2022 13:40:59 GMT</pubDate>
            <description><![CDATA[<p>어떠한 조건에 따라 서로 다른 <code>html class</code>를 적용시켜야 한다면, class binding을 사용해서 코드를 간소화 할 수 있다.</p>
<h3 id="기존-코드">기존 코드</h3>
<pre><code class="language-html">&lt;div v-if=&quot;item.count &gt; 0&quot;&gt;
  &lt;div class=&quot;red&quot;&gt;
    &lt;p&gt; {{ count }} &lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div v-if=&quot;item.count &lt; 0&quot;&gt;
  &lt;div class=&quot;blue&quot;&gt;
    &lt;p&gt; {{ count }} &lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre>
<p>위와 같이 두 <code>&lt;div&gt;</code>가 동일한 내용을 포함하고 있지만, <code>class</code> 만 상황에 따라 다르게 적용되어야할 때 <code>class binding</code>을 사용할 수 있다.</p>
<h3 id="변경">변경</h3>
<pre><code class="language-html">&lt;div :class=&quot;{&#39;red&#39;: item.count &gt; 0, &#39;blue&#39; : item.coun &lt; 0}&quot;&gt;
  &lt;p&gt; {{ count }} &lt;/p&gt;
&lt;/div&gt;</code></pre>
<p>이렇게 <code>class binding</code>을 적용한다면 변경전 코드보다 훨씬 간소화할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue] emit 사용하기]]></title>
            <link>https://velog.io/@pc_jin/Vue-emit-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@pc_jin/Vue-emit-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 01 Dec 2022 13:30:03 GMT</pubDate>
            <description><![CDATA[<p>자식 컴포넌트의 변수로 부모 컴포넌트의 메서드를 동작시키고 반환 값을 다시 자식 컴포넌트로 가져오는 방법이 있다.</p>
<h2 id="부모-컴포넌트">부모 컴포넌트</h2>
<pre><code class="language-js">&lt;template&gt;
  &lt;ChildComponent 
        @up=&quot;increase&quot;
  /&gt;
&lt;/template&gt;
&lt;script&gt;
import ChildComponent from &#39;@/ChildComponent.vue&#39;;

export default {
    setup() {
      const increase = (count) = &gt; {
        count += 1;
      };

      return {
        increase,
      }
    },
      components: {
      ChildComponent,
    }
}
&lt;/script&gt;</code></pre>
<p>자식 컴포넌트에 <code>up</code>이라는 이름으로 increase 메서드 전달</p>
<h2 id="자식-컴포넌트">자식 컴포넌트</h2>
<pre><code class="language-js">&lt;template&gt;
  &lt;p&gt; {{ count }} &lt;/p&gt;
  &lt;button @click=&quot;clickToIncrease(count)&quot;&gt;CLICK&lt;/button&gt;
&lt;/template&gt;
&lt;script&gt;
export default {
    emits: [&#39;up&#39;,],

    setup(context){
      const count = ref(0);

      const clickToIncrease = (count) =&gt; {
        context.emit(&#39;up&#39;, count);
      };

      return {
        count,
      }
    }
}
&lt;/script&gt;</code></pre>
<p>emits로 부모 컴포넌트에서 전달 받고 <code>clickToIncrease</code> 메서드를 통해 부모 컴포넌트의 메서드를 동작시키고 값을 반환해서 출력한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue3] 반응성]]></title>
            <link>https://velog.io/@pc_jin/Vue3-%EB%B0%98%EC%9D%91%EC%84%B1</link>
            <guid>https://velog.io/@pc_jin/Vue3-%EB%B0%98%EC%9D%91%EC%84%B1</guid>
            <pubDate>Thu, 01 Dec 2022 13:07:11 GMT</pubDate>
            <description><![CDATA[<h2 id="ref">ref</h2>
<pre><code class="language-js">&lt;template&gt;
  &lt;h3&gt;잔액 = {{ money }} &lt;/h3&gt;
  &lt;input v-model=&quot;money&quot;&gt;
  &lt;button @click=&quot;reset&quot;&gt; RESET &lt;/button&gt;
&lt;/template&gt;

&lt;script&gt;
import { ref } from &#39;vue&#39;;

export default {
  setup() {
    const money = ref(&quot;&quot;);

       const reset = () =&gt; {
      money.value = 10000;
    }

    return {
      money,
    }
  }
}</code></pre>
<p>원시 타입을 반응형으로 사용할 때 사용한다.
<code>script</code>안에서 해당 값에 접근할 때는 <code>.value</code>를 통해서 접근해야 접근이 가능하다. 만약 그냥 접근하게 된다면 해당 값은 <span style="color:red"><code>undifined</code></span>로 반환되어 원하는 결과를 얻을 수 없다.</p>
<h2 id="reactive">reactive</h2>
<pre><code class="language-js">&lt;template&gt;
  &lt;h3&gt;잔액 = {{ money }} &lt;/h3&gt;
  &lt;input v-model=&quot;money&quot;&gt;
  &lt;button @click=&quot;reset&quot;&gt; RESET &lt;/button&gt;
&lt;/template&gt;

&lt;script&gt;
import { reactive, toRefs } from &#39;vue&#39;;

export default {
  setup() {
    const state = reactive({
      money : &#39;&#39;,
    });

       const reset = () =&gt; {
      state.money = 10000;
    }

    return {
      ...toRefs(state),
    }
  }
}</code></pre>
<p>원시타입으로 적용이 안되고 <code>Object</code>,<code>array</code>,<code>Map</code>,<code>Set</code> 등의 타입에서만 사용할 수 있다.
<code>ref</code>와는 다르게 <code>.value</code>로 접근할 필요가 없다.</p>
<h3 id="toref">toRef</h3>
<pre><code class="language-js">&lt;template&gt;
  &lt;h1&gt;msg = {{ msg }}&lt;/h1&gt;
  &lt;input v-model=&quot;msg&quot;&gt;
&lt;/template&gt;

&lt;script&gt;
import { reactive, toRef } from &#39;vue&#39;

export default {
  setup() {
  const words = reactive({a:&quot;a&quot;,b:&quot;b&quot;});
  const msg = words.a;
  },

  return {
    msg,
  }
}
&lt;/script&gt;</code></pre>
<p>위와 같이 작성 했을 때, 자바스크립트는 word.a의 value값만 복사하기 때문에 Proxy의 반응성을 유지하지 못한다.
<code>words</code>의 <code>a</code>가 string이기 때문에 복사를 하면 value값만 복사해 반응성을 잃어버려서 반영되지 않는 모습입니다.</p>
<pre><code class="language-js">&lt;template&gt;
  &lt;h1&gt;msg = {{ msg }}&lt;/h1&gt;
  &lt;input v-model=&quot;msg&quot;&gt;
&lt;/template&gt;

&lt;script&gt;
import { reactive, toRef } from &#39;vue&#39;
export default {
  setup() {
    const words = reactive({a:&quot;a&quot;,b:&quot;b&quot;})
    const msg = toRef(words, &#39;a&#39;)
    },
  return {
      msg,
  }
}
&lt;/script&gt;</code></pre>
<p>toRef는 하나의 property에 대해 부모 object와의 연결성을 유지한채로 reactive를 반환하고 이 변화는 부모에게도 반영이 되어 추적이 된다.</p>
<h3 id="torefs">toRefs</h3>
<pre><code class="language-js">&lt;template&gt;
  &lt;h1&gt;msg = {{ a }}&lt;/h1&gt;
  &lt;input v-model=&quot;a&quot;&gt;
&lt;/template&gt;

&lt;script&gt;
import { reactive, toRef } from &#39;vue&#39;
export default {
  setup() {
    const words = reactive({a:&quot;a&quot;,b:&quot;b&quot;})
    },
  return {
      ...toRefs(words),
  }
}
&lt;/script&gt;</code></pre>
<p><code>toRefs</code>는 reactive의 모든 프로퍼티에 대해 toRef를 적용해 반환한다.</p>
<blockquote>
<p>정하기 나름이지만 보통 <code>ref</code>선언해줘야 할 것이 4개가 넘어가는 경우 <code>reactive</code> 사용함</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Promise]]></title>
            <link>https://velog.io/@pc_jin/JavaScript-Promise</link>
            <guid>https://velog.io/@pc_jin/JavaScript-Promise</guid>
            <pubDate>Thu, 01 Dec 2022 12:18:28 GMT</pubDate>
            <description><![CDATA[<h2 id="promise란">Promise란?</h2>
<p>자바 스크립트의 비동기 처리에 사용되는 객체</p>
<h2 id="promise의-상태">Promise의 상태</h2>
<ul>
<li>Pending(대기) : 비동기 처리 로직이 완료되지 않은 상태</li>
<li>Fulfilled(이행) : 비동기 처리가 완료되어 promise가 결과 값을 반환한 상태</li>
<li>Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태</li>
</ul>
<pre><code class="language-js">function getData() {
  return new Promise(function(resolve, reject) {    // promise 객체를 생성 (pending 상태)
    $.get(&#39;url 주소/products/1&#39;, function(response) {
      if (response) {
        resolve(response);    // response가 있다면 reslove (fulfilled 상태)
      }
      reject(new Error(&quot;Request is failed&quot;));    // response가 없으면 reject (rejected 상태)
    });
  });
}

// 위 $.get() 호출 결과에 따라 &#39;response&#39; 또는 &#39;Error&#39; 출력
getData().then(function(data) {
  console.log(data); // response 값 출력
}).catch(function(err) {
  console.error(err); // Error 출력
});</code></pre>
<h2 id="reference">Reference</h2>
<p><a href="https://joshua1988.github.io/web-development/javascript/promise-for-beginners/">https://joshua1988.github.io/web-development/javascript/promise-for-beginners/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue] CORS 해결]]></title>
            <link>https://velog.io/@pc_jin/Vue-CORS-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@pc_jin/Vue-CORS-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Thu, 01 Dec 2022 12:03:03 GMT</pubDate>
            <description><![CDATA[<p>CORS 오류가 발생했을 때, 서버에서 <span style="color:red"><code>Access-Control-Allow-Origin</code></span> 설정해주는 방법 이외에 프론트에서 처리 할 수 있는 방법이 있다.
바로 <span style="color:blue"><code>proxy</code></span>를 설정해주면 되는데, 다음은 <span style="color:green"><code>Vue</code></span>에서 <span style="color:blue"><code>proxy</code></span> 설정 해주는 방법이다.</p>
<h3 id="viteconfigjs">vite.config.js</h3>
<pre><code class="language-js">  server: {
    port: 9000
    proxy: {
      &#39;/board/v1&#39;: &#39;http://192.168.0.47:8080&#39;,
    }
  }</code></pre>
<ul>
<li>port : 프론트 서버를 9000번 포트로 실행</li>
<li>proxy : 9000번 포트로 들어온 <code>/board/v1</code> 으로 들어온 요청을 <code>http://192.168.0.47:8080</code> 여기로 넘겨줌</li>
</ul>
<blockquote>
<p>요청 자체는 <span style="color : blue"><code>http://localhost:9000/board/v1</code></span>으로 보여지게 되지만 vite.config.js의 서버 proxy 설정으로 인해서 해당 요청은 <code>http://192.168.0.47:8080</code>여기로 넘어가게 된다.</p>
</blockquote>
<p>이렇게 된다면, 프론트와 백엔드 서버는 서로 동일한 출처의 리소스로 인식을 해서 CORS 문제가 해결되게 된다.
하지만, 해당 설정은 local에서 실행할 때만 적용이되고 배포시에는 서버에서 <span style="color:red"><code>Access-Control-Allow-Origin</code></span>을 설정하거나, <code>nginx</code>에서 proxy설정을 해주어야 한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 비동기 처리 (async / await)]]></title>
            <link>https://velog.io/@pc_jin/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@pc_jin/JavaScript-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Sun, 27 Nov 2022 13:57:40 GMT</pubDate>
            <description><![CDATA[<h2 id="async-함수">async 함수</h2>
<pre><code class="language-js">async function f() {
  return 1;
}</code></pre>
<p><code>async</code>함수는 항상 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise"><code>Promise</code></a>를 반환한다.
<code>Promise</code>가 아닌 값도 <code>Promise</code>로 값을 감싸 반환한다.</p>
<h2 id="await">await</h2>
<p><code>await</code>는 <code>async</code>함수 안에서만 동작하며, <code>Promise</code>가 처리 될 때까지 기다립니다.</p>
<pre><code class="language-js">async function f() {

  let promise = new Promise((resolve, reject) =&gt; {
    setTimeout(() =&gt; resolve(&quot;완료!&quot;), 1000)
  });

  let result = await promise; // 프라미스가 이행될 때까지 기다림

  alert(result); // &quot;완료!&quot;
}

f();</code></pre>
<p>다음 코드에서,
<code>await</code>를 만나 <code>Promise</code>처리가 될 때 까지 기다렸다가 다음 동작을 진행하게 된다. 따라서 위의 함수를 실행하면 1초뒤에 <code>완료!</code>가 출력되게 된다.</p>
<h2 id="reference">Reference</h2>
<p><a href="https://ko.javascript.info/async-await">https://ko.javascript.info/async-await</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] 옵셔널 체이닝]]></title>
            <link>https://velog.io/@pc_jin/JavaScript-%EC%98%B5%EC%85%94%EB%84%90-%EC%B2%B4%EC%9D%B4%EB%8B%9D</link>
            <guid>https://velog.io/@pc_jin/JavaScript-%EC%98%B5%EC%85%94%EB%84%90-%EC%B2%B4%EC%9D%B4%EB%8B%9D</guid>
            <pubDate>Sun, 27 Nov 2022 13:10:44 GMT</pubDate>
            <description><![CDATA[<h2 id="옵셔널-체이닝-">옵셔널 체이닝 (?.)</h2>
<pre><code class="language-js">let user = {};
alert(user.address.street);    // TypeError: Cannot read property &#39;street&#39; of undefined</code></pre>
<p>값이 정의되어 있지않은 값을 참조 할 때 <span style="color:red"><code>TypeError</code></span>가 발생하게 되는데, 이럴 경우 옵셔널체이닝 <code>?.</code>을 통해서 평가 대상이 <code>undefined</code>나 <code>null</code>이면 평가를 멈추고 <code>undefined</code>를 반환한다.</p>
<blockquote>
<pre><code class="language-js">let user = {};
</code></pre>
</blockquote>
<p>alert(user?.address?.street);    // undefined</p>
<pre><code>
&gt; 
```js
let user = null;
&gt;
alert( user?.address ); // undefined
alert( user?.address.street ); // undefined</code></pre><p>이렇게 <code>user</code> 객체가 존재하지 않더라도 에러가 발생하지 않는다.</p>
<h3 id="하지만">하지만,</h3>
<blockquote>
</blockquote>
<pre><code class="language-js">&gt;
alert( user?.address ); // ReferenceError: user is not defined</code></pre>
<p>이렇게 <code>user</code>가 정의되어 있지 않을 때는 에러가 발생한다.</p>
<h2 id="reference">Reference</h2>
<p><a href="https://ko.javascript.info/optional-chaining">https://ko.javascript.info/optional-chaining</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] undefined와 null]]></title>
            <link>https://velog.io/@pc_jin/JavaScript-undefined%EC%99%80-null</link>
            <guid>https://velog.io/@pc_jin/JavaScript-undefined%EC%99%80-null</guid>
            <pubDate>Sun, 27 Nov 2022 12:53:09 GMT</pubDate>
            <description><![CDATA[<h2 id="undefined와-null">undefined와 null</h2>
<p>JavsScript에는 &#39;없음&#39;을 <code>undifined</code>와 <code>null</code> 두가지로 나타낼 수 있다.</p>
<h3 id="undefined">undefined</h3>
<pre><code class="language-js">let foo;
foo        // undefined

const obj = {};
obj.prop;    // undefined</code></pre>
<p>값이 대입되지 않은 변수 혹은 속성을 사용하려고 하면 <code>undefined</code>를 반환한다.</p>
<h3 id="null">null</h3>
<pre><code class="language-js">let foo = null;
foo     // null

const obj = {prop: null};
obj.prop     // null</code></pre>
<p><code>null</code>은 객체가 없음을 나타낸다.</p>
<h3 id="typeof-연산">typeof 연산</h3>
<pre><code class="language-js">typeof null     // &#39;object&#39;
typeof undefined     //    &#39;undefined&#39;</code></pre>
<hr>
<h2 id="null-check">Null Check</h2>
<p><code>==</code> 연산자는 비교하는 두 타입을 일치시킨 후 값만 비교하고,
<code>===</code> 연산자는 비교하는 두 타입과 값을 모두 비교한다.</p>
<pre><code class="language-js">null === undefined; // false
null == undefined;  // true

null == 1       // false
null == &#39;hello&#39; // false
null == false   // false

undefined == 1       // false
undefined == &#39;hello&#39; // false
undefined == false   // false</code></pre>
<p>위의 코드를 보면, 
<code>==</code>를 사용해서 <code>undefined</code>와 <code>null</code>에 대해서 Null Check를 할 수 있는 것을 알 수 있다.</p>
<h3 id="추가로---">추가로 . . !</h3>
<pre><code class="language-js">let a = null;
let b;
let c = &#39;123;

if(a){
  // 실행 안됨
}

if(b) {
  // 실행 안됨
}

if(c) {
  // 실행 됨
}</code></pre>
<p><code>if</code>에서 조건으로 작용할 때, 값이 <code>null</code>과 <code>undefined</code>라면 <span style="color:red"><code>false</code></span>로 작동한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue3] v-bind와 v-model]]></title>
            <link>https://velog.io/@pc_jin/Vue3-v-bind%EC%99%80-v-model</link>
            <guid>https://velog.io/@pc_jin/Vue3-v-bind%EC%99%80-v-model</guid>
            <pubDate>Wed, 23 Nov 2022 15:18:44 GMT</pubDate>
            <description><![CDATA[<h2 id="vuejs-data-바인딩">Vue.js data 바인딩</h2>
<p>data 바인딩할 때, <code>v-bind</code>와 <code>v-model</code>을 사용할 수 있다.
두가지의 차이점은</p>
<h3 id="v-bind">v-bind</h3>
<ul>
<li>템플릿을 통해 변수를 변경시킬 수 없음</li>
</ul>
<h3 id="v-model">v-model</h3>
<ul>
<li>템플릿을 통해 변수를 변경시킬 수 있음</li>
</ul>
<hr>
<h2 id="example">example</h2>
<pre><code>&lt;template&gt;
    &lt;p&gt;줄임말과 원래말을 입력하세요.&lt;/p&gt;
    &lt;!-- v-bind는 템플릿을 통해 변수를 변경시킬 수 없음 (abbr값은 변경 안됨 - 일방작용)--&gt;
    &lt;input type=&quot;text&quot; v-bind:value=&quot;abbr&quot; /&gt;
    &lt;!-- v-model은 템플릿을 통해 변수를 변경시킬 수 있음 (normal값은 변경 됨 - 양방향 작용)--&gt;
    &lt;input type=&quot;text&quot; v-model=&quot;normal&quot; /&gt;
    &lt;hr /&gt;
    &lt;abbr v-bind:title=&quot;normal&quot;&gt;{{ abbr }}&lt;/abbr&gt;
&lt;/template&gt;

&lt;script&gt;
    import { ref } from &#39;vue&#39;

    export default {
        setup() {
            const abbr = ref(&#39;CJ&#39;)
            const normal = ref(&#39;CheolJin&#39;)
            return {
                abbr,
                normal,
            }
        },
    }
&lt;/script&gt;</code></pre><ul>
<li>초기 값
<img src="https://velog.velcdn.com/images/pc_jin/post/e5a97e7f-9991-4779-a185-bae2a4a16591/image.png" alt=""></li>
<li>변경
<img src="https://velog.velcdn.com/images/pc_jin/post/2d51728f-c7bf-4c4f-9d0f-bbb33c7bfc7a/image.png" alt=""></li>
</ul>
<blockquote>
<p><code>v-bind</code>로 바인딩한 값<code>(normal)</code>은 CJ로 고정되어 변경이 되지 않는다.</p>
</blockquote>
<ul>
<li>data를 불러오는 것만 가능 (일방 작용)</li>
</ul>
<blockquote>
<p><code>v-model</code>로 바인딩한 값<code>(abbr)</code>은 입력하는 값에 따라서 변경된다.</p>
</blockquote>
<ul>
<li>data를 불러오고 입력해서 변경도 가능 (양방향 작용)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[API 활용] Slack Webhook + Kotlin + SpringBoot]]></title>
            <link>https://velog.io/@pc_jin/API-%ED%99%9C%EC%9A%A9-Slack-Webhook-Kotlin-SpringBoot</link>
            <guid>https://velog.io/@pc_jin/API-%ED%99%9C%EC%9A%A9-Slack-Webhook-Kotlin-SpringBoot</guid>
            <pubDate>Tue, 15 Nov 2022 13:41:13 GMT</pubDate>
            <description><![CDATA[<h2 id="1-webhook-생성">1. Webhook 생성</h2>
<h3 id="원하는-채널에-webhook-app-추가">원하는 채널에 Webhook app 추가</h3>
<ol>
<li>해당 채널 통합에서 앱추가 클릭
<img src="https://velog.velcdn.com/images/pc_jin/post/22fdd294-ce6c-4cd7-bf4d-fab28b181346/image.png" alt=""></li>
<li>Webhook 검색 및 설치
<img src="https://velog.velcdn.com/images/pc_jin/post/1eb3dfa9-ec7d-4f66-b118-ac6a18f94a07/image.png" alt=""></li>
<li>원하는 채널 선택 후 앱 추가
<img src="https://velog.velcdn.com/images/pc_jin/post/3d5be1a1-7033-4f56-8b46-ecb0b81a155d/image.png" alt=""></li>
<li>Webhook URL 기억하기
<img src="https://velog.velcdn.com/images/pc_jin/post/3f333bdb-2217-4557-bca2-c5ef8df2ed48/image.png" alt=""></li>
</ol>
<h2 id="2-kotlin-코드-작성">2. Kotlin 코드 작성</h2>
<h3 id="slackwebhookservicekt">SlackWebhookService.kt</h3>
<pre><code class="language-kotlin">@Service
class SlackWebhookService(private val restTemplate: RestTemplate) {

    fun sendContent(content: String) {
        val jsonObj = JSONObject(
                &quot;&quot;&quot;
                    {&quot;attachments&quot;: [
                        { 
                            &quot;pretext&quot; : &quot;attachments 제목입니다!&quot;,
                            &quot;color&quot; : &quot;#2eb886&quot;,
                            &quot;text&quot; : ${content}
                        }
                      ]
                    }
                &quot;&quot;&quot;.trimIndent()
        )

        val header = HttpHeaders()
        header.contentType = MediaType.APPLICATION_JSON
        val httpEntity = HttpEntity(jsonObj.toString(), header)

        var webhookUrl = &quot;Webhook url을 입력하세요!&quot;

        restTemplate.exchange(webhookUrl, HttpMethod.POST, httpEntity, String::class.java)

    }
}</code></pre>
<h3 id="slackwebhookcontrollerkt">SlackWebhookController.kt</h3>
<pre><code class="language-kotlin">@RestController
class SlackWebhookController(private val webhookCallService: SlackWebhookService) {
    @PostMapping(&quot;/msg&quot;)
    fun messageSendToSlack(@RequestParam(required = true) text: String): ResponseEntity&lt;String&gt;{
        webhookCallService.sendContent(&quot;${text}&quot;)
        return ResponseEntity(&quot;success&quot;, HttpStatus.OK)
    }
}</code></pre>
<p>추가로 <code>RestTemplate</code>를 빈으로 주입 시켜야하는데, 그것은 다시 정리해서 따로 올리도록 하겠다!</p>
<p>자세한 내용은 <a href="https://github.com/devpcjin/SlackApi_webhook">github</a> 참고</p>
<h2 id="3-테스트">3. 테스트</h2>
<h3 id="1-post-man으로-전송">1) Post man으로 전송</h3>
<p><img src="https://velog.velcdn.com/images/pc_jin/post/e47e823c-096e-4345-8bbe-d7a8db016d41/image.png" alt=""></p>
<h3 id="2-slack에서-전송-확인">2) Slack에서 전송 확인</h3>
<p><img src="https://velog.velcdn.com/images/pc_jin/post/17fa4288-7e1d-4aab-9da8-6d1d98a265a6/image.png" alt=""></p>
<blockquote>
<p>메시지 전송 형식(<code>attachments</code>)은 
<a href="https://roseline.oopy.io/4d14964c-53fc-4b65-9e53-026fc52cb9cb">https://roseline.oopy.io/4d14964c-53fc-4b65-9e53-026fc52cb9cb</a>
이곳을 참고</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kotlin] 문자열]]></title>
            <link>https://velog.io/@pc_jin/Kotlin-%EB%AC%B8%EC%9E%90%EC%97%B4</link>
            <guid>https://velog.io/@pc_jin/Kotlin-%EB%AC%B8%EC%9E%90%EC%97%B4</guid>
            <pubDate>Sun, 13 Nov 2022 15:55:45 GMT</pubDate>
            <description><![CDATA[<h2 id="문자열-템플릿">문자열 템플릿</h2>
<pre><code class="language-kotlin">import java.util.Date

fun main() {
    val name = readLine()
    println(&quot;Hello, $name! \n Today is ${Date()}&quot;)
}</code></pre>
<ul>
<li><code>${}</code>의 중괄호 사이에 문자열을 넣어서 사용할 수 있다.</li>
<li><code>$name</code>과 같이 식이 간단한 변수 참조인 경우 중괄호 생략 가능</li>
</ul>
<h3 id="로우-문자열">로우 문자열</h3>
<pre><code class="language-kotlin">import java.util.Date

fun main() {
    val name = readLine()
    val message = &quot;&quot;&quot;
        Hello, $name!
        Today is ${Date()}
    &quot;&quot;&quot;.trimIndent()

    println(message)
}</code></pre>
<h2 id="기본-문자열-연산">기본 문자열 연산</h2>
<h3 id="문자-인덱스">문자 인덱스</h3>
<pre><code class="language-kotlin">&quot;Hello!&quot;.length       // 6
&quot;Hello!&quot;.lastIndex    // 5</code></pre>
<pre><code class="language-kotlin">val s = &quot;Hello!&quot;
println(s[0])        // H
println(s[5])        // !
println(s[10])        // 잘못된 인덱스</code></pre>
<h3 id="문자열-연결">문자열 연결</h3>
<pre><code class="language-kotlin">val s1 = &quot;Hello!&quot;
val s3 = &quot;Hel&quot; + &quot;lo!&quot;
println(s1 == s2) // true  &lt;java : s1.equals(s2)&gt;</code></pre>
<blockquote>
<p>Tip)
자바의 <code>==</code>와 <code>!=</code> 연산자는 참조 동등성을 비교하기 때문에 실제 문자열 내용을 비교하려면 <code>equals()</code> 메서드를 사용해야 한다.
코틀린에서는 <code>==</code>가 기본적으로 <code>equals()</code>를 가리키는 편의 문법이기 때문에 <code>==</code>를 사용하면, 직접 <code>equal()</code>를 호출하므로, 따로 <code>equals()</code>를 호출할 필요가 없다.
&nbsp;
&nbsp;
<strong>코틀린에서 참조 동등성을 쓰려면?</strong></p>
<blockquote>
<p><code>===</code>와 <code>!==</code> 연산자를 사용하면 된다.</p>
</blockquote>
</blockquote>
<h3 id="문자열이-제공하는-함수">문자열이 제공하는 함수</h3>
<ul>
<li><p><code>isEmpty()</code>, <code>isNotEmpty()</code> : 문자열이 비어있는지 검사</p>
<pre><code class="language-kotlin">&quot;Hello&quot;.isEmpty()          // false
&quot;Hello&quot;.isNotEmpty()       // true</code></pre>
</li>
<li><p><code>substring()</code> : 부분 문자열 추출</p>
<pre><code class="language-kotlin">&quot;Hello&quot;.substring(2)       // &quot;llo&quot;
&quot;Hello&quot;.substring(1, 3)    // &quot;el&quot;</code></pre>
</li>
<li><p><code>endsWith()</code>, <code>startsWith()</code> : 접두사나 접미사인지 검사</p>
<pre><code class="language-kotlin">&quot;Hello&quot;.startsWith(&quot;Hel&quot;)  // true
&quot;Hello&quot;.endsWith(&quot;lo&quot;)     // true</code></pre>
</li>
<li><p><code>indexOf()</code> : 인자로 받은 문자나 문자열이 나타나는 첫번째 인덱스를 반환</p>
<pre><code class="language-kotlin">//맨 앞부터 찾기
&quot;abcabc&quot;.indexOf(&#39;b&#39;)      // 1

//주어진 인덱스부터 찾기
&quot;abcabc&quot;.indexOf(&#39;b&#39;, 2)   // 4</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kotlin] 기본문법]]></title>
            <link>https://velog.io/@pc_jin/Kotlin-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%96%B8%EC%96%B4-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@pc_jin/Kotlin-%EC%BD%94%ED%8B%80%EB%A6%B0-%EC%96%B8%EC%96%B4-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Sun, 13 Nov 2022 14:26:54 GMT</pubDate>
            <description><![CDATA[<h2 id="변수-정의하기">변수 정의하기</h2>
<pre><code class="language-kotlin">fun main() {
    val a = readline()!!.toInt()
    val b = readline()!!.toInt()

    println(a + b)
}</code></pre>
<ul>
<li><code>readline()</code> : 한 줄을 읽어 문자열로 반환</li>
<li><code>!!</code> : 널인 경우 예외를 발생</li>
<li><code>toInt()</code> :호출된 문자열을 정숫값으로 변환<ul>
<li>코틀린 String 클래스가 제공하는 메서드</li>
</ul>
</li>
</ul>
<h2 id="가변변수">가변변수</h2>
<pre><code class="language-kotlin">var sum = 1
sum = sum + 2
sum = sum + 3</code></pre>
<ul>
<li><code>val</code> : 불변(immutable) 변수</li>
<li><code>var</code> : 가변(mutable) 변수<blockquote>
<p>불변 변수를 사용하면 함수가 부수 효과를 일으키지 못하고, 함수형 스타일 코드를 장려할 수 있음</p>
</blockquote>
</li>
<li><blockquote>
<p>코드에 대한 추론이 쉬워지기 때문에 가능하면 불변 변수를 사용해야한다.</p>
</blockquote>
</li>
</ul>
<h2 id="문자-타입-char">문자 타입 Char</h2>
<ul>
<li><code>\t</code> : 탭</li>
<li><code>\b</code> : 백스페이스</li>
<li><code>\n</code> : 새줄</li>
<li><code>\r</code> : 캐리지 리턴</li>
<li><code>\&#39;</code>, <code>\&quot;</code> : 작은따옴표, 큰따옴표</li>
<li><code>\\</code> : 역슬래시 </li>
<li><code>\$</code> : 달러 표시</li>
</ul>
<h2 id="수-변환">수 변환</h2>
<pre><code class="language-kotlin">val n = 100 // Int
val l: Long = n // Error : cant&#39; assign Int to Long</code></pre>
<blockquote>
<p>더 큰 범위의 타입으로 변환 하는 경우 다른 박싱한 타입의 깂을 만들어낼 수 있는 가능성이 생기고, 이로 인해 <strong>동등성 요구조건을 만족시키지 못하게 되어 오류</strong>를 발생</p>
</blockquote>
<pre><code class="language-kotlin">println(l == n)</code></pre>
<p>위 코드를 올바른 코드로 인정하면 다음 연산 결과 <span style = "color:red"><code>false</code></span>를 출력</p>
<pre><code class="language-kotlin">val n = 100 // Int
val l: Long = n.toLong()</code></pre>
<h2 id="불-타입과-논리-연산">불 타입과 논리 연산</h2>
<ul>
<li><code>!</code> : not</li>
<li><code>or</code>, <code>and</code>, <code>xor</code> </li>
<li><code>||</code>, <code>&amp;&amp;</code> : 지연 계산</li>
</ul>
<p>코틀린에서는 <code>and</code>와 <code>or</code>가 <code>&amp;</code>와 <code>|</code>를 대신한다.</p>
<p><code>or</code>, <code>and</code>, <code>xor</code> 는  <code>||</code>, <code>&amp;&amp;</code> 보다 우선해 계산된다.</p>
<blockquote>
<p>예를 들어,</p>
</blockquote>
<pre><code class="language-kotlin">a || b and c or d &amp;&amp; e</code></pre>
<p>은</p>
<pre><code class="language-kotlin">a || (((b and c ) or d) &amp;&amp; e)</code></pre>
<p>이다.</p>
<h2 id="reference">Reference</h2>
<p>알렉세이 세두노프, ⌜코틀린 완벽 가이드⌟, 길벗</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 20221109]]></title>
            <link>https://velog.io/@pc_jin/TIL-20221109</link>
            <guid>https://velog.io/@pc_jin/TIL-20221109</guid>
            <pubDate>Wed, 09 Nov 2022 14:04:45 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/pc_jin/post/f10c3abe-c6fe-422e-9efc-0954f80b18d4/image.png" alt=""></p>
<h2 id="마무리">마무리</h2>
<blockquote>
<p>오늘 <code>OJT</code> 끝!
코드 작성하고 하는 것 보다 서버 환경설정하고 프로젝트 빌드하고, 도커이미지 빌드하고 했던게 훨씬 오래 걸렸던 것 같다.</p>
</blockquote>
<blockquote>
<p><code>코틀린 완벽 가이드</code> 책 구매 완료
코틀린으로 프로젝트를 한다고 생각하니 막막하고 걱정도 많이 되지만, 천천히 해보자 어차피 <code>자바도 처음이었고 C/C++도 처음</code>이었을 때가 있었으니까~</p>
</blockquote>
<ul>
<li>도커관련해서 학습한것은 주말에 정리해서 올려야겠다.</li>
<li>회사 적응하고 하느라 TIL도 안쓰고, 학습한 내용 정리도 못하고 일주일이 슥슥 지나간것 같은데, 다시 꾸준히 쓰는 습관을 만들자!</li>
<li>일주일간의 길고 긴 삽질의 끝 -&gt; 앞으로 또 얼마나 많은 삽질을 하게 될까....?</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Vue] nested router]]></title>
            <link>https://velog.io/@pc_jin/Vue-nested-router</link>
            <guid>https://velog.io/@pc_jin/Vue-nested-router</guid>
            <pubDate>Wed, 09 Nov 2022 13:53:08 GMT</pubDate>
            <description><![CDATA[<h2 id="초기-버전">초기 버전</h2>
<h3 id="routerindexjs">router/index.js</h3>
<pre><code class="language-js">const routes = [
    {
        path: &#39;/&#39;,
        name: &#39;PageHome&#39;,
        component: PageHome
    },
    {
        path: &#39;/board&#39;,
        name: &#39;BoardList&#39;,
        component: BoardList
    },
    {
        path: &#39;/detail&#39;,
        name: &#39;BoardDetail&#39;,
        component: BoardDetail
    },
    {
        path: &#39;/write&#39;,
        name: &#39;BoardWrite&#39;,
        component: BoardWrite
    },
]</code></pre>
<ul>
<li><code>BoardList</code>, <code>BoardDetail</code>, <code>BoardWrite</code>는 모두 게시판에 관한 기능이므로 공통 url을 <span style="color:blue"><code>/board</code></span>로 묶어야겠다고 생각했다.</li>
</ul>
<h2 id="삽질1">삽질1</h2>
<h3 id="routerindexjs-1">router/index.js</h3>
<pre><code class="language-js">const routes = [
    {
        path: &#39;/&#39;,
        name: &#39;PageHome&#39;,
        component: PageHome,
    },
    {
        path: &#39;/board&#39;,
        name: &#39;board&#39;,
        component: BoardList,
        children: [
            {
                path: &quot;write&quot;,
                component: BoardWrite,
                name: &#39;BoardWrite&#39;,
            },
            {
                path: &quot;detail&quot;,
                component: BoardDetail,
                name: &#39;BoardDetail&#39;,
            }
        ]
    },
]</code></pre>
<ul>
<li>이렇게 구성을 했더니, <code>/board</code>에서 <code>/detail</code>, <code>/write</code> 페이지로 넘어가지 않고, 페이지가 멈춰있는 문제가 발생했다.</li>
</ul>
<h2 id="해결">해결</h2>
<blockquote>
<p>children을 사용하는 경우는 크게 2가지가 있다.</p>
<blockquote>
<ol>
<li>공통 컨포넌트가 존재하는 경우에 공통 컨포넌트에서 <code>&lt;router-view&gt;&lt;/router-view&gt;</code> 태그를 사용해서 API 요청을 통해 태그에 해당하는 영역을 바꿀 때<ol start="2">
<li>별개의 컨포넌트들을 공통 url을 사용하여 가지 뻗어나갈 때 (v - 원했던 방식)</li>
</ol>
</li>
</ol>
</blockquote>
</blockquote>
<h3 id="routerindexjs-2">router/index.js</h3>
<pre><code class="language-js">import { RouterView } from &#39;vue-router&#39;

const routes = [
    {
        path: &#39;/&#39;,
        name: &#39;PageHome&#39;,
        component: PageHome,
    },
    {
        path: &#39;/board&#39;,
        name: &#39;board&#39;,
        component: RouterView,
        children: [
            {
                path: &quot;write&quot;,
                component: BoardWrite,
                name: &#39;BoardWrite&#39;,
            },
            {
                path: &quot;detail&quot;,
                component: BoardDetail,
                name: &#39;BoardDetail&#39;,
            },
            {
                path: &quot;list&quot;,
                component: BoardList,
                name: &#39;BoardList&#39;,
            }
        ]
    },
]</code></pre>
<ul>
<li>2번 방식으로 진행하기 위해서는 위 처럼 <code>vue-router</code>에서 import한 <code>RouterView</code>를 컨포넌트로 설정하고 List, Detail, Write를 모두 <code>/board</code>에서부터 뻗어져 나오게 하면 된다!<ul>
<li><code>http://xxxxxx/board/write</code> -&gt; BoardWrite</li>
<li><code>http://xxxxxx/board/detail</code> -&gt; BoardDetail</li>
<li><code>http://xxxxxx/board/list</code> -&gt; Boardlist</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Kotlin] 코틀린이란?]]></title>
            <link>https://velog.io/@pc_jin/Kotlin-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@pc_jin/Kotlin-%EC%BD%94%ED%8B%80%EB%A6%B0%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Sun, 30 Oct 2022 13:52:02 GMT</pubDate>
            <description><![CDATA[<h2 id="코틀린은-무엇인가">코틀린은 무엇인가?</h2>
<blockquote>
<p><strong><code>Jetbrains</code>에서 개발한 언어</strong>
자바 플랫폼에서 돌아가는 새로운 프로그래밍 언어로, 자바 라이브러리나 프레임워크와 함께 잘 작동하며, 성능도 자바와 같은 수준이다.</p>
</blockquote>
<hr>
<h2 id="코틀린의-특징">코틀린의 특징</h2>
<blockquote>
<p><strong>코틀린의 주목적</strong></p>
</blockquote>
<ul>
<li>현재 자바가 사용되고 있는 모든 용도에 적합하면서도 더 간결하고 생산적이며 안전한 대체 언어 제공</li>
</ul>
<h3 id="정적-타입-지정-언어">정적 타입 지정 언어</h3>
<ul>
<li>모든 프로그램 구성 요소의 타입을 컴파일 시점에 알 수 있음<ul>
<li>컴파일러가 타입을 검증해줌</li>
<li>자바와 달리 코틀린에서는 컴파일러가 문맥으로부터 변수 타입을 자동으로 유추 (타입 추론 지원)<pre><code class="language-kotlin">var x = 1 // x를 정수(Int) 값으로 타입 추론</code></pre>
<h3 id="null-안정성">Null 안정성</h3>
</li>
</ul>
</li>
<li>Null이 될 수 있는 타입도 지원<ul>
<li><code>null pointer exception</code>으로 부터 자유로움</li>
</ul>
</li>
</ul>
<h3 id="합수-타입-지원">합수 타입 지원</h3>
<ul>
<li>함수형 프로그래밍을 지원<ul>
<li>함수를 작성해서 변수에 저장할 수도 있고, 다른 함수에 전달, 반환이 가능</li>
</ul>
</li>
</ul>
<hr>
<h2 id="왜-코틀린을-사용하는가">왜 코틀린을 사용하는가?</h2>
<blockquote>
<p>자바와 상호운용서을 갖춘 간결하며 안전한 언어이기 때문에</p>
</blockquote>
<h3 id="실용성">실용성</h3>
<ul>
<li><strong>다른 프로그래밍 언어가 채택한 이미 성공적으로 검증된</strong> 해법과 기능에 의존</li>
</ul>
<h3 id="간결성">간결성</h3>
<ul>
<li>getter, setter, 생성자 파라미터를 필드에 대입하기 위한 로직 등 자바에 존재하는 여러 가지 번거로운 준비 코드를 묵시적으로 제공</li>
<li>람다를 지원하기 때문에 작은 코드 블록을 라이브러리 함수에 쉽게 전달</li>
</ul>
<h3 id="안전성">안전성</h3>
<ul>
<li>JVM에서 실행한다는 사실은이미 상당한 안전성을 보장할 수 있다는 뜻<ul>
<li>JVM을 사용하면 메모리 안전성을 보장하고, 버퍼 오버플로우를 방지하며, 동적으로 할당한 메모리를 잘못 사용함으로 인해 발생할 수 있는 다양한 문제를 예방</li>
</ul>
</li>
</ul>
<h3 id="상호운용성">상호운용성</h3>
<ul>
<li>기존 자바 라이브러리를 가능하면 최대한 활용함</li>
</ul>
<hr>
<h2 id="reference">Reference</h2>
<p><a href="https://incheol-jung.gitbook.io/docs/study/kotlin-in-action/1">https://incheol-jung.gitbook.io/docs/study/kotlin-in-action/1</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 20221029]]></title>
            <link>https://velog.io/@pc_jin/TIL-20221029</link>
            <guid>https://velog.io/@pc_jin/TIL-20221029</guid>
            <pubDate>Sat, 29 Oct 2022 14:44:40 GMT</pubDate>
            <description><![CDATA[<h2 id="오늘의-일기">오늘의 일기</h2>
<blockquote>
<p>어제 오늘 푹<del>~ 놀았다!
오랜만에 술도 먹고! 이제 마음 가라앉히고 준비해보자!
룰루</del></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>