<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>lucky-kor.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 19 Nov 2021 20:24:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. lucky-kor.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/lucky-korma" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[기본 정렬 알고리즘]]></title>
            <link>https://velog.io/@lucky-korma/%EA%B8%B0%EB%B3%B8-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@lucky-korma/%EA%B8%B0%EB%B3%B8-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Fri, 19 Nov 2021 20:24:07 GMT</pubDate>
            <description><![CDATA[<h2 id="선택-정렬-selection-sort">선택 정렬 (Selection sort)</h2>
<p>선택 정렬은 이름과 같이, 현재 위치에 들어갈 값을 찾아 정렬하는 방법입니다. 
현재 위치에 들어갈 값의 크기가 작으면 최소 선택 정렬 (Minimum Selection sort), 값의 크기가 크다면 최대 선택 정렬 (Maximum Selection sort)로 구분 할 수 있습니다.
최소 선택 정렬은 오름차순으로 정리되고, 최대 선택 정렬은 내림차순으로 정렬됩니다.</p>
<p>최소 선택 정렬의 정렬 로직은 다음과 같습니다.</p>
<p>정렬되지 않은 인덱스의 맨 앞부터, 배열의 마지막까지 값 중 가장 작은 값을 찾습니다.</p>
<p>가장 작은 값을 찾는다면(첫 인덱스부터 전체 조회가 끝난 이후) 그 값을 현재 인덱스의 값과 교체합니다.</p>
<p>다음 인덱스부터(N+1) 위의 과정을 반복합니다.</p>
<p>한번 탐색이 끝날때마다 탐색 범위의 맨 앞의 인덱스에 최소값이 고정되기 떄문에 선택 정렬 알고리즘은 n개, n-1개, n-2개 ... 1개까지 비교를 반복해서 진행하게 됩니다.</p>
<p>첫 배열의 정렬상태와 상관없이 전체 배열의 비교를 진행하기 떄문에 시간복잡도는 O(N^2)입니다.</p>
<p>공간복잡도는 하나의 배열에서 비교를 진행하기 때문에 O(N)입니다.</p>
<h2 id="버블-정렬-bubble-sort">버블 정렬 (Bubble sort)</h2>
<p>버블 정렬은 매번 인접한 두개의 인덱스에 할당된 값을 비교하여 정한 기준(오름차순, 내림차순)에 따라 기준의 값의 위치를 변경하는 정렬 알고리즘입니다.
오름차순으로 정렬할 경우, 비교를 진행할때마다 큰 값이 1칸씩 뒤로 이동하며 배열을 한 번 순회할때마다 제일 큰 값이 가장 마지막의 인덱스에 위치하게 됩니다.
제일 마지막에 순회하며 비교한 값들중 가장 큰 값이 제일 뒤로 위치하여 고정되기 때문에, n-1개, n-2개 ... 1개까지 비교를 반복하여 O(N^2)의 시간복잡도를 가지게 됩니다.
공간복잡도도 하나의 배열에서 비교를 진행하기 때문에 O(N)입니다.</p>
<p>(오름차순) 버블 정렬의 동작 로직은 다음과 같습니다.</p>
<p>두번째 인덱스부터, 바로 앞의 인덱스의 값과 비교를 시작합니다.</p>
<p>이전 인덱스의 값이 현재 인덱스의 값보다 크다면 현재 인덱스의 값과 바꿔줍니다.</p>
<p>현재 인덱스가 더 크다면 교환하지 않습니다.</p>
<p>위의 과정을 배열의 마지막 인덱스까지 반복합니다.</p>
<p>한번 순회를 거칠때마다 순회한 구간의 맨 마지막 인덱스는 자동으로 고정되므로, 배열의 길이가 7이라면 6번, 5번, 4번 이와같이 순회하는 배열의 마지막 인덱스가 하나씩 줄어들게 됩니다.</p>
<h2 id="삽입-정렬-insertion-sort">삽입 정렬 (Insertion Sort)</h2>
<p>삽입 정렬은 배열의 두번째 인덱스부터 시작하며, 현재 위치에서 그 이하의(앞의 인덱스의) 배열을 비교하며 자신의 위치를 찾아서 그 위치에 값을 삽입하는 정렬입니다.</p>
<p>삽입 정렬의 로직은 다음과 같습니다.</p>
<ol>
<li>두번째 인덱스부터 시작합니다. 현재 인덱스의 값은 별도의 변수에 저장한 후, 비교 인덱스를 현재 인덱스 -1 로 설정합니다.</li>
<li>별도로 저장한 변수의 값과, 비교 인덱스의 값을 비교하여, 비교 인덱스의 값이 더 작으면 현재 인덱스를 -1로 변경하며 인덱스가 0이 될 때까지 반복합니다. 비교 인덱스의 값보다 크다면 현재 인덱스 +1에 별도로 저장한 변수의 값을 저장합니다.</li>
<li>위 과정을 마지막 인덱스까지 반복합니다.</li>
</ol>
<p>삽입 정렬 알고리즘의 경우 n-1개, n-2개, ... 1개까지 비교를 진행하여 시간복잡도는 O(n^2)입니다. 다만 다른 정렬 알고리즘과 다른점은 현재 저장된 배열의 값이 모두 정렬되어 있는 상태라면 배열을 한번만 순회하기 때문에 O(n)의 시간복잡도를 나타나게 되는 특징이 있습니다.</p>
<p>비교를 진행할때 하나의 배열만을 사용하기에, 공간복잡도는 O(n)입니다.</p>
<h2 id="병합-정렬-merge-sort">병합 정렬 (Merge sort)</h2>
<p>병합 정렬은 <strong>분할 정복 알고리즘</strong>(Divide and conquer algorithm) 방식으로 설계된 알고리즘입니다. <strong>분할 정복 알고리즘</strong>은 큰 문제를 반으로 쪼개어 해결하는 방식으로 병합 정렬의 경우, 배열의 길이가 1이 될때까지 쪼개어 반복합니다.</p>
<p>하나의 배열을 입력받아, 두개의 배열로 계속 쪼개나간 후, 분할이 모두 이루어진 이후에 다시 합치는 과정을 거치며 정렬된 하나의 배열을 출력(리턴)합니다.</p>
<p>분할 과정은 다음과 같습니다.</p>
<ol>
<li>현재 배열을 반으로 나누어줍니다.</li>
<li>나누어진 배열의 길이가 1보다 클 경우, 다시 1번을 반복합니다.</li>
<li>나누어진 베열의 길이가 1보다 작을경우 분할 과정을 종료합니다.</li>
</ol>
<p>분할 과정의 경우 크기가 n인 배열을 매번 분할한다면 처음은 n/2 n/2개, 두번째는 n/4 n/4 n/4 n/4개</p>
<p>, 이런 과정을 반복하게 되어서, logn만큼의 시간복잡도를 가지게 됩니다.</p>
<p>이후 합병 과정이 진행됩니다.</p>
<ol>
<li>두 배열 a,b의 요소를 비교합니다. 현재 인덱스를 i, j로 가정합니다.</li>
<li>a[i]와, b[j]를 비교합니다.</li>
<li>오름차순의 경우, a[i]보다 b[j]가 크다면 a[i]를 C라는 새 배열에 저장한 후, i의 값을 1 증가합니다.</li>
<li>2~3의 과정을 i 혹은 j가 배열의 끝까지 도달할때까지 반복합니다.</li>
<li>i 혹은 j가 배열의 끝까지 도달한 이후 남은 값을 C 배열에 모두 저장합니다.</li>
<li>C 배열을 원래의 배열에 저장합니다.</li>
</ol>
<p>합병 과정의 경우 나누어진 배열만큼의 시간복잡도를 가지게 됩니다. 원래 주어진 배열이 C라고 한다면, C라는 배열을 A, B로 반씩 나누었을때 O(A + B)의 시간복잡도를 가지게 됩니다.
A + B = C이므로, O(N)의 시간복잡도를 가지게 됩니다.</p>
<p>분할과 합병과정을 모두 거치므로, 병합정렬의 경우 O(nlogn)의 시간복잡도를 가지게 됩니다.</p>
<p>배열은 정렬을 위한 배열을 하나 더 사용하므로, 2N이 됩니다.</p>
<p>별도의 최적화 과정(in place)과정을 거친다면 새로운 배열을 사용하지 않고 인덱스만으로 분할 과정을 거쳐서 사용되는 메모리를 줄일 수 있습니다.</p>
<h2 id="퀵-정렬-quick-sort">퀵 정렬 (Quick sort)</h2>
<p>퀵 정렬은 병합 정렬과 비슷하게 <strong>정복 알고리즘</strong>(Divide and conquer algorithm) 방식으로 설계된 알고리즘입니다. pivot이라는 하나의 기준이 되는 값을 정하고 이 값보다 작은 값들을 왼쪽, 큰 값들을 오른쪽으로 옮기는 방법으로 정렬이 이루어 집니다. 이를 반복해 분할되는 배열의 길이가 1보다 작을때까지 반복하게 됩니다.</p>
<p>퀵 정렬이 동작하는 순서는 다음과 같습니다.</p>
<ol>
<li>리스트 안에 있는 한 요소를 선택한다. 이렇게 고른 원소를 피벗(pivot) 이라고 한다.</li>
<li>피벗을 기준으로 피벗보다 작은 요소들은 모두 피벗의 왼쪽으로 옮겨지고 피벗보다 큰 요소들은 모두 피벗의 오른쪽으로 옮겨진다. (피벗을 중심으로 왼쪽: 피벗보다 작은 요소들, 오른쪽: 피벗보다 큰 요소들)</li>
<li>피벗을 제외한 왼쪽 리스트와 오른쪽 리스트에 대하여 1~2번 과정을 통해 정렬을 반복합니다.</li>
<li>해당 리스트의 크기가 1보다 작을때까지 위 과정을 반복합니다.</li>
</ol>
<h2 id="힙-정렬-heap-sort">힙 정렬 (Heap sort)</h2>
<p>힙 정렬의 경우, 힙 트리 자료구조를 사용하여 데이터를 정렬하는 알고리즘입니다. 간단히 힙이라는 자료구조에 대해 알아보고 갈게요.</p>
<p><strong>힙</strong>(heap)은 최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된 완전이진트리(complete binary tree)를 기본으로 한 자료구조(tree-based structure)입니다. 항상 루트 노드에 최대값 혹은 최소값이 존재하고, 데이터를 추가하거나 삭제했을때 정렬이 빠른 장점이 있습니다.</p>
<p>오름차순으로 정렬이 필요하다고 가정할 때, 최대힙을 구현하면 항상 루트 노드에 최대값이 존재하기 때문에, 루트 노드의 값을 배열의 가장 마지막 부분에 저장하고 값을 고정한 이후에, 해당 노드를 제외하고 다시 최대힙으로 정렬 과정을 거치게 됩니다.</p>
<ol>
<li>최대 힙으로 데이터 정렬</li>
<li>루트 노드의 값을 트리의 가장 마지막 값과 교환</li>
<li>교환한 가장 마지막 위치에 값을 저장하고 고정</li>
<li>가장 마지막 값을 제외한(n-1) 데이터를 다시 최대 힙으로 정렬</li>
<li>2~4번을 반복하여 루트 노드를 제외한 모든 값이 고정될 때까지 반복합니다.</li>
</ol>
<p>위의 과정이 힙 정렬을 사용하여 데이터를 정렬하는 방식입니다.</p>
<p>힙 트리에서 데이터를 정렬하는 시간복잡도는 logn이며, 데이터를 정렬하는 과정을 n번만큼 진행하기 때문에, 시간복잡도는 O(nlong)이 됩니다.</p>
<p>완전이진트리 구조는 배열로 쉽게 변환이 가능하고, 정렬과정에서 새로운 배열을 사용하지 않기 때문에, 공간복잡도는 o(n)입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트에서의 호이스팅]]></title>
            <link>https://velog.io/@lucky-korma/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C%EC%9D%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@lucky-korma/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C%EC%9D%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Wed, 14 Jul 2021 05:58:21 GMT</pubDate>
            <description><![CDATA[<h3 id="호이스팅hoisting의-개념">호이스팅(Hoisting)의 개념</h3>
<p>함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것입니다.</p>
<h4 id="호이스팅이란">호이스팅이란</h4>
<p>자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언하게 됩니다.
자바스크립트가 함수 실행 전 해당 함수의 내용을 한번 체크합니다.
함수 안에 존재하는 변수,함수선언에 대한 내용을 체크하고 있다가 실행합니다. 유혀범위는 함수 블록 안에서 유효합니다.
이말은, 함수 내에서 하단에 위치한 내용 중 필요한 값을 상단으로 끌어올리는 것입니다. 실제 코드가 상단으로 끌어올려지는것은 아니며, 자바스크립트에서 내부적으로 끌어올려서 처리하는 것으로 실제 메모리에서는 변화가 없습니다.</p>
<h4 id="호이스팅의-대상">호이스팅의 대상</h4>
<ul>
<li>var 변수 선언과 함수선언문에서만 호이스팅이 일어납니다.</li>
<li>var 변수/함수의 선언만 위로 끌어 올려지며, 할당은 그대로 위치합니다.</li>
<li>let/const 변수 선언과 함수표현식에서는 호이스팅이 발생하지 않습니다.</li>
</ul>
<h3 id="간단한-예시">간단한 예시</h3>
<blockquote>
<p>작성한 코드</p>
</blockquote>
<pre><code class="language-javascript">console.log(&quot;hello world&quot;);
var catName = &quot;Lucky&quot;; // var 변수 
let cat2Name = &quot;Vanilla&quot;; // let 변수 </code></pre>
<p>실제 동작시 코드</p>
<pre><code class="language-javascript">var catName;
console.log(&quot;hello world&quot;);
catName = &quot;Lucky&quot;; // var 변수 
let cat2Name = &quot;Vanilla&quot;; // let 변수 </code></pre>
<blockquote>
<p>작성한 코드</p>
</blockquote>
<pre><code class="language-javascript">func1();
func2();
function func1() { // 함수선언문
  console.log(&quot;hello Lucky&quot;);
}
var func2 = function() { // 함수표현식
  console.log(&quot;hello Vanilla&quot;);
}</code></pre>
<p>실제 동작하는 코드</p>
<pre><code class="language-javascript">var func2;
function func1() { // 함수선언문
  console.log(&quot;hello Lucky&quot;);
}
func1();  //&quot;hello Lucky! 출력
func2();  //ERROR! TypeError: func2 is not a function
func2 = function() { // 함수표현식
  console.log(&quot;hello Vanilla&quot;);
}</code></pre>
<h3 id="함수-선언식에서의-호이스팅">함수 선언식에서의 호이스팅</h3>
<blockquote>
<p>작성한 코드</p>
</blockquote>
<pre><code class="language-javascript">function howling(catName) {
    var func1 = setName();
    console.log(typeof setName);
    console.log(func1 + &#39; meow meow&#39;);
    function setName() {
        return catName;
    }
}
howling(&#39;Lucky&#39;);</code></pre>
<p>실제 동작하는 코드</p>
<pre><code class="language-javascript">function howling(catName) { // 함수선언식
      var func1;    //변수 선언(호이스팅)
    function setName() { // 함수선언식(호이스팅)
      return catName;
    }
    func1 = setName(); //할당
    console.log(typeof setName); // &gt; &quot;function&quot;
    console.log(func1 + &#39; meow meow&#39;); // &gt; &quot;Lucky meow meow&quot;
}
howling(&#39;Lucky&#39;);</code></pre>
<p>함수 선언문은 작성한 위치와 상관없이, 자바스크립트 호이스팅의 특징으로 상단으로 끌어올려집니다.</p>
<h4 id="함수-표현식에서의-호이스팅">함수 표현식에서의 호이스팅</h4>
<blockquote>
<p>선언이 호출보다 상단에 존재하는 경우</p>
</blockquote>
<pre><code class="language-javascript">function howling(catName) {
  var func1 = function() {
    return catName;
  }
  var func2 = func1();
  console.log(func2 + &quot; meow meow&quot;);
}
howling(&#39;Lucky&#39;);</code></pre>
<pre><code class="language-javascript">function howling(catName) {
  var func1;    //함수표현식 선언(호이스팅)
  var func2;    //함수 선언(호이스팅)
  func1 = function() {    //함수표현식 할당
      return catName;
  }
  func2 = func1();
  console.log(func2 + &quot; meow meow&quot;);    // &quot;Lucky meow meow&quot;
}
howling(&#39;Lucky&#39;);</code></pre>
<p>문제없이 출력됩니다.</p>
<blockquote>
<p>선언이 호출보다 하단에 존재하는 경우</p>
</blockquote>
<pre><code class="language-javascript">function howling(catName) {
  console.log(func2);
  var func2 = func1();
  console.log(func2 + &quot; meow meow&quot;);
  var func1 = function() {
    return catName;
  }
}
howling(&#39;Lucky&#39;);</code></pre>
<pre><code class="language-javascript">function howling(catName) {
  var func1;
  console.log(func2);    // 선언은 되었으나, 할당이 되지 않아 &quot;undefined&quot;가 출력됩니다.
  var func2 = func1();    //ERROR! TypeError: func1 is not a function
  console.log(func2 + &quot; meow meow&quot;);
  func1 = function() {
    return catName;
  }
}
howling(&#39;Lucky&#39;);</code></pre>
<p>func1은 선언만 되고, 할당은 호이스팅이 되지 않아서 undefined입니다. 해당 값이 함수가 아니기 때문에 var func2 = func1()에서 타입오류가 생기게 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[조합, 순열, 부분집합 Javascript]]></title>
            <link>https://velog.io/@lucky-korma/%EC%A1%B0%ED%95%A9-%EC%88%9C%EC%97%B4-%EB%B6%80%EB%B6%84%EC%A7%91%ED%95%A9-Javascript</link>
            <guid>https://velog.io/@lucky-korma/%EC%A1%B0%ED%95%A9-%EC%88%9C%EC%97%B4-%EB%B6%80%EB%B6%84%EC%A7%91%ED%95%A9-Javascript</guid>
            <pubDate>Wed, 30 Jun 2021 03:29:17 GMT</pubDate>
            <description><![CDATA[<h3 id="조합">조합</h3>
<pre><code class="language-javascript">const getCombination = (arr, n) =&gt; {
  const result = [];
  if(n === 1) return arr.map(e =&gt; [e]);
  arr.forEach((e, idx, origin) =&gt; {
    const rest = origin.slice(idx + 1);
    const combinations = getCombination(rest, n-1);
    const attached = combinations.map(combi =&gt; [e, ...combi]);
    result.push(...attached);
  });
  return result;
}</code></pre>
<h3 id="순열">순열</h3>
<pre><code class="language-javascript">const getPermutations= function (arr, selectNumber) {
  const results = [];
  if (selectNumber === 1) return arr.map((value) =&gt; [value]);

  arr.forEach((fixed, index, origin) =&gt; {
    const rest = [...origin.slice(0, index), ...origin.slice(index+1)]
    const permutations = getPermutations(rest, selectNumber - 1);
    const attached = permutations.map((permutation) =&gt; [fixed, ...permutation]);
    results.push(...attached);
  });

  return results;
};</code></pre>
<h3 id="부분집합">부분집합</h3>
<pre><code class="language-javascript">// 비트연산자 사용
let result = [];

for(let i = 1; i &lt; (1 &lt;&lt; arr.length); i++) {
      result.push([]);
    for(let j = 0; j &lt; arr.length; j++) {
        if(i &amp; (1 &lt;&lt; j)) result[i-1].push(arr[j])
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[코드스테이츠 27기를 마치며]]></title>
            <link>https://velog.io/@lucky-korma/%EC%BD%94%EB%93%9C%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%B8%A0-27%EA%B8%B0%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0</link>
            <guid>https://velog.io/@lucky-korma/%EC%BD%94%EB%93%9C%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%B8%A0-27%EA%B8%B0%EB%A5%BC-%EB%A7%88%EC%B9%98%EB%A9%B0</guid>
            <pubDate>Fri, 25 Jun 2021 10:33:46 GMT</pubDate>
            <description><![CDATA[<p>코스가 끝난지 2주가 지났지만 뒤늦게 후기를 작성합니다... 사실 이후에 다른과정을 2주동안 추가로 진행하게되어서 코스가 끝났다는 안도감을 느낄틈도 없이 시간이 흘러갔어요.....</p>
<p>정말 힘들기도 많이 힘들었고 즐겁기도 정말 즐거운 반년의 과정이였습니다. 처음 수많은 부트캠프중 코드스테이츠를 선택한 제 자신과, 코드스테이츠를 추천해준 지인분들께 너무 고맙다는 말을 전하고 싶어요...!!</p>
<p>길게 6달동안의 과정에 따라 느낀점을 작성해보자면...처음 프리코스애서는 편안하고 어렵지않게 진행하였습니다. 완전하게 아무것도 모르는상태로 코스에 들어온게 아닌 저로써는 기본을 다시 다잡고 넘어가는 과정이였습니다. 그런데....중간 발표때마다 너무너무 잘하시는분들이 많아서 스스로에게 많이 실망도 하고...속상한 마음이 들때마다 힘든 순간이 많았습니다. 실제로 주어진 과제는 어렵지 않게 완수해 제출하였으나 다른분들과 비교했을때 위축되는 기분이 드는건 어쩔수 없더라구요...그럴때마다 주변의 다른분들과 엔지니어분들의 피드백으로 한걸음씩 나아갔던것 같습니다. 코스를 모두 완주한 지금은 왜 그때 그렇게까지 힘들어했을까?? 라는 생각이 들정도로 스스로 많은 발전이 있었어요...!</p>
<p>코드스테이츠를 진행하면서 정말 마음에 들었던 부분을 몇가지 말씀드리면 재일 중요한건 항상 페어와 함께 진행하는부분이 너무 좋았습니다. 새로운 사람을 만나서 서로 다양한 의견을 공유하고 함께 과제를 수행해나가는 부분이 처음에는 어색했으나, 나중에는 혼자 진행하면 뭔가 어색하고 섭섭한 마음이 들더라구요...실제로 코드스테이츠에 방문하는 일정이 생기면서 함께 진행했던 페어분을 만났을때 너무 반갑고 즐거웠습니다. 이렇게 다양한 코연을 만들어 나가는게 너무 기뻐요...!!</p>
<p>그리고 자기주도적 학습...정말 중요합니다. 코드스테이츠를 포함한 대부분의 부트캠프는 모든 정답을 알려드리지 않아요..! 스스로 필요한 부분을 찾아서 공부하는 습관이 필요한데, 세션중에 래퍼런스를 찾는 방법이 있었습니다. 해당 과정을 통해서 스스로 찾아보고 배울수 있는 과정이 너무 중요했어요! 오해는 하지 마세요! 실제로 스스로 찾을수 없을때는 수많은 크루분들이 여러분을 위해 기다리고 있습니다. 저도 많은분들에게 많은 도움을 받았습니다 :)</p>
<p>또 빼놓을수 없는 프로젝트....정말 실패도 겪고,많은 배움도 얻을수 있는 과정입니다. 앞서서 배운 모든것들은 이 과정을 위해서 노력했다고 말할 수 있을정도로 제겐 큰 도움이 되었어요...! 다른 부트캠프와 다르게 클론 프로젝트를 진행하지 않고 정말 아무것도 없는 무에서 유를 창조하는 과정을 직접 경험하게 됩니다... 신체적으로는 정말 너무 힘들었어요.. 잠을 엄청 줄이고 항상 피곤하지만 맥북앞에 앉아있는 일상을 경험하게 됩니다. 그런데 그게 또 너무 즐거워요 :) 정말 다양한 소통과 의견공유가 이루어지고, 스스로에게 부족한 부분과 다른분에게서 배워야 할 부분을 바로 느낄 수 있는 과정입니다. 지금애서야 프로젝트를 또 진행하라고 하시면 조금 쉬었다가 기쁜 마음으로 진행할 정도로 제게는 만족감이 높았습니다!</p>
<p>일기장에 일기를 쓰는것처럼 작성이 되었지만, 스스로에게 만족할수 있는 과정이 아니였나 하는 생각이 듭니다.. 만약 누군가가 개발자로의 커리어 전환을 생각해서 제게 부트캠프에 대해 물어본다면 저는 코드스테이츠를 꼭 추천할것 같아요 :)</p>
<p>행복했고 즐거웠습니다. 안녕 나의 코드스테이츠😀</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코드스테이츠 파이널 프로젝트 회고... :)]]></title>
            <link>https://velog.io/@lucky-korma/%EC%BD%94%EB%93%9C%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%B8%A0-%ED%8C%8C%EC%9D%B4%EB%84%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@lucky-korma/%EC%BD%94%EB%93%9C%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%B8%A0-%ED%8C%8C%EC%9D%B4%EB%84%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 25 Jun 2021 10:04:15 GMT</pubDate>
            <description><![CDATA[<p>프로젝트가 끝난지 시간이 꽤 지났지만.. 이후에 특별반과 이력서 준비등으로 미뤄졌던 파이날 프로젝트의 회고를 드디어 작성합니다!!
4주동안 진행되었으며, 4명이서 작업을 진행하였습니다.</p>
<h2 id="프로젝트-소개">프로젝트 소개</h2>
<p>[ 배포 링크 ] <a href="https://picaff.ga">https://picaff.ga</a>
[ 깃헙 링크 ] <a href="https://github.com/codestates/picaff-server">https://github.com/codestates/picaff-server</a>
[ 소개 문서 ] <a href="https://bit.ly/3ddzdwu">https://bit.ly/3ddzdwu</a>
[ 미팅 로그 ] <a href="https://bit.ly/3gPXJpR">https://bit.ly/3gPXJpR</a>
[ 코드 리뷰 ] <a href="https://bit.ly/35Sjjnc">https://bit.ly/35Sjjnc</a> </p>
<p><strong>피카프(PICAFF)</strong>는 유저의 취향을 분석하여, 
각 유저에게 적합한 홈카페 아이템을 추천해 드리는 <strong>맞춤형</strong> <strong>큐레이션 서비스</strong>입니다.</p>
<ul>
<li><p><strong>📃 간단한 취향파악 설문</strong></p>
<p>  간단한 질문 몇 가지를 통하여 내게 맞는 홈카페 취향을 확인 할 수 있어요.</p>
</li>
<li><p><strong>☕ 내 취향에 맞는 원두 정보와 추출용품 정보</strong></p>
<p>  취향에 맞춰 맛있게 먹을 수 있는 원두와 커피용품까지 추천해줘요.</p>
</li>
<li><p><strong>🤼 친구들과 공유하기</strong></p>
<p>  친구들에게 서비스를 공유해요.</p>
</li>
<li><p><strong>💸 오픈마켓 시세 정보 확인</strong></p>
<p>  현재 오픈 마켓에서는 내 취향의 커피는 어느 정도에 거래되는지 바로 알려줘요.</p>
</li>
<li><p>메인 랜딩페이지</p>
<img src='https://s3.us-west-2.amazonaws.com/secure.notion-static.com/55033adc-2508-4789-a563-5392ef367dfd/main_page.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210625%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210625T090337Z&X-Amz-Expires=86400&X-Amz-Signature=9e178539b37c3b1cbd5b4543633683a4b15d906ea0a50d57d25ad5c274970f39&X-Amz-SignedHeaders=host'/>
</li>
<li><p>설문조사 페이지</p>
<img src='https://s3.us-west-2.amazonaws.com/secure.notion-static.com/a6d61a3c-ca96-4454-a12a-fbfb1bd6e3f8/suggestions.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210625%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210625T090809Z&X-Amz-Expires=86400&X-Amz-Signature=615d0a7c8e5d00274f6d930b8fe625554e525147744918d203ce66001fad87d9&X-Amz-SignedHeaders=host'/>
</li>
<li><p>설문조사 이후 추천아이템 조회</p>
<img src='https://s3.us-west-2.amazonaws.com/secure.notion-static.com/7979c69d-7608-4e29-a653-92d2e17b1f72/result.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210625%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210625T090807Z&X-Amz-Expires=86400&X-Amz-Signature=9f12706d605078401010f2e48632f518641869ed521a3aebc08cac8a84cabfc4&X-Amz-SignedHeaders=host'/>
</li>
<li><p>개별 아이템 조회</p>
<img src ='https://s3.us-west-2.amazonaws.com/secure.notion-static.com/6bf40091-e56f-45c9-818b-491919108baa/coffeeitem.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210625%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210625T090327Z&X-Amz-Expires=86400&X-Amz-Signature=1cf60c3b6ebf63a771a61cc4e0820ca43608ed6ea39ef701f009813bd51a2619&X-Amz-SignedHeaders=host'/>

</li>
</ul>
<h3 id="프로젝트-기획">프로젝트 기획</h3>
<p>처음 프로젝트의 아이디어는 서로 다양한 의견을 모아봤으나, 정훈님의 의견중에 하나인 커피관련 큐레이션 서비스를 제작해보자는 의견을 채택하게 되었습니다. 마침 제가 전에 다니던 직장이 커피 관련회사로 정보를 얻기가 매우 수월했습니다 :)</p>
<p>퍼스트 프로젝트때 기획단계를 너무 부실하게 진행하여 프로젝트를 진행하면서 너무 많은 부분에서 수정사항이 발생했던 경험이 있었습니다. 파이널 프로젝트는 일주일동안 정말 세세하게 팀원간의 지켜야할 룰, 코드리뷰시간, 회의진행시간과 회의록 작성방법, Dev-log작성등에 대한 부분까지 모두 결정하고 진행하였습니다. 목업, 스키마디자인, 워크플로우등 모든 작업을 다 함께 miro를 사용해 진행하였고, git에서 협업을 위해 사용할 브랜치와, 풀리퀘 이후 머지 이전에 지켜야할 규칙,  사용해야할 명령어까지 모두 기획단계에서 정하게 되었습니다.</p>
<p>기획단계에서 정말 많이 배우고 얻었던 경험이 따로 많은데, 정훈님께서 보일러플레이트를 클라이언트/서버쪽 모두 제작해주셨습니다. 기획단계에서 처음 경험해보는 작업이였고, 해당 과정은 이후 단계별로 개발과정이 진행되면서 너무 큰 도움이 되었습니다.
또한 깃에서 작업한 내용을 PR을 보낼때마다 나머지 3분의 코드리뷰(검수?)를 받았을때만, 머지를 진행할 수 있게 설정하였고, 각각의 풀리퀘, 머지가 진행될때 디스코드로 연동하여 바로바로 알람으로 확인 할 수 있게 설정하여 진행한것도 너무 큰 도움이 되었습니다.</p>
<h3 id="타입스크립트typescript-typeorm-사용">타입스크립트(TypeScript), TypeORM 사용</h3>
<p>프로젝트에서 새로 도입한 기술은 타입스크립트와, 타입스크립트를 사용하기 위해 적용한 TypeORM이였습니다. 
개인적으로 JS를 배우기 이전에 JAVA를 먼저 배웠던 경험이 있어서 타입을 지정해주는것 자체에 크게 어려움은 없었습니다. 하지만 TypeORM에서 Entity를 설정해주는 부분에서 이전에 사용하던 시퀄라이즈와의 차이점과, Entity에서도 타입을 지정해줘야 하는 부분에서 조금 어려움을 느꼈습니다.
타입스크립트도 처음에는 어렵지 않게 시작하였지만, 개발이 진행될수록, 예상하지 못하는 오류들을 많이 만나게 되었습니다. 기존의 JS를 사용할때와는 다르게, 타입이 지정되다보니 해당 변수에 들어오는 타입에 따라 예외처리를 진행해 주지 않으면 코드 작성과정에서 오류가 생겨나는것을 여러번 경험했습니다.
하지만 하나하나 작성해나가면서 기존의 JS를 사용했을때와는 다르게 조금 더 명확하게 오류가 발생하는 부분을 미리 체크할 수 있었고, 사용하는 다양한 변수의 타입을 미리 알 수 있어서 코드 작성이 훨씬 편하게 느껴졌습니다.
조금 아쉬운 부분은 제네릭 타입을 완벽하게 이해하지 못해서, 제대로 적용하지 못한점과 as캐스팅을 최대한 피하고 싶었지만, 해결법을 찾지못해 몇몇부분에서 해당 캐스팅을 사용한점이 조금 아쉬웠습니다.</p>
<h3 id="파이널-프로젝트가-끝나고-나서의-느낀점">파이널 프로젝트가 끝나고 나서의 느낀점</h3>
<p>정말 4주동안 잠도 많이 줄이고 건강을 포기하고 프로젝트에 집중할만큼 최선을 다했습니다. 새로운 타입스크립트를 사용하고, 크롤러 제작을 위해 새로운 모듈을 사용하며 공부할 시간도 필요했기때문에, 주말에는 주로 새롭게 공부가 필요한부분에 집중해서 시간을 투자했습니다. 아마 그래도 지금 팀원분들이 아니였다면 성공하기 어렵지 않았을까..? 라는 생각이 들기도 합니다.. 정말 서로 모르는 부분이나, 어려운 부분에 대해서 솔직하게 말씀드리고 필요한 정보들과 조금 더 빠르게 익히기 위해 필요한 레퍼런스들을 서로 공유하면서 빠르게 프로젝트에 적용시킬 수 있었습니다.
또한 아침마다 오전회의를 진행하여, 현재 진행상황과 문제점, 오늘의 작업을 서로 공유하면서 작업을 진행하였습니다. 해당 내용을 모두 회의록으로 기록해 남겨두었습니다.
오후에는 항상 다들 다시 만나서, 오늘 작성한 코드에 대한 리뷰시간을 가졌습니다. 이 부분이 정말 많은 도움이 되었습니다. 보완할점이나, 해당 작성한 코드에서 정말 좋은부분이 있다면 그 부분에 대해 서로 의견을 공유하였습니다. 처음에는 코드리뷰라는것 자체가 부담스럽고, 잘할수 있을까..? 라는 마음이 앞섰지만, 프로젝트를 진행하면서 3주차가 지날때쯤에는 코드리뷰시간이 매우 기다려지는 순간이 오게 되었습니다.</p>
<p>작업을 마치고, 배포까지 모두 확인한 이후..정말 후련함과 아쉬운 감정이 너무 크게 다가왔습니다. 스스로 만족할만한 결과이긴 하지만, 제가 조금 더 타입스크립트를 빠르게 익혔다면..? 배포를 조금 더 빠르게 진행했다면..? 하는 아쉬움이 크게 남았습니다. 하지만 이번 프로젝트를 진행하면서 제일 큰 소득은 소통의 중요성과, 처음 기획단계의 중요성을 크게 느낀것만으로도 만족스러운 프로젝트가 아니였나 생각합니다 :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자료구조 Stack, Queue]]></title>
            <link>https://velog.io/@lucky-korma/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-Stack-Queue</link>
            <guid>https://velog.io/@lucky-korma/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-Stack-Queue</guid>
            <pubDate>Thu, 24 Jun 2021 19:32:45 GMT</pubDate>
            <description><![CDATA[<h2 id="스택stack">스택(Stack)</h2>
<p><img src="https://images.velog.io/images/lucky-korma/post/b2a9f73b-65b7-4264-a795-803211df8f7f/R1280x0.png" alt=""></p>
<h3 id="스택의-개념">스택의 개념</h3>
<p>스택(stack)은 제한적으로 접근할 수 있는 나열 구조입니다. 그 접근 방법은 언제나 목록의 끝에서만 일어나게 됩니다.</p>
<p>스택은 한 쪽 끝에서만 자료를 넣거나 뺄 수 있는 선형 구조(LIFO - Last In First Out)으로 되어 있습니다. 자료를 넣는 것을 &#39;밀어넣는다&#39; 하여 푸쉬(push)라고 하고 반대로 넣어둔 자료를 꺼내는 것을 팝(pop)이라고 하는데, 이때 꺼내지는 자료는 가장 최근에 푸쉬한 자료부터 나오게 된니다. 이처럼 나중에 넣은 값이 먼저 나오는 것을 LIFO(Last In First Out) 구조라고 합니다.</p>
<p>그리고 비어있는 스택에서 원소를 추출하려고 할 때 stack underflow라고 하며,
스택이 넘치는 경우 stack overflow라고 합니다. (우리가 흔히 접하는 유명한 사이트의 이름이 여기서 유래되었습니다)</p>
<h3 id="스택의-활용-예시">스택의 활용 예시</h3>
<ul>
<li>웹 브라우저의 방문기록 (뒤로가기)</li>
<li>실행 취소 (가장 나중에 실행된 명령부터 취소)</li>
<li>역순 문자열 만들기 (가장 나중에 입력된 문자열부터 출력)</li>
<li>재귀 알고리즘에서 유용하게 사용</li>
<li>하노이의탑(유명한 알고리즘)</li>
</ul>
<h2 id="큐queue">큐(Queue)</h2>
<h3 id="큐의-개념">큐의 개념</h3>
<p><img src="https://images.velog.io/images/lucky-korma/post/96d914e3-a445-416d-9441-3d5b001ecd59/R1280x0-2.png" alt=""></p>
<p>Queue 의 사전적 의미는 1. (무엇을 기다리는 사람, 자동차 등의) 줄 , 혹은 줄을 서서 기다리는 것을 의미합니다.
따라서 일상생활에서 놀이동산에서 줄을 서서 기다리는 것, 은행에서 먼저 온 사람의 업무를 창구에서 처리하는 것과 같이
선입선출(FIFO, First in first out) 방식의 자료구조입니다.</p>
<p>정해진 한 곳(top)을 통해서 삽입, 삭제가 이루어지는 스택과는 달리
큐는 한쪽 끝에서 삽입 작업이, 다른 쪽 끝에서 삭제 작업이 양쪽으로 이루어지게 됩니다.
이때 삭제연산만 수행되는 곳을 프론트(front), 삽입연산만 이루어지는 곳을 리어(rear)로 정하여 각각의 연산작업만 수행됩니다. 이때, 큐의 리어에서 이루어지는 삽입연산을 인큐(enQueue)
프론트에서 이루어지는 삭제연산을 디큐(dnQueue)라고 부르고 있습니다.</p>
<h3 id="큐의-활용-예시">큐의 활용 예시</h3>
<ul>
<li>프로세스 관리</li>
<li>캐시(Cache) 구현</li>
<li>우선순위가 같은 작업 예약(프린터의 인쇄 대기열)</li>
<li>너비우선탐색 구현(BFS)</li>
</ul>
<h2 id="시간복잡도">시간복잡도</h2>
<p>스택과 큐 모두 데이터의 삽입/삭제의 경우 <code>O(1)</code>의 시간복잡도를 가지고 있습니다. 그래서 데이터의 삽입과 삭제가 매우 빠르다는 장점을 가지고 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[REST API 정확히 알고 사용하기!]]></title>
            <link>https://velog.io/@lucky-korma/REST-API-%EC%A0%95%ED%99%95%ED%9E%88-%EC%95%8C%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@lucky-korma/REST-API-%EC%A0%95%ED%99%95%ED%9E%88-%EC%95%8C%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 18 Jun 2021 08:02:30 GMT</pubDate>
            <description><![CDATA[<h2 id="rest-api의-탄생배경">REST API의 탄생배경</h2>
<p>REST는 Representational State Transfer라는 용어의 약자로서 2000년도에 로이 필딩 (Roy Fielding)의 박사학위 논문에서 최초로 소개되었습니다. 로이 필딩은 HTTP의 주요 저자 중 한 사람으로 그 당시 웹(HTTP) 설계의 우수성에 비해 제대로 사용되어지지 못하는 모습에 안타까워하며 웹의 장점을 최대한 활용할 수 있는 아키텍처로써 REST를 발표했다고 합니다.</p>
<h2 id="rest-api-구성요소">REST API 구성요소</h2>
<ul>
<li>자원(RESOURCE) - URL
모든 자원에는 고유한 ID가 존재하게 되고, 이 자원은 Server에 존재한다. 해당 고유한 ID는 HTTP URL로 구분 할 수 있습니다.</li>
<li>행위(Verb) - HTTP METHOD
클라이언트에서는 HTTP Method(POST, GET, DELETE, PUT)를 사용하여 지정한 자원에 대한 요청을 보낼 수 있습니다.</li>
<li>표현(Representations)
클라이언트에서 자원에 대한 조작을 요청하면 서버에서는 적절한 응답(Representation)을 보내야 합니다.</li>
</ul>
<h2 id="rest-api의-특징">REST API의 특징</h2>
<ul>
<li><p>Uniform (유니폼 인터페이스)
REST는 HTTP 표준에만 따른 다면, 어떠한 기술이라던지 사용이 가능한 인터페이스 스타일입니다. 예를 들어 HTTP+JSON으로 REST API를 정의했다면, 안드로이드 플랫폼이건, iOS 플랫폼이건, 또는 C나 Java/Python이건 특정 언어나 기술에 종속 받지 않고 HTTP와 JSON을 사용할 수 있는 모든 플랫폼에 사용이 가능한 느슨한 결함(Loosely coupling) 형태의 구조이다.</p>
</li>
<li><p>Stateless (무상태성)
REST는 무상태성 성격을 갖습니다. 다시 말해 작업을 위한 상태정보를 따로 저장하고 관리하지 않습니다. 세션 정보나 쿠키정보를 별도로 저장하고 관리하지 않기 때문에 API 서버는 들어오는 요청만을 단순히 처리하면 됩니다. 때문에 서비스의 자유도가 높아지고 서버에서 불필요한 정보를 관리하지 않음으로써 구현이 단순해집니다.</p>
</li>
<li><p>Cacheable (캐시 가능)
REST의 가장 큰 특징 중 하나는 HTTP라는 기존 웹표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 그대로 활용이 가능합니다. 따라서 HTTP가 가진 캐싱 기능이 적용 가능합니다. HTTP 프로토콜 표준에서 사용하는 Last-Modified태그나 E-Tag를 이용하면 캐싱 구현이 가능합니다.</p>
</li>
<li><p>Self-descriptiveness (자체 표현 구조)
REST의 또 다른 큰 특징 중 하나는 REST API 메시지만 보고도 이를 쉽게 이해 할 수 있는 자체 표현 구조로 되어 있다는 것입니다.</p>
</li>
<li><p>Client - Server 구조
REST 서버는 API 제공, 클라이언트는 사용자 인증이나 컨텍스트(세션, 로그인 정보)등을 직접 관리하는 구조로 각각의 역할이 확실히 구분되기 때문에 클라이언트와 서버에서 개발해야 할 내용이 명확해지고 서로간 의존성이 줄어들게 됩니다.</p>
</li>
</ul>
<p>6) 계층형 구조
REST 서버는 다중 계층으로 구성될 수 있으며 보안, 로드 밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있고 PROXY, 게이트웨이 같은 네트워크 기반의 중간매체를 사용할 수 있게 합니다.</p>
<h2 id="rest-api-디자인">REST API 디자인</h2>
<ul>
<li>URI는 정보의 자원을 표현해야 한다. (리소스명은 동사보다는 명사를 사용)</li>
<li>자원에 대한 행위는 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.</li>
<li>슬래시 구분자(/)는 계층 관계를 나타낼 때 사용한다.<blockquote>
<p><code>https://naver.com/comic/</code></p>
</blockquote>
</li>
<li>URL 마지막 문자로 슬래시(/)를 포함하지 않는다.</li>
<li>하이픈(-)은 URL 가독성을 높이는데 이용한다.</li>
<li>언더바(_) 문자는 URI에 사용하지 않습니다.</li>
<li>URI를 작성하는 데에는 소문자가 적합하다.</li>
<li>파일 확장자는 URL에 포함시키지 않는다.</li>
</ul>
<h2 id="rest-api에서-피해야-할-패턴">REST API에서 피해야 할 패턴</h2>
<ul>
<li>GET/POST를 이용한 터널링</li>
</ul>
<p>가장 나쁜 디자인 중 하나가 GET이나 POST를 이용한 터널링입니다.
<code>http://lucky.co.kr/?method=update&amp;id=cat</code> 이 경우가 전형적인 GET을 이용한 터널링입니다. 메서드의 실제 동작은 리소스를 업데이트 하는 내용인데, HTTP PUT을 사용하지 않고, GET에 쿼리 패러미터로 method=update라고 넘겨서, 이 메서드가 수정 메세드임을 명시했습니다. 대단히 안좋은 디자인으로, HTTP 메서드 사상을 따르지 않았기 때문에, REST라고 부를 수 도 없고, 또한 웹 캐쉬 인프라등도 사용이 불가능합니다.</p>
<ul>
<li>Self-descriptiveness 속성을 사용하지 않음</li>
</ul>
<p>앞서 특징에서 설명한 바와 같이 REST의 특성중 하나는 자기 서술성(Self-descriptiveness) 속성으로 REST URI와 메서드 그리고 쉽게 정의된 메시지 포맷에 의해서 쉽게 API를 이해할 수 있는 기능이 되어야 합니다.</p>
<ul>
<li>HTTP Response code를 사용하지 않음
다음으로 많이 하는 실수중의 하나가 Http Response code를 충실하게 따르지 않고, 성공은 200, 실패는 500 과 같이 1~2개의 HTTP response code만 사용하는 경우입니다. 심한 경우에는 에러도 HTTP Response code 200으로 정의한후 별도의 에러 메시지를 200 response code와 함께 보내는 경우인데, 이는 REST 디자인 사상에도 어긋남은 물론이고 자기 서술성에도 어긋납니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[DFS, BFS의 설명, 차이점]]></title>
            <link>https://velog.io/@lucky-korma/DFS-BFS%EC%9D%98-%EC%84%A4%EB%AA%85-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@lucky-korma/DFS-BFS%EC%9D%98-%EC%84%A4%EB%AA%85-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Mon, 14 Jun 2021 07:40:53 GMT</pubDate>
            <description><![CDATA[<h3 id="bfs-dfs-두가지-모두-그래프를-탐색하는-방법입니다">BFS, DFS 두가지 모두 그래프를 탐색하는 방법입니다.</h3>
<p>그래프란, <strong>정점(node)</strong>과 그 정점을 연결하는 <strong>간선(edge)</strong>으로 이루어진 자료구조의 일종을 말하며,
그래프를 탐색한다는 것은 하나의 정점으로부터 시작하여 차례대로 모든 정점들을 한 번씩 방문하는 것을 말합니다.</p>
<h4 id="dfs-깊이-우선-탐색-depth-first-search">DFS 깊이 우선 탐색 (Depth-First Search)</h4>
<p><img src="https://images.velog.io/images/lucky-korma/post/30737a15-9adf-49a6-96a0-98c211cab1cc/R1280x0.gif" alt=""></p>
<center>출처 https://developer-mac.tistory.com/64</center>


<p>루트 노드(혹은 다른 임의의 노드)에서 시작해서 다음 분기로 넘어가기 전에 해당 분기를 완벽하게 탐색하는 방식을 말합니다.</p>
<p>예를 들어, 미로찾기를 할 때 최대한 한 방향으로 갈 수 있을 때까지 쭉 가다가 더 이상 갈 수 없게 되면 다시 가장 가까운 갈림길로 돌아와서 그 갈림길부터 다시 다른 방향으로 탐색을 진행하는 것이 깊이 우선 탐색 방식이라고 할 수 있습니다.</p>
<ol>
<li>모든 노드를 방문하고자 하는 경우에 이 방법을 선택함</li>
<li>깊이 우선 탐색(DFS)이 너비 우선 탐색(BFS)보다 좀 더 간단함</li>
<li>검색 속도 자체는 너비 우선 탐색(BFS)에 비해서 느림</li>
</ol>
<h4 id="bfs-너비-우선-탐색-breadth-first-search">BFS 너비 우선 탐색 (Breadth-First Search)</h4>
<p><img src="https://images.velog.io/images/lucky-korma/post/2112183b-bfcd-427e-8072-c9dc983180ba/R1280x0-2.gif" alt=""></p>
<center>출처 https://developer-mac.tistory.com/64</center>

<p>루트 노드(혹은 다른 임의의 노드)에서 시작해서 인접한 노드를 먼저 탐색하는 방법으로,
시작 정점으로부터 가까운 정점을 먼저 방문하고 멀리 떨어져 있는 정점을 나중에 방문하는 순회 방법입니다.</p>
<p>주로 두 노드 사이의 최단 경로를 찾고 싶을 때 이 방법을 선택합니다.
ex) 지구 상에 존재하는 모든 친구 관계를 그래프로 표현한 후 Sam과 Eddie사이에 존재하는 경로를 찾는 경우</p>
<ul>
<li>깊이 우선 탐색의 경우 - 모든 친구 관계를 다 살펴봐야 할지도 모름</li>
<li>너비 우선 탐색의 경우 - Sam과 가까운 관계부터 탐색</li>
</ul>
<h3 id="dfs-bfs-비교">DFS, BFS 비교</h3>
<p><img src="https://images.velog.io/images/lucky-korma/post/e2ef7ac3-14e6-42e7-a768-224c5f773e29/R1280x0-3.gif" alt=""></p>
<center>출처 https://namu.wiki/w/BFS</center>

<p><span></span></p>
<table>
<thead>
<tr>
<th>DFS(깊이우선탐색)</th>
<th>BFS(너비우선탐색)</th>
</tr>
</thead>
<tbody><tr>
<td>현재 정점에서 갈 수 있는 점들까지 들어가면서 탐색</td>
<td>현재 정점에 연결된 가까운 점들부터 탐색</td>
</tr>
<tr>
<td><strong>스택</strong> 또는 <strong>재귀함수</strong>로 구현</td>
<td><strong>큐</strong>를 이용해서 구현</td>
</tr>
</tbody></table>
<p><span></span></p>
<h3 id="dfs와-bfs의-시간복잡도">DFS와 BFS의 시간복잡도</h3>
<p>두 방식 모두 조건 내의 모든 노드를 검색한다는 점에서 시간 복잡도는 동일합니다.
DFS와 BFS 둘 다 다음 노드가 방문하였는지를 확인하는 시간과 각 노드를 방문하는 시간을 합하면 됩니다.</p>
<p>깊이 우선 탐색(DFS)과 너비 우선 탐색(BFS) 활용한 문제 유형/응용</p>
<p>DFS, BFS은 특징에 따라 사용에 더 적합한 문제 유형들이 있습니다.</p>
<ul>
<li>그래프의 모든 정점을 방문하는 것이 주요한 문제
단순히 모든 정점을 방문하는 것이 중요한 문제의 경우 DFS, BFS 두 가지 방법 중 어느 것을 사용하셔도 상관없습니다.
둘 중 편한 것을 사용하시면 됩니다.</li>
<li>경로의 특징을 저장해둬야 하는 문제
예를 들면 각 정점에 숫자가 적혀있고 a부터 b까지 가는 경로를 구하는데 경로에 같은 숫자가 있으면 안 된다는 문제 등, 각각의 경로마다 특징을 저장해둬야 할 때는 DFS를 사용합니다. (BFS는 경로의 특징을 가지지 못합니다)</li>
<li>최단거리 구해야 하는 문제
미로 찾기 등 최단거리를 구해야 할 경우, BFS가 유리합니다.
왜냐하면 깊이 우선 탐색으로 경로를 검색할 경우 처음으로 발견되는 해답이 최단거리가 아닐 수 있지만, 
너비 우선 탐색으로 현재 노드에서 가까운 곳부터 찾기 때문에경로를 탐색 시 먼저 찾아지는 해답이 곧 최단거리기 때문입니다.</li>
</ul>
<p>이밖에도 </p>
<ul>
<li>검색 대상 그래프가 정말 크다면 DFS를 고려</li>
<li>검색대상의 규모가 크지 않고, 검색 시작 지점으로부터 원하는 대상이 별로 멀지 않다면 BFS</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Semantic Tags (시맨틱 태그)]]></title>
            <link>https://velog.io/@lucky-korma/Semantic-Tags-%EC%8B%9C%EB%A7%A8%ED%8B%B1-%ED%83%9C%EA%B7%B8</link>
            <guid>https://velog.io/@lucky-korma/Semantic-Tags-%EC%8B%9C%EB%A7%A8%ED%8B%B1-%ED%83%9C%EA%B7%B8</guid>
            <pubDate>Mon, 14 Jun 2021 06:19:28 GMT</pubDate>
            <description><![CDATA[<h3 id="시맨틱-태그란">시맨틱 태그란..?</h3>
<p>Semantic은 &#39;의미의&#39;,&#39;의미론의&#39;라는 뜻으로 시맨틱 태그는 태그 자체만으로 해당 태그가 어떤 기능을 나타내는지 의미를 포함하고 있는 태그입니다.</p>
<p>이전 HTML4에서 <code>&lt;div&gt;</code>를 사용하여 웹 문서를 만들었을때, 시각장애인 낭독기(screen reader) 혹은 검색엔진에서 웹소스를 읽어올때, 어느부분이 본문인지, 어느부분이 헤더부분인지 구별하기가 쉽지 않았습니다. 그래서 HTML5부터 표준화된 문서구조를 만들어주는 시맨틱태그가 등장하였습니다.</p>
<p><del><img src="https://images.velog.io/images/lucky-korma/post/af628af1-fe28-48c8-8944-3d7cd3fce901/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-06-14%20%EC%98%A4%ED%9B%84%203.24.18.png" alt=""></del>
시맨틱 태그는 HTML5부터 도입되었으며, 대표적으로 <code>&lt;form&gt;</code>, <code>&lt;table&gt;</code>, <code>&lt;article&gt;</code> 같은 태그입니다.</p>
<p>일반적으로 <code>&lt;div&gt;</code>, <code>&lt;p&gt;</code> 같은 태그는 해당 태그 안에 이미지가 들어갈지, 텍스트가 들어갈지 어떤 값이 들어가 있을지 예측 할 수 없습니다. 하지만 시맨틱태그는 태그 이름만으로 어떤 값이 들어갈지, 어떤 용도로 사용될지 예측할 수 있습니다.
예를들어 <code>&lt;table&gt;</code> 태그안에는 표가 들어갈 것이라는걸 예측 할 수 있고, <code>&lt;article&gt;</code> 태그안에는 글이 들어갈 것이라는걸 예상 할 수 있습니다.</p>
<p>HTML5 이전에는 header나 footer를 나타내기 위해 </p>
<pre><code class="language-html">&lt;div class=&quot;header&quot;&gt; header &lt;/div&gt;
&lt;div class=&quot;footer&quot;&gt; footer &lt;/div&gt;</code></pre>
<p>처럼 사용되었다면, HTML5 이후로는</p>
<pre><code class="language-html">&lt;header&gt; header &lt;/header&gt;
&lt;footer&gt; footer &lt;/footer&gt;</code></pre>
<p>처럼 간단하게 시맨틱 태그를 사용하여 작성할 수 있습니다.</p>
<h3 id="시맨틱-태그를-사용하는-이유">시맨틱 태그를 사용하는 이유</h3>
<h4 id="검색-엔진-최적화seo-search-engine-optimization">검색 엔진 최적화(SEO: Search Engine Optimization)</h4>
<p>검색엔진이 웹페이지의 자료를 수집하거나 순위를 방식에 맞게 웹페이지를 구성하여, 검색 결과의 상위에 나올 수 있게하는 행위를 말합니다.
SEO를 위해서는 검색어를 페이지에 적절하게 배치해야 합니다. 검색엔진은 결과를 보여줄 때, HTML의 태그들을 분석합니다. 이 때, Semantic한 문서는 검색엔진이 유의미한 결과를 낳을 수 있도록 합니다.</p>
<h4 id="웹페이지의-의미부여">웹페이지의 의미부여</h4>
<p>의미요소(Semantic Element)는 HTML로 만든 문서에 추가적으로 의미를 부여해줍니다.</p>
<p>시맨틱 태그를 사용하여 의미를 부여해준다면, 해당 페이지를 유지보수하기 위해서 다시 문서를 분석할 경우, 시간을 절약할 수 있습니다.
협업을 진행하며, 개발자들 사이에서 변수의 지정이나, 개발도구의 환경등 여러가지 표준을 만들고 작업을 시작하는 것처럼, 시맨틱태그를 사용하여 웹페이지를 제작하면 해당 웹페이지를 함께 작업하는 사람들이 훨씬 쉽고 빠르게 접근이 가능합니다.</p>
<h3 id="시맨틱-태그의-종류">시맨틱 태그의 종류</h3>
<p><code>&lt;header&gt;</code> 문서나 Section의 상단 정보 영역을 의미
<code>&lt;footer&gt;</code> 문서나 Section의 하단 정보 영역을 의미
<code>&lt;article&gt;</code> 문서나 사이트에서 독립된 컨텐츠 영역을 지정
<code>&lt;aside&gt;</code> 페이지의 왼쪽 혹은 오른쪽에 위치한 컨텐츠영역
<code>&lt;details&gt;</code> 추가정보를 기술하는 영역을 의미
<code>&lt;figcaption&gt;</code> <code>&lt;figure&gt;</code>의 제목을 지정
<code>&lt;figure&gt;</code> 문서흐름상 이해를 위해 필요한 그림, 동영상을 포함할때 사용
<code>&lt;main&gt;</code> 문서의 주 컨텐츠영역을 지정
<code>&lt;mark&gt;</code> 마크되거나 강조된 텍스트를 의미
<code>&lt;nav&gt;</code> 문서를 연결하는 네비게이션
<code>&lt;section&gt;</code> 주제별 컨텐츠 영역, 컨텐츠별로 페이지의 묶음단위를 의미</p>
<h3 id="ie8-이하버젼-대응하기">IE8 이하버젼 대응하기</h3>
<p>html5에서 추가되는 태그나 css3 속성들은 지원하지 않기 때문에 특별히 지정을 해줘야 합니다. css 에서 시맨틱 태그를 블럭처리하거나 자바스크립트로 시맨틱 태그 요소를 새로 생성하는 방법이 있습니다만 번거롭습니다. 그래서 간단하게 html5shiv.js 파일을 로드하는 방법을 많이 이용합니다. IE8 이하 버젼만 적용되면 되므로 아래처럼 <code>&lt;head&gt;</code>태그 사이에 작성해주면 됩니다.</p>
<pre><code class="language-html">&lt;head&gt;
    ....
    &lt;!-- [if lt IE 9&gt;
        &lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js&quot;&gt;&lt;/script&gt;
    &lt;![endif] --&gt;
&lt;/head&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] cmarket-redux]]></title>
            <link>https://velog.io/@lucky-korma/TIL-cmarket-redux</link>
            <guid>https://velog.io/@lucky-korma/TIL-cmarket-redux</guid>
            <pubDate>Mon, 05 Apr 2021 08:30:12 GMT</pubDate>
            <description><![CDATA[<p>이번 페어 과제는 redux를 이용해 저번에 진행하였던 cmarket의 기능을 구현하는 과제였습니다.</p>
<p>총 구현해야 할 기능은 3가지였습니다.</p>
<ol>
<li>상품리스트 화면에서 상품 화면아래 &quot;장바구니 담기&quot; 버튼을 클릭했을때 장바구니에 해당 상품이 추가되는 기능</li>
<li>장바구니 화면에서 상품목록 옆에 &quot;삭제&quot;버튼을 클릭시 해당 상품이 리스트에서 삭제되는 기능</li>
<li>장바구니 화면에서 상품목록 옆에 해당 상품의 갯수를 바꿀 때, 장바구니 안의 해당 상품의 수량이 변경되는 기능</li>
</ol>
<h4 id="세가지-경우-모두-">세가지 경우 모두 ,</h4>
<p><code>action/index.js</code> 에서</p>
<pre><code>export const addToCart = (itemId) =&gt; {
  return {
    type: ADD_TO_CART,
    payload: {
      quantity: 1,
      itemId
    }
  }
}

export const removeFromCart = (itemId) =&gt; {
  return {
    type: REMOVE_FROM_CART,
    payload: {
      itemId
    }
  }
}

export const setQuantity = (itemId, quantity) =&gt; {
  return {
    type: SET_QUANTITY,
    payload: {
      itemId,
      quantity
    }
  }
}
</code></pre><p>위의 내용을 추가해 action.payload로 불러와 사용할 값을 보내줍니다.</p>
<h4 id="이후-첫번째-상품을-장바구니에-추가하는-내용은">이후 첫번째 상품을 장바구니에 추가하는 내용은</h4>
<p><code>pages/ItemListContainer.js</code>에서</p>
<pre><code>const handleClick = (item) =&gt; {
    if (!cartItems.map((el) =&gt; el.itemId).includes(item.id)) {
      dispatch(addToCart(item.id));
      dispatch(notify(`장바구니에 ${item.name}이(가) 추가되었습니다.`))
    }</code></pre><p>위의 3번째 줄에 dispatch로 리듀서에 해당 함수와 변수를 보내주게 됩니다.</p>
<p>그리고 <code>reducer/ItemReducer.js</code>파일에서</p>
<pre><code>    case ADD_TO_CART:
      return Object.assign({}, state, {
        cartItems: [...state.cartItems, action.payload]
      });</code></pre><p>해당 내용을 추가해주면 기능이 정상적으로 작동합니다.
<code>Object.assign</code>를 사용해 기존의 상태인 state와 state.cartItems와 dispatch로 입력받은 값(action.payload)을 합쳐서 리턴해주게 됩니다.</p>
<h4 id="두번째-장바구니에서-해당-제품을-삭제하는-기능은">두번째 장바구니에서 해당 제품을 삭제하는 기능은</h4>
<p><code>pages/ShoppingCart.js</code>에서</p>
<pre><code>const handleDelete = (itemId) =&gt; {
    setCheckedItems(checkedItems.filter((el) =&gt; el !== itemId))
    dispatch(removeFromCart(itemId));
  }</code></pre><p>해당 내용을 추가해 dispatch로 해당 함수와 변수를 보내준 후,
<code>reducer/ItemReducer.js</code>파일에서</p>
<pre><code>    case REMOVE_FROM_CART:
      let curItem = state.cartItems.filter(el =&gt; el.itemId !== action.payload.itemId)
      return Object.assign({}, state, {
        cartItems: curItem
      })</code></pre><p>해당 내용을 추가해주면 기능이 정상적으로 작동합니다.
cutItem이라는 변수 안에 state.cartitems에 저장된 전체 배열의 값 중 선택해서 지울 아이템만 filter로 지우고 남은 값들만 배열로 저장한 후, 리턴값에 해당 변수를 함께 포함하여 리턴합니다.</p>
<h4 id="세번째-장바구니에서-해당-제품의-수량을-변경하는-기능은">세번째 장바구니에서 해당 제품의 수량을 변경하는 기능은</h4>
<p><code>pages/ShoppingCart.js</code>에서</p>
<pre><code>const handleQuantityChange = (quantity, itemId) =&gt; {
    dispatch(setQuantity(itemId, quantity));
  }</code></pre><p>해당 내용을 추가해 dispatch로 해당 함수와 변수를 보내준 후,
<code>reducer/ItemReducer.js</code>파일에서</p>
<pre><code>    case SET_QUANTITY:
      let idx = state.cartItems.findIndex(el =&gt; el.itemId === action.payload.itemId);

      let editQuantity = state.cartItems.map(function(el, index) {
        if(idx === index){
          return {itemId: action.payload.itemId, quantity: action.payload.quantity}
        }else{
          return el;
        }
      })</code></pre><p>해당 내용을 추가해주면 기능이 정상적으로 작동합니다.
idx라는 변수 안에 수량을 바꿀 상품의 인덱스값이 저장되고,
해당 값을 사용해 장바구니에 저장된 값들을 모두 map으로 순회하며, 조건문을 사용해 해당 값에서만 dispatch로 받아온 아이템의 Id와 quantity값을 직접 입력해 변경해 주었습니다.</p>
<p>이후 해당 변경된 값을 포함해 리턴하여주었습니다.</p>
<p>이후 추가 advanced과제를 익일 도전 할 예정입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 자바스크립트에서 커링(currying)과 클로져(closure)]]></title>
            <link>https://velog.io/@lucky-korma/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EC%BB%A4%EB%A7%81currying%EA%B3%BC-%ED%81%B4%EB%A1%9C%EC%A0%B8closure</link>
            <guid>https://velog.io/@lucky-korma/JS-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EC%BB%A4%EB%A7%81currying%EA%B3%BC-%ED%81%B4%EB%A1%9C%EC%A0%B8closure</guid>
            <pubDate>Mon, 05 Apr 2021 04:11:56 GMT</pubDate>
            <description><![CDATA[<p>Currying은 여러 개의 인자를 가진 함수를 호출 할 경우, 파라미터의 수보다 적은 수의 파라미터를 인자로 받으면서 누락된 파라미터를 인자로 받는 기법을 말한다. 즉 커링은 함수 하나가 n개의 인자를 받는 과정을 n개의 함수로 각각의 인자를 받도록 하는 것이다. 부분적으로 적용된 함수를 체인으로 계속 생성해 결과적으로 값을 처리하도록 하는 것이 그 본질이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux 의미와 특징]]></title>
            <link>https://velog.io/@lucky-korma/Redux-%EC%9D%98%EB%AF%B8%EC%99%80-%ED%8A%B9%EC%A7%95</link>
            <guid>https://velog.io/@lucky-korma/Redux-%EC%9D%98%EB%AF%B8%EC%99%80-%ED%8A%B9%EC%A7%95</guid>
            <pubDate>Mon, 05 Apr 2021 02:39:57 GMT</pubDate>
            <description><![CDATA[<h2 id="1redux-정보">1.Redux 정보</h2>
<p>리덕스는 사용률이 높은 라이브러리입니다. Redux를 사용하면, 단순 react 라이브러리를 사용했을때와 다르게, 컴포넌트별로 상태를 공유할 때 여러 컴포넌트를 거치지 않고 손쉽게 상태를 관리, 변경이 가능합니다.
또한, 리덕스에서는 브라우져 내에 추가적인 기능을 통해서 현재 상태에 대한 정보를 확인하기가 편리해집니다.
그래서 React와 다르게 컴포넌트별로 관리되지 않아, 상태확인이 더 쉬워지고, 유지보수도 좀 더 편리해집니다.</p>
<h2 id="redux의-특징">Redux의 특징</h2>
<p>Redux의 특징은 크게 3가지로 나뉘어집니다.</p>
<h4 id="1single-source-of-truth-store">1.Single source of truth (Store)</h4>
<p>같은 데이터는 항상 같은 장소에서 관리됩니다.</p>
<h4 id="2state-is-read-only-action">2.State is read-only (Action)</h4>
<p>React에서는 상태를 변경할 때, setState를 사용해 변경해야만 했던것처럼, Redux에서는 Action이라는 객체를 통해서 상태를 변경 할 수 있습니다.</p>
<p>해당 객체는 다음과 같은 형식으로 이루어져 있습니다.</p>
<pre><code>{
  Type : &quot;ADD_TODO&quot; ,
  data : {
    id : &quot;0&quot;,
    text : &quot;study Redux&quot;
  }
}</code></pre><p>액션 객체는 반드시 <code>Type</code> 필드를 가지고 있어야 하고, 그 이외의 값들은 자유롭게 셋팅이 가능합니다.</p>
<h4 id="3changes-are-made-with-pure-functions-reducer">3.Changes are made with pure functions (Reducer)</h4>
<p>변경은 순수 함수로만 가능합니다. 해당 내용은 리듀서와 연관되어 있습니다. Reducer는 2번의 상태 변경을 위한 Action과 연결되며, Action객체가 Dispatch에게 전달되고, Dispatch는 Reducer를 호출하여 새로운 상태를 만들어냅니다.</p>
<p>리듀서의 사용방법은 아래와 같습니다.</p>
<pre><code>function reducer(state, action) {
  return alteredState;
}</code></pre><p>리듀서는 state와 action이라는 두가지 파라미터를 받아오게 되어 있습니다. 현재 상태와 전달받은 액션을 사용하여 새로운 상태를 반환합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] Reduce]]></title>
            <link>https://velog.io/@lucky-korma/JS-Reduce</link>
            <guid>https://velog.io/@lucky-korma/JS-Reduce</guid>
            <pubDate>Fri, 12 Mar 2021 08:53:00 GMT</pubDate>
            <description><![CDATA[<h3 id="reduce">reduce</h3>
<p>reduce는 배열에 각 요소에 대해 주어진 함수를 실행하고, 결과값을 반환합니다. map이나 filter가 해당 배열내 모든 값을 순회하면서 새로운 배열을 만들어낸다면, reduce는 배열내의 값을 변경합니다. reduce라는 이름이 쓰인 이유는 보통 배열 내 값을 하나로 줄이기 때문에 붙여진 이름입니다. 내용처럼 배열 내 숫자들을 모두 더하거나, 빼거나 등등의 작용을 할 수 있습니다.
하지만 reduce메소드가 반환하는 값은 하나의 객체일수도, 배열일수도 있습니다.</p>
<pre><code>Array.reduce(function(acc, cur, index, array), initialValue);</code></pre><p>acc(accumulator)는 콜백함수의 반환값을 누적해 저장합니다. 콜백함수의 이전 반환값, 또는 콜백함수의 첫번째 호출이면서, 
initialValue를 제공한 경우에는initialValue의 값입니다.</p>
<p>cur(currentValue)는 순회하면서 사용되는 현재의 값입니다.</p>
<p>index는 현재의 값의 인덱스 값입니다.</p>
<p>array는 reduce를 호출한 배열을 나타냅니다.</p>
<p>initialValue는 callback함수에서 최초의 acc에서 사용 할 값을 나타냅니다. 빈 배열에서 initialValue없이 reduce를 사용하면 오류가 발생합니다.
또한 곱셈연산을 사용할때 1의 값을 넣어주지 않으면 정상적으로 작동하지 않는 경우도 발생합니다.</p>
<pre><code>const arr = [1,2,3,4,5]
const arr2 = arr.reduce(function(acc,cur){
  return acc + cur;
});

console.log(arr2) // 15</code></pre><p>위의 예시처럼 배열안에 모든 값을 더해 새로운 변수에 저장 할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] forEach]]></title>
            <link>https://velog.io/@lucky-korma/JS-forEach</link>
            <guid>https://velog.io/@lucky-korma/JS-forEach</guid>
            <pubDate>Fri, 12 Mar 2021 07:59:31 GMT</pubDate>
            <description><![CDATA[<h3 id="foreach">forEach</h3>
<p>forEach는 반복문인 for문처럼 해당 배열의 데이터를 하나씩 순회하는 기능입니다. 다른 map,filter,reduce와는 다르게, return문이 사용이 불가능하며, 새로운 변수에 새로운 배열을 선언하지 않습니다. 그래서 callback함수를 사용한 새로운 배열을 선언하려면 함수 밖에서 선언한 변수를 사용하여야 합니다.</p>
<p>사용 구문은 다음과 같습니다.</p>
<pre><code>Array.forEach(callbackfunction(value, index, array)</code></pre><p>value는 현재 데이터, index는 현재 데이터의 인덱스값, array는 사용되는 배열 본인을 나타냅니다.</p>
<pre><code>const = arr = [1,2,3,4,5,6]
let arr2 [];

arr.forEach(function(value){
  if(value % 2 === 0) arr2.push(value);
});

console.log(arr2); // [2,4,6]</code></pre><p>위의 예시처럼 return문을 사용할 수 없기때문에, 함수 밖에 변수를 선언한 후, 함수 내에서 조건에 맞는 데이터만 따로 push를 사용해 넣어주는 모습입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] filter]]></title>
            <link>https://velog.io/@lucky-korma/JS-filter</link>
            <guid>https://velog.io/@lucky-korma/JS-filter</guid>
            <pubDate>Fri, 12 Mar 2021 07:50:21 GMT</pubDate>
            <description><![CDATA[<h3 id="filter">Filter</h3>
<p>filter함수는 이름과 같이, callback함수에 조건에 해당하는 모든 요소를 찾아 새로운 배열에 넣어주는 기능입니다.</p>
<pre><code>array.filter(callbackfunction(value,index,array),this{
callback함수내용 return 조건;
});</code></pre><p>위의 구문으로 사용이 가능하며, value는 array내의 현재값이며, index는 현재값의 인덱스, array는 돌아가는 본인 배열을 나타냅니다. this는 callback함수내에서 사용되는 this값입니다.</p>
<pre><code>let arr = [1,2,3,4,5,6,7,8];
let arrFilter = arr.filter(function(value){
  return (value % 2 === 0);
});
console.log(arrFilter) // [2, 4, 6, 8]</code></pre><p>위의 예시처럼 사용이 가능합니다.</p>
<p>객체에서도 사용이 가능합니다.</p>
<pre><code>const cats = [
  { name : &#39;Lucky&#39; , age : 2},
  { name : &#39;Vanilla&#39;, age : 1},
  { name : &#39;Latte&#39;, age : 1},
  { name : &#39;midSummer&#39;, age : 1}
]
const cat = cats.filter(function(value){
  return (value.age&gt;1);
});

console.log(cat) = [{ name : &#39;lucky&#39; , age 2 }];</code></pre><p>해당 내용처럼 객체내의 키,데이터를 callback함수에 조건에 해당하는 데이터만 따로 저장이 가능합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] map]]></title>
            <link>https://velog.io/@lucky-korma/JS-mapfilterforEachreduce</link>
            <guid>https://velog.io/@lucky-korma/JS-mapfilterforEachreduce</guid>
            <pubDate>Fri, 12 Mar 2021 07:40:07 GMT</pubDate>
            <description><![CDATA[<h3 id="map">Map</h3>
<p>map함수는 callback함수를 실행한 결과를 가지고 새로운 배열을 만들때 사용됩니다.</p>
<pre><code>array.map(callbackfunction(value, index, array), this){
return 리턴된 해당 값들을 선언하는곳;
})</code></pre><p>위의 예제처럼 사용되며, value는 배열을 돌며 사용되는 현재 값이며, index는 현재값의 인덱스, array는 map함수가 사용되는 앞의 array본인입니다. 뒤의 this는 콜백함수내의 this에서 사용되는 값입니다.</p>
<pre><code>const data = [1,2,3,4,5,6]
const addData = data.map(function(value){
  return value = value + value;
});

console.log(addData) // [2,4,6,8,10,12]</code></pre><p>위의 예시처럼 사용되며, addData의 변수에 콜백함수를 적용한 배열이 새로 선언됩니다.
해당내용은 화살표함수를 사용해서 좀더 간단하게 선언 할 수 있습니다.</p>
<pre><code>const data = [1,2,3,4,5,6]
const addData = data.map(value =&gt; value+value);

console.log(addData) // [2,4,6,8,10,12]</code></pre><p>Map함수는 객체에서도 사용이 가능합니다.</p>
<pre><code>const cats = [
  { name : &#39;Lucky&#39; , age : 2},
  { name : &#39;Vanilla&#39;, age : 1},
  { name : &#39;Latte&#39;, age : 1},
  { name : &#39;midSummer&#39;, age : 1}
]

const cat = cats.map(function(value, index){
  let check = {}
  check.[value.name] = value.age;
  return check;
});

console.log(cat) 
/*** [
  { Lucky : 2 },
  { Vanilla : 1 },
  { Latte : 1 },
  { midSummer : 1 }
]</code></pre><p>위의 예시처럼 객체의 키값과 키에 해당하는 데이터를 따로 불러와 변경할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 원시 자료형, 참조 자료형의 차이]]></title>
            <link>https://velog.io/@lucky-korma/JS-%EC%9B%90%EC%8B%9C-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%B0%B8%EC%A1%B0-%EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@lucky-korma/JS-%EC%9B%90%EC%8B%9C-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%B0%B8%EC%A1%B0-%EC%9E%90%EB%A3%8C%ED%98%95%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Fri, 12 Mar 2021 07:20:17 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트에서 사용하는 데이터는 크게 원시자료형, 참조자료형 두가지로 구분할 수 있습니다.</p>
<p>먼저 원시자료형(primitive type)의 특징으로는,
객체가 아니면서, method를 가지지 않는 6가지 타입입니다.
string, number, bigint, boolean, undefined, symbol, (null)
원시자료형은 모두 하나의 데이터만을 가지고 있습니다.
배열이나 객체와 다르게, 하나의 변수에 하나의 데이터만 저장 할 수 있습니다.</p>
<pre><code>let primitive = 1,2,3; // 원시자료형은 3가지 정보를 저장 할 수 없어서 오류가 발생합니다.</code></pre><p>해당 내용처럼 원시자료형은 한가지를 넘어선 자료를 저장하려고하면, 오류로 저장이나, 선언이 되지 않습니다.
이유는 메모리에 용량이 제한되어있어, 변수 하나에 데이터를 하나만 넣을 수 있기 때문입니다.</p>
<p>참조 자료형의 경우 변수에 데이터를 할당하지 않고, 주소를 할당합니다. 이 주소 자체를 우리가 눈으로 볼 수 없기 때문에, 이해하기가 어렵습니다. 
참조자료형은 데이터중 원시자료형이 아닌 모든 데이터가 참조자료형입니다. 배열과, 객체, 함수가 대표적인 참조자료형입니다.
참조 자료형의 데이터 자체는 지금까지 배웠던 원시 자료형이 보관되는 데이터 보관함이 아닌 특별한 데이터 보관함에 저장됩니다. 
이 데이터가 위치한 곳(메모리 상 주소)을 가리키는 주소가 변수에 저장됩니다. 즉, 변수에는 특별한 데이터 보관함을 찾아갈 수 있는 주소가 담겨있고, 이 주소를 따라가보면 특별한 데이터 보관함을 찾을 수 있는데, 이 특별한 데이터 보관함에서는 자기 마음데로 사이즈를 늘렸다가 줄였다가 합니다. (&quot;동적(dynamic)으로 변한다&quot;라고 하기도 합니다.)
이처럼 데이터는 별도로 관리되고, 우리가 직접 다루는 변수에는 주소가 저장되기 때문에 reference type이라고 불립니다. 이런 특별한 데이터 보관함을 heap이라고도 부릅니다.
<img src="https://images.velog.io/images/lucky-korma/post/ea22db48-b2ff-4a65-9dc7-a17f9e6563b8/5hlJ5eHOk-1604321316118.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 객체의 기초적인 내용들]]></title>
            <link>https://velog.io/@lucky-korma/JS-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EA%B8%B0%EC%B4%88%EC%A0%81%EC%9D%B8-%EB%82%B4%EC%9A%A9%EB%93%A4</link>
            <guid>https://velog.io/@lucky-korma/JS-%EA%B0%9D%EC%B2%B4%EC%9D%98-%EA%B8%B0%EC%B4%88%EC%A0%81%EC%9D%B8-%EB%82%B4%EC%9A%A9%EB%93%A4</guid>
            <pubDate>Fri, 12 Mar 2021 05:46:06 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트에서는 처음 자바를 배웠을때의 객체의 내용이 조금 달라 따로 정리하려고 합니다.
Array처럼 데이터를 쉽게 저장하고, 읽어올 수 있게 정리하는 자료타입입니다.
배열과는 다르게, 한 데이터에 다양한 속성을 가지고 있고, 해당 속성마다 데이터가 조금씩 다를때 사용하면, 데이터를 효율적으로 관리할 수 있습니다.</p>
<pre><code>let obj = {}</code></pre><p>등으로 선언이 가능하며, 객체 내의 key갑과 value를 저장 할 수 있습니다.</p>
<pre><code>let obj = {};
obj.name: &#39;KimLucky&#39;
obj.job: &#39;Cute Cat&#39;
console.log(obj) -&gt;
{
name : &#39;kimLucky,
job : &#39;Cute Cat&#39;
}
console.log(obj.name) // &#39;KimLucky&#39;</code></pre><p>이런식으로 사용이 가능합니다.
해당 내용중 obj.name은 obj[&#39;name&#39;]으로도 사용이 가능합니다.</p>
<p>객내의 안에, key값의 value으로 배열이나, 또 다른 객체를 선언 할 수 있습니다.</p>
<p>배열처럼 length명령어를 사용하려면, 조금 다른식으로 접근해야 합니다.</p>
<pre><code>Object.keys(obj).length</code></pre><p>해당 명령어로 사용이 가능하며, 반복문을 사용할때 명령어를 기억하면, 어렵지 않게 사용이 가능합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] Array의 사용, 복사, 메소드, 이중배열등 배열에 대해]]></title>
            <link>https://velog.io/@lucky-korma/JS-Array%EC%9D%98-%EC%82%AC%EC%9A%A9-%EB%B3%B5%EC%82%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9D%B4%EC%A4%91%EB%B0%B0%EC%97%B4%EB%93%B1-%EB%B0%B0%EC%97%B4%EC%97%90-%EB%8C%80%ED%95%B4</link>
            <guid>https://velog.io/@lucky-korma/JS-Array%EC%9D%98-%EC%82%AC%EC%9A%A9-%EB%B3%B5%EC%82%AC-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%9D%B4%EC%A4%91%EB%B0%B0%EC%97%B4%EB%93%B1-%EB%B0%B0%EC%97%B4%EC%97%90-%EB%8C%80%ED%95%B4</guid>
            <pubDate>Fri, 12 Mar 2021 05:36:06 GMT</pubDate>
            <description><![CDATA[<p>Array,배열은 개발자라면 언제나 익숙하고 자주 접하게 됩니다.
코드스테이츠에 들어오기 전, JAVA위주로 공부한 저에게는 비슷하지만 몇가지 다른점들이 있어, 해당 내용을 복습하면서 정리하려고 합니다.</p>
<p>기본적으로 배열의 선언은</p>
<pre><code>let arr = [];
let arr = [1,2,3]
let arr = Array(length)
let arr = new Array(length)</code></pre><p>등의 명령어로 선언이 가능합니다.</p>
<p>Array에서 가장 많이 사용되는 메소드는 length이며,
Array.length를 입력시 해당 배열의 길이를 리턴해줍니다.
보통 반복문에서 많이 사용되며, 이중배열일 경우는 해당 인덱스를 입력시 안의 이중배열의 길이만 리턴이 가능합니다.</p>
<p>다른 map,forEach,reduce,filter등의 메소드는 따로 포스트에 정리하도록 하겠습니다.</p>
<p>가장 중요한 배열의 복사입니다.
제가 이 포스팅을 작성하는 의미이며, 얕은복사와 깊은복사에 대해 적으려고 합니다.
얕은복사는 해당 배열을 참조하며, 원본과 사본을 수정시 함께 수정되는 애로사항이 있습니다.</p>
<pre><code>let arr1 = [1,2,3,4]
let arr2 = arr1;
arr2[3] = 5
console.log(arr1) // [1,2,3,5]
console.log(arr2) // [1,2,3,5]</code></pre><p>이렇게 출력되며, 해당 내용을 참조만 하기때문에 원본과 사본 모두 동시에 변경됩니다.
얕은 복사를 피하기 위해서 사용하는 몇가지 방법이 있습니다.
slice명령어를 이용하거나, spread를 사용하면 됩니다.</p>
<pre><code>let arr1 = [1,2,3,4];
let arr2 = arr1.slice();
arr2[2] = 0;
console.log(arr1) // [1,2,3,4]
console.log(arr2) // [1,2,0,4]</code></pre><p>이렇게 출력되오며 해당내용은 slice()로 arr1의 배열의 모든 내용을 arr2로 복사해 새로운 배열을 만들어낸 결과입니다.</p>
<pre><code>let arr1 = [1,2,3,4];
let arr2 = [...arr1];
arr2[0] = 9;
console.log(arr1) // [1,2,3,4]
console.log(arr2) // [9,2,3,4]</code></pre><p>위의 내용은 spread용법을 사용해 배열을 깊은복사로 복사하는 방법입니다.</p>
<p>이중배열의 복사는 조금더 까다롭습니다
위와 같이 배열을 복사했을때 배열내 배열의 참조는 변경되지 않기때문에, 배열내 배열마다 따로 slice()나 spread용법을 사용해 변경해 주어야 합니다.</p>
<pre><code>let arr1 = [[1,2,3],[1,2,3,4,5],[1,2,3]];
let arr2 = new Array(arr1.length);
for(let i = 0; i &lt; arr2.length; i++) {
  arr2[i] = arr1[i].slice()
}</code></pre><p>위처럼 사용하거나,</p>
<pre><code>let arr2 = new Array(arr1.length);
for(let i = 0; i &lt; arr2.length; i++) {
  arr2[i] = [...arr[i]];
}</code></pre><p>위의 내용처럼 사용하여 깊은 복사가 가능합니다.
배열의 깊이에 따라 해당내용을 응용해 사용이 가능합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTML,CSS,JS 웹을 만드는 세가지 축]]></title>
            <link>https://velog.io/@lucky-korma/HTMLCSSJS-%EC%9B%B9%EC%9D%84-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%84%B8%EA%B0%80%EC%A7%80-%EC%B6%95</link>
            <guid>https://velog.io/@lucky-korma/HTMLCSSJS-%EC%9B%B9%EC%9D%84-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%84%B8%EA%B0%80%EC%A7%80-%EC%B6%95</guid>
            <pubDate>Fri, 12 Mar 2021 05:20:53 GMT</pubDate>
            <description><![CDATA[<p>HTML은 Markup, 구조를 표헌하는 언어라고 생각하면 됩니다.
HTML의 문법의 특징으로는 opening tag, closing tag가 있으며, 주로 </p>
<pre><code>&lt;div&gt; 내용을 입력하세요 &lt;/div&gt;</code></pre><p>와 같은 문법으로 사용할 수 있습니다.
또한 input type을 설정하여 다양한 종류의 input을 활용할 수 있고, id와 class를 지정하여 해당 내용을 구분해 활용 할 수 있습니다.</p>
<p>CSS는 쉽게말하면 HTML로 만들어진 구조를 꾸미는 스타일링 작업을 구현하는것이라고 생각하면 됩니다.
만들어진 구조를 적당한 위치에 배치하는것도 가능하며,
텍스트 강조나 마우스오버시 바뀌는 기능이나, 해당창의 display속성값들을 이용해 뒤에 나오는 JS에서 CSS의 속성을 바꾸어 더 다양한 기능을 구현 할 수 있습니다.
해당 설명만 본다면 CSS는 디자이너의 영역으로 생각 할 수 있지만, 간단한 작업은 개발자도 기본으로 알아야 하며, JS를 작성할때도 이벤트에 따라 CSS의 속성을 바꾸는 일이 많기때문에, 해당 내용을 모른다면, 스크립트를 작성하는데 많은 어려움이 발생합니다.</p>
<p>JS (Java Script)는 HTML로 만들어진 구조와 CSS로 스타일링된 페이지에 다양한 기능을 구현하는 스크립트입니다.
작성된 파일을 HTML에 불러와 적용이 가능하며,
마우스 클릭시 나오는 이벤트나, Input Text창에 입력된 메시지를 클릭으로 입력받아 작동하는 방법등 여러가지 기능을 구현하기 위해 필요한 과정입니다.
쉽게 생각하면 웹 사이트에서 아이디와 비밀번호를 받아 로그인하는 기능들을 구현하는데 사용된다고 생각하시면 됩니다.</p>
<p>CSS와 JS를 사용할때 HTML에서 구조를 만들때 사용된 Class와 Id로 해당 구역을 확인하여, 그 부분만 적용이 가능하며, 해당 내용들은 이후 포스팅에서 자세히 설명하겠습니다.</p>
]]></description>
        </item>
    </channel>
</rss>